我在使用复合主键的hibernate实体集时遇到了问题。
我们的应用程序中有一个概念“Target”。目标id应该是其他三个表(实体)主id的组合。目标也有一个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工作正常,它允许我每个role_id(员工)多个目标,只要应用程序和项目分类不同。
这是目标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;
}
}
这是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;
}
...
}
通过hibernate创建和存储目标是可行的,数据库中的一切看起来都很好。问题是,即使数据库允许每个员工存储多个目标,只要applicationperiod和projectclass不同,Hibernate也不会每个员工存储多个目标,无论applicationperiod和projectclass是否不同。我做错了什么?如何使Hibernate允许我为每个员工存储多个目标?
好的,我想出来了。问题似乎是TargetID类不能使用实体属性,相反,它应该使用long来指向相关实体的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;
}
}
员工实体,包含一组目标:
@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;
}
...
}
我有一个复合主键,其中一个键为空。实体中必须存在哪些注释,以便我可以使用此类JPA获取数据: 我尝试使用IdClass Annotation和EmbeddedId Annotation,但出现异常: 例如,使用了数据,但在实际项目中使用了类似的数据,因此无法用值替换null。
问题内容: 我有一个类似的问题,如下所示,但解决方案无法解决我的问题。 休眠复合主键包含复合外键,如何映射 我正在尝试加入2个表,每个表都有一个带有部分外键引用的复合主键。 在一个: 在BPK中: 上面的方法给我这个异常: 你能帮忙吗? 问题答案: 假设f1和F2唯一标识A并存在于APK中,则可以通过几种方式使用JPA 2.0的派生ID。最容易显示的是: 这里的关键点是B对A的引用控制了外键字段f
问题内容: 我有一个类似的问题,如下所示,但解决方案无法解决我的问题。 休眠复合主键包含复合外键,如何映射 我正在尝试加入2个表,每个表都有一个带有部分外键引用的复合主键。 在一个: 在BPK中: 上面的方法给我这个异常: 你能帮忙吗? 问题答案: 假设f1和F2唯一标识A并存在于APK中,则可以通过几种方式使用JPA 2.0的派生ID。最容易显示的是: 这里的关键点是B对A的引用控制了外键字段f
我有一个类似的问题如下,但解决方案没有解决我的问题。 hibernate复合主键包含复合外键,如何映射此 我试图连接2个表,每个表都有一个复合主键和部分外键引用。 你能帮忙吗?
问题内容: 我在这里搜索,但未找到任何类似的主题,因此我发布了一个新问题。 我正在使用现有数据库上的Hibernate。我们不允许更改表的结构和数据。该应用程序正在从数据库读取数据,并根据某种逻辑迁移到另一个数据存储。 现在的问题是关于复合PK映射。例如 表A具有复合PK。 表B也有一个复合PK,此复合PK的一部分是A的PK,此处也用作FK。 我尝试了几种方法,但都无济于事。谁能告诉一个有效的Hi
问题内容: 我正在设计一个数据库,该数据库将用于存储来自许多不同来源的数据。我存储的实例由原始来源分配了唯一的ID。我存储的每个实例都应包含有关其来源的信息,以及与此来源相关联的ID。 作为示例,请考虑说明该问题的下表: 请注意,尽管每个来源的唯一,但有可能在不同来源中找到相同的来源。 我对关系数据库有一个不错的了解,但是与专家甚至是经验丰富的用户都相去甚远。我在此设计中面临的问题是应该用作主键。