2012-11-21 228 views
2

我有複雜主鍵的hibernate組實體有問題。休眠複合主鍵

我們在應用程序中有一個「目標」的概念。目標ID應該是三個其他表(實體)主要ID的組合。 Target也有一個int taget。員工應該有一組目標。該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工作得很好,並且它可以讓我每ROLE_ID(員工)以上的目標,只要applicationperiodid和projectclassid是不同的。

這是目標ID類

@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將不會爲每個員工存儲多個目標,無論applicationperiod和projectclass是否不同。我究竟做錯了什麼?我如何讓Hibernate讓我爲每個員工存儲多個目標?

回答

5

好的,我想通了。問題似乎是,TargetID類不能使用實體屬性,相反,它應該使用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; 
    }  
    ... 
}