【问题标题】:Hibernate composite primary key using @Embedded and @Id使用@Embedded 和@Id 的休眠复合主键
【发布时间】:2014-03-27 02:23:11
【问题描述】:

我想知道 hibernate 是否支持使用字段和组件类型的复合主键。所以我有一个@Embeddable 组件类型,我想将它用作主键,同时将另一列用作复合主键。

所以我的表“DEPT_HISTORY”有复合主键(GROUP_DEPT、DEPTID、EFFDT)。我将 GROUP_DEPT 和 DEPTID 作为 @Embeddable 组件类型映射到 Department 类。

@Embeddable public class Department implements Serializable {

    private static final long serialVersionUID = 1L;

    private String departmentGroup;

    private String departmentId;

    public String getDepartmentGroup() {
        return departmentGroup;
    }

    public void setDepartmentGroup(String departmentGroup) {
        this.departmentGroup = departmentGroup;
    }

    public Department withDepartmentGroup(String departmentGroup) {
        setDepartmentGroup(departmentGroup);
        return this;
    }

    public String getDepartmentId() {
        return departmentId;
    }

    public void setDepartmentId(String departmentId) {
        this.departmentId = departmentId;
    }

    public Department withDepartmentId(String departmentId) {
        setDepartmentId(departmentId);
        return this;
    }

    @Override
    public String toString() {
        return Objects.toStringHelper(this).add("departmentGroup", getDepartmentGroup())
                .add("departmentId", getDepartmentId()).toString();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Department)) {
            return false;
        }
        Department other = (Department) obj;

        return Objects.equal(getDepartmentGroup(), other.getDepartmentGroup())
                && Objects.equal(getDepartmentId(), other.getDepartmentId());

    }

    @Override
    public int hashCode() {
        return Objects.hashCode(getDepartmentGroup(), getDepartmentId());
    }

}

我正在使用 GROUP_DEPT、上面的 DEPTID 和下面的 EFFDT 映射复合主键,如下所示。休眠是否支持这一点。我有类似的类,它可以工作,但由于某种原因在这个类上失败,原因是:org.hibernate.AnnotationException:com.blah.blah.component.Department 在用作@EmbeddedId 时不能有@Id 属性:com .blah.blah.entity.DepartmentHistory.department

@Entity @Table(name = "dept_history") public class DepartmentHistory implements Serializable {

    private static final long serialVersionUID = 1L;
    private static final String DATETIME_FORMAT = "MM-dd-yyyy HH:mm:ss ZZ";
    protected static final DateTimeFormatter DATE_FORMAT = DateTimeFormat.forPattern(DATETIME_FORMAT);

    @Id
    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "departmentGroup", column = @Column(name = "GROUP_DEPT", nullable = false)),
            @AttributeOverride(name = "departmentId", column = @Column(name = "DEPTID", nullable = false)) })
    private Department department;

    @Id
    @Column(name = "EFFDT", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Calendar effectiveDate;

    @Column(name = "DESCR", nullable = false)
    private String description;

    @Column(name = "MANAGER_ID", nullable = false)
    private String managerId;

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(final Department department) {
        this.department = department;
    }

    public DepartmentHistory withDepartment(final Department department) {
        setDepartment(department);
        return this;
    }

    public Calendar getEffectiveDate() {
        return effectiveDate;
    }

    public void setEffectiveDate(final Calendar effectiveDate) {
        this.effectiveDate = effectiveDate;
    }

    public DepartmentHistory withEffectiveDate(final Calendar effectiveDate) {
        setEffectiveDate(effectiveDate);
        return this;
    }

    public DateTime readEffectiveDateAsDateTime() {
        return calendarToDateTime(effectiveDate);
    }

    public void writeEffectiveDateAsDateTime(final DateTime effectiveDate) {
        this.effectiveDate = dateTimeToCalendar(effectiveDate);
    }

    public DepartmentHistory withEffectiveDateAsDateTime(final DateTime effectiveDate) {
        writeEffectiveDateAsDateTime(effectiveDate);
        return this;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    public DepartmentHistory withDescription(final String description) {
        setDescription(description);
        return this;
    }

    public String getManagerId() {
        return managerId;
    }

    public void setManagerId(final String managerId) {
        this.managerId = managerId;
    }

    public DepartmentHistory withManagerId(final String managerId) {
        setManagerId(managerId);
        return this;
    }

    @Override
    public String toString() {
        return Objects.toStringHelper(this).add("department", getDepartment())
                .add("effectiveDate", DATE_FORMAT.print(readEffectiveDateAsDateTime()))
                .add("description", getDescription()).add("managerId", getManagerId()).toString();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof DepartmentHistory)) {
            return false;
        }
        DepartmentHistory other = (DepartmentHistory) obj;

        return Objects.equal(getDepartment(), other.getDepartment())
                && Objects.equal(getEffectiveDate(), other.getEffectiveDate());

    }

    @Override
    public int hashCode() {
        return Objects.hashCode(getDepartment(), getEffectiveDate());
    }

}

我可以使用@Embedded 和字段上的@Id 属性将@Embeddable 和另一个字段组合成一个复合主键。我不想将 (GROUP_DEPT, DEPTID, EFFDT) 设为 @EmbeddedId,因为这样的组件类型没有意义,而且我不想创建一个在我的域中没有任何意义的类只是用作复合主键。仅包含 (GROUP_DEPT, DEPTID) 的组件部门作为部门是有意义的。非常感谢。

【问题讨论】:

    标签: java hibernate jpa hibernate-mapping


    【解决方案1】:

    根据规范,当您使用复合键时,您应该使用 @EmbeddedId 或 @IdClass。

    如果依赖实体类还有主键属性 对应于父主键的那些,或者如果父 具有复合主键,必须使用嵌入的 id 或 id 类 指定依赖实体的主键。它不是 父实体和从属实体都必须使用嵌入式 ids 或两者都使用 id 类来表示复合主键 父级有一个复合键。

    问题是:

    我正在使用上面的 GROUP_DEPT、DEPTID 映射复合主键 和 EFFDT 如下。 hibernate 支持吗?

    是的,hibernate 支持,但你应该使用@EmbeddedId,我知道这需要创建一个新类来处理密钥,但据我所知需要完成。

    【讨论】:

    • 感谢您的回复。我在这里没有实现任何继承,所以没有父实体和依赖实体。我有类似的课程,例如。位置和位置历史,其中组件类型位置为 (GROUP_LOCATION, LOCATION) 和 EFFDT 作为实体 location_history 中的字段。我以完全相同的方式映射它,它工作得很好。只是这个特定的类似乎不起作用,我不知道为什么。
    • 只是一个问题,当您尝试使用 EntityManager 查找方法根据键检索对象时,您的模型有效?
    • 当 spring 尝试实例化 bean 时,此模型失败并出现上述异常。但是,当我执行 Location location = new Location().withLocationGroup("TEST").withLocationId("100"); 时,我有一个类似的位置模型可以正常工作List locationHistory = locationHistoryDao.getLocationHistoryById(location);在 dao 中,我使用标准 api 来获取结果
    猜你喜欢
    • 2012-03-21
    • 1970-01-01
    • 1970-01-01
    • 2015-12-14
    • 1970-01-01
    • 2017-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多