简体   繁体   English

休眠复合主键

[英]Hibernate composite primary keys

Im having trouble with hibernate sets of entities with composite primary keys. 我在使用复合主键的实体休眠集中遇到麻烦。

We have a concept "Target" in our app. 我们的应用程序中有一个“目标”概念。 Target id should be the combination of three other tables (entities) primary ids. 目标ID应该是其他三个表(实体)主要ID的组合。 Target also has an int taget. Target也有一个int标签。 Employees should have a collection of targets. 员工应有一系列目标。 The SQL looks like this: SQL看起来像这样:

CREATE TABLE IF NOT EXISTS `target` (
  `role_id` bigint(20) NOT NULL,
  `ApplicationPeriod_id` bigint(20) NOT NULL,
  `project_class_id` bigint(20) NOT NULL,
  `target` int(11) NOT NULL,
  PRIMARY KEY (`role_id`,`ApplicationPeriod_id`,`project_class_id`),
  KEY `fk_role_id` (`role_id`),
  KEY `fk_ApplicationPeriod_id` (`ApplicationPeriod_id`),
  KEY `fk_project_class_id` (`project_class_id`),
  KEY `FKCB7E71918717386C` (`project_class_id`),
  KEY `FKCB7E7191BEC322C1` (`ApplicationPeriod_id`),
  KEY `FKCB7E71917B617197` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

This SQL works fine, and it allows me to more than one target per role_id (Employee) as long as the applicationperiodid and projectclassid are different. 此SQL可以正常工作,并且只要applicationperiodid和projectclassid不同,它就允许我每个role_id(员工)有多个目标。

This is the targetID class 这是targetID类别

@Embeddable
public class TargetId implements Serializable {

    @ManyToOne
    private Employee employee;

    @ManyToOne
    private ApplicationPeriod applicationPeriod;

    @ManyToOne
    private ProjectClass projectClass;


    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

    public ApplicationPeriod getApplicationPeriod() {
        return applicationPeriod;
    }

    public void setApplicationPeriod(ApplicationPeriod applicationPeriod) {
        this.applicationPeriod = applicationPeriod;
    }

    public ProjectClass getProjectClass() {
        return projectClass;
    }

    public void setProjectClass(ProjectClass projectClass) {
        this.projectClass = projectClass;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof TargetId)) return false;

        TargetId that = (TargetId) o;

        if (applicationPeriod != null ? !applicationPeriod.equals(that.applicationPeriod) : that.applicationPeriod != null)
            return false;
        if (employee != null ? !employee.equals(that.employee) : that.employee != null) return false;
        if (projectClass != null ? !projectClass.equals(that.projectClass) : that.projectClass != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = employee != null ? employee.hashCode() : 0;
        result = 31 * result + (applicationPeriod != null ? applicationPeriod.hashCode() : 0);
        result = 31 * result + (projectClass != null ? projectClass.hashCode() : 0);
        return result;
    }
}

This is the target class 这是目标阶层

@Entity
@Table(name = "target")
@AssociationOverrides({
        @AssociationOverride(name = "targetId.employee",
            joinColumns = @JoinColumn(name = "role_id")),
        @AssociationOverride(name = "targetId.applicationPeriod",
            joinColumns = @JoinColumn(name = "ApplicationPeriod_id")),
        @AssociationOverride(name = "targetId.projectClass",
                joinColumns = @JoinColumn(name = "project_class_id"))
})
public class Target implements Serializable {

    @EmbeddedId
    private TargetId targetId;

    private int target;

    public TargetId getTargetId() {
        return targetId;
    }

    public void setTargetId(TargetId targetId) {
        this.targetId = targetId;
    }

    public int getTarget() {
        return target;
    }

    public void setTarget(int target) {
        this.target = target;
    }

    public Target() {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Target)) return false;

        Target target = (Target) o;

        if (this.target != target.target) return false;
        if (targetId != null ? !targetId.equals(target.targetId) : target.targetId != null)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = targetId != null ? targetId.hashCode() : 0;
        result = 31 * result + target;
        return result;
    }
}

This is the employee class, in which I want to store a set of targets for each employee. 这是员工类,在其中我想为每个员工存储一组目标。

@Entity
@Cacheable(true)
@Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) //Hibernate specific
public class Employee {

    ...

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "targetId.employee", cascade=CascadeType.ALL, orphanRemoval=true)
    private Set<Target> targets = new HashSet<Target>();

    public Set<Target> getTargets() {
        return targets;
    }

    public void setTargets(Set<Target> targets) {
        this.targets = targets;
    }

    ...

}

Creating and storing targets via hibernate works, and everything in the database looks good. 通过休眠工作创建和存储目标,数据库中的所有内容看起来都很不错。 The problem is that, even thought the database allows storing more than one target per employee as long as the applicationperiod and projectclass are different, Hibernate wont store more than one target per employee regardless of whether the applicationperiod and projectclass are different. 问题是,即使认为数据库允许每个员工存储一个以上的目标,只要应用程序周期和项目类不同,Hibernate也不会为每个员工存储多个目标,而不管应用程序周期和项目类是否不同。 What am I doing wrong? 我究竟做错了什么? How can I make Hibernate let me store more than one target per employee? 如何让Hibernate让我为每个员工存储多个目标?

OK, I figured it out. 好,我知道了。 The problem, it seems, was that the TargetID class cant use Entity attributes, rather, it should use Longs to point to ids for the entities in question. 看来问题在于TargetID类不能使用Entity属性,而应该使用Longs指向所涉及实体的ID。 You then use SQL to set the correct constraints and connections between columns in the DB. 然后,您可以使用SQL来设置数据库中各列之间的正确约束和连接。

SQL: SQL:

CREATE TABLE IF NOT EXISTS `target` (
  `applicationPeriodId` bigint(20) NOT NULL,
  `employeeId` bigint(20) NOT NULL,
  `projectClassId` bigint(20) NOT NULL,
  `target` int(11) NOT NULL,
  PRIMARY KEY (`applicationPeriodId`,`employeeId`,`projectClassId`),
  KEY `FKCB7E71913353DC5C` (`employeeId`),
  KEY `FKCB7E7191A520201E` (`projectClassId`),
  KEY `FKCB7E7191790761A4` (`applicationPeriodId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Constraints for table `target`
--
ALTER TABLE `target`
  ADD CONSTRAINT `FKCB7E7191790761A4` FOREIGN KEY (`applicationPeriodId`) REFERENCES `ApplicationPeriod` (`id`),
  ADD CONSTRAINT `FKCB7E71913353DC5C` FOREIGN KEY (`employeeId`) REFERENCES `role` (`id`),
  ADD CONSTRAINT `FKCB7E7191A520201E` FOREIGN KEY (`projectClassId`) REFERENCES `project_class` (`id`);

The compound ID class: 复合ID类别:

@Embeddable
public class TargetId implements Serializable {

    @Basic
    private Long employeeId;

    @Basic
    private Long applicationPeriodId;

    @Basic
    private Long projectClassId;

    public Long getEmployeeId() {
        return employeeId;
    }

    public void setEmployeeId(Long employeeId) {
        this.employeeId = employeeId;
    }

    public Long getApplicationPeriodId() {
        return applicationPeriodId;
    }

    public void setApplicationPeriodId(Long applicationPeriodId) {
        this.applicationPeriodId = applicationPeriodId;
    }

    public Long getProjectClassId() {
        return projectClassId;
    }

    public void setProjectClassId(Long projectClassId) {
        this.projectClassId = projectClassId;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof TargetId)) return false;

        TargetId targetId = (TargetId) o;

        if (applicationPeriodId != null ? !applicationPeriodId.equals(targetId.applicationPeriodId) : targetId.applicationPeriodId != null)
            return false;
        if (employeeId != null ? !employeeId.equals(targetId.employeeId) : targetId.employeeId != null) return false;
        if (projectClassId != null ? !projectClassId.equals(targetId.projectClassId) : targetId.projectClassId != null)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = employeeId != null ? employeeId.hashCode() : 0;
        result = 31 * result + (applicationPeriodId != null ? applicationPeriodId.hashCode() : 0);
        result = 31 * result + (projectClassId != null ? projectClassId.hashCode() : 0);
        return result;
    }
}

The Target entity: 目标实体:

@Entity
@Table(name = "target")
@AssociationOverrides({
        @AssociationOverride(name = "targetId.employeeId",
            joinColumns = @JoinColumn(name = "role_id")),
        @AssociationOverride(name = "targetId.applicationPeriodId",
            joinColumns = @JoinColumn(name = "ApplicationPeriod_id")),
        @AssociationOverride(name = "targetId.projectClassId",
                joinColumns = @JoinColumn(name = "project_class_id"))
})
public class Target implements Serializable {

    @EmbeddedId
    private TargetId targetId;

    private int target;

    public TargetId getTargetId() {
        return targetId;
    }

    public void setTargetId(TargetId targetId) {
        this.targetId = targetId;
    }

    public int getTarget() {
        return target;
    }

    public void setTarget(int target) {
        this.target = target;
    }

    public Target() {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Target)) return false;

        Target target = (Target) o;

        if (this.target != target.target) return false;
        if (targetId != null ? !targetId.equals(target.targetId) : target.targetId != null)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = targetId != null ? targetId.hashCode() : 0;
        result = 31 * result + target;
        return result;
    }
}

The Employee entity, which contains a Set of Targets: Employee实体,其中包含一组目标:

@Entity
@Cacheable(true)
@Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) //Hibernate specific
public class Employee extends ProjectTeamMember {
    ...
    public Set<Language> getLanguages() {
        return languages;
    }

    public void setLanguages(Set<Language> languages) {
        this.languages = languages;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "targetId.employeeId", cascade=CascadeType.ALL, orphanRemoval=true)
    private Set<Target> targets = new HashSet<Target>();

    public Set<Target> getTargets() {
        return targets;
    }

    public void setTargets(Set<Target> targets) {
        this.targets = targets;
    }    
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM