2012-11-21 2 views
2

J'ai des problèmes avec les ensembles d'entités Hibernate avec des clés primaires composites.Clés primaires composites Hibernate

Nous avons un concept "cible" dans notre application. L'ID cible doit être la combinaison de trois autres tables (entités) ID principaux. Target a également un tag int. Les employés devraient avoir une collection de cibles. Le SQL ressemble à ceci:

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; 

Ce SQL fonctionne très bien, et cela me permet de aussi longtemps que le applicationperiodid et projectclassid sont différents plus d'une cible par role_id (employé).

C'est la classe 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; 
    } 
} 

Ceci est la classe cible

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

C'est la classe des employés, où je veux stocker un ensemble d'objectifs pour chaque employé. La création et le stockage de cibles via hibernate fonctionne, et tout dans la base de données semble bon. Le problème est que, même si la base de données permet de stocker plus d'une cible par employé tant que les classes applicationperiod et projectclass sont différentes, Hibernate ne stocke pas plus d'une cible par employé, indépendamment de la différence entre applicationperiod et projectclass. Qu'est-ce que je fais mal? Comment puis-je faire en sorte que Hibernate puisse stocker plus d'une cible par employé?

Répondre

5

OK, je l'ai compris. Le problème, semble-t-il, était que la classe TargetID ne pouvait pas utiliser les attributs Entity, elle devrait plutôt utiliser des Longs pour pointer vers les ids pour les entités en question. Vous utilisez ensuite SQL pour définir les contraintes correctes et les connexions entre les colonnes dans la base de données.

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`); 

Le composé ID classe:

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

L'entité cible:

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

L'entité employé, qui contient un ensemble de cibles:

@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; 
    }  
    ... 
} 
Questions connexes