2

我在使用具有复合主键的休眠实体集时遇到问题。

我们的应用程序中有一个概念“目标”。目标 id 应该是其他三个表(实体)主 id 的组合。Target 也有一个 int 标记。员工应该有一个目标集合。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;

此 SQL 工作正常,只要 applicationperiodid 和 projectclassid 不同,它就允许我为每个 role_id (Employee) 设置多个目标。

这是 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;
    }
}

这是目标类

@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;
    }
}

这是员工类,我想在其中为每个员工存储一组目标。

@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;
    }

    ...

}

通过 hibernate 创建和存储目标可以正常工作,并且数据库中的所有内容看起来都不错。问题是,即使数据库允许每个员工存储多个目标,只要 applicationperiod 和 projectclass 不同,Hibernate 也不会为每个员工存储多个 target,无论 applicationperiod 和 projectclass 是否不同。我究竟做错了什么?如何让 Hibernate 让我为每位员工存储多个目标?

4

1 回答 1

5

好的,我想通了。问题似乎在于 TargetID 类不能使用 Entity 属性,而是应该使用 Longs 来指向相关实体的 id。然后,您可以使用 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`);

复合 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;
    }
}

目标实体:

@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;
    }
}

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;
    }    
    ...
}
于 2012-11-22T02:27:55.607 回答