我有以下域对象:
public class Department {
private long departmentId;
}
public class Manager {
private long managerId;
}
public class Project {
private ProjectId compositeId;
@ManyToOne
private Department department;
@ManyToOne
private Manager manager;
}
public class ProjectId {
private long departmentId;
private long managerId;
}
项目由复合键(departmentId,managerId)标识。问题是如何实现Project.setManager(..)或Project.setDepartment(..)?下面列出的实施是最佳做法吗?
public void setManager( Manager manager ) {
this.manager = manager;
this.compositeId.setManagerId( manager.getId() );
}
我的理解是每当设置属性时都需要更新compositeId。
更难和相关的问题是应该如何实现Project.setCompositeId(..)?项目将无法根据复合ID(长)更新物业经理或部门。在不更新属性的情况下覆盖compositeId会使Project处于不协调状态。
答案 0 :(得分:2)
我建议如下:
@Entity
@IdClass(ProjectId.class)
public class Project {
@Id @Column(name="DEPARTMENT_ID")
private long departmentId;
@Id @Column(name="MANAGER_ID")
private long managerId;
@ManyToOne
@PrimaryKeyJoinColumn(name="DEPARTMENT_ID", referencedColumnName="DPT_ID")
private Department department;
@ManyToOne
@PrimaryKeyJoinColumn(name="MANAGER_ID", referencedColumnName="MGR_ID")
private Manager manager;
...
}
中详细说明了这种映射
JPA 1.0要求所有
@Id
映射 是基本映射,所以如果你的ID来了 从一个外键列到一个 你是OneToOne
或ManyToOne
映射 还必须定义Basic
@Id
映射 对于外键列。原因 因为这部分是Id
必须的 是一个简单的身份和对象 缓存目的,并用于IdClass
或EntityManager
find()
API。因为您现在有两个映射 你必须使用相同的外键列 定义将写入哪一个 数据库(必须是基础 一),所以
OneToOne
或ManyToOne
必须定义外键 只读。这是通过完成的 设置JoinColumn
属性insertable
和updatable
为false,或 使用@PrimaryKeyJoinColumn
而不是@JoinColumn
。具有两个映射的副作用 对于同一列,就是你现在 必须保持两者同步。这是 通常通过设置完成
OneToOne
属性的方法也是 将Basic
属性值设置为 目标对象的id。这可以成为 如果目标非常复杂 对象的主键是aGeneratedValue
,在这种情况下你必须 确保目标对象的id具有 在关联两个对象之前已分配。(...)
示例ManyToOne id注释
... @Entity @IdClass(PhonePK.class) public class Phone { @Id @Column(name="OWNER_ID") private long ownerId; @Id private String type; @ManyToOne @PrimaryKeyJoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID") private Employee owner; ... public void setOwner(Employee owner) { this.owner = owner; this.ownerId = owner.getId(); } ... }