Java 持久化/多对一
外观
< Java 持久化
Java 中的 多对一
关系是指源对象有一个属性引用另一个对象,即目标对象。例如典型的 Java 案例,一个对象持有对另一个对象的引用。多对一
关系可以是单向的。但是,目标对象通常具有指向源对象的逆关系。这将是目标对象中的 一对多
关系规范。Java 和 JPA 中的所有关系都是单向的,也就是说,如果源对象引用目标对象,则不能保证目标对象也与源对象有关系。这与关系数据库不同,在关系数据库中,关系通过外键和查询来定义,以便始终存在反向查询。
在 JPA 中,多对一
关系通过 @ManyToOne
注解或 <many-to-one>
元素指定。@ManyToOne
注解通常伴随 @JoinColumn
注解。@JoinColumn
注解指定了关系如何映射到数据库(在数据库中表示)。@JoinColumn
定义了源对象中用于查找(连接)目标对象的外部键列名称(@JoinColumn(name = "...")
)。
如果在目标对象中指定了反向 一对多
关系,那么目标对象中的 @OneToMany
注解必须包含 mappedBy
属性来定义这个反向关系。
JPA 还定义了 一对一
关系,它类似于 多对一
关系,除了反向关系(如果定义了的话)是一个 一对一
关系。JPA 中 一对一
和 多对一
关系的主要区别在于,多对一
始终包含从源对象表的外部键到目标对象表的外部键,而 一对一
关系的外部键可能位于源对象表或目标对象表中。
员工(表)
员工 ID | 姓名 | 姓氏 | 薪资 | 经理 ID |
1 | 鲍勃 | 韦 | 50000 | 2 |
2 | 莎拉 | 史密斯 | 75000 | 空 |
电话(表)
ID | 类型 | 区号 | 电话号码 | 所有者 ID |
1 | 家庭 | 613 | 792-0000 | 1 |
2 | 工作 | 613 | 896-1234 | 1 |
3 | 工作 | 416 | 123-4444 | 2 |
@Entity
public class Phone {
@Id
private long id;
...
// Specifies the PHONE table does not contain an owner column, but
// an OWNER_ID column with a foreign key. And creates a join to
// lazily fetch the owner
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="OWNER_ID")
private Employee owner;
...
}
// Specification of the reverse OneToMany relationship in Employee
@Entity
public class Employee {
@Id
private long emp_id;
...
// The 'mappedBy = "owner"' attribute specifies that
// the 'private Employee owner;' field in Phone owns the
// relationship (i.e. contains the foreign key for the query to
// find all phones for an employee.)
@OneToMany(mappedBy = "owner")
private List<Phone> phones;
...
<entity name="Phone" class="org.acme.Phone" access="FIELD">
<attributes>
<id name="id"/>
<many-to-one name="owner" fetch="LAZY">
<join-column name="OWNER_ID"/>
</many-to-one>
</attributes>
</entity>
- 参见 通过一对一关系生成主键.
- 如果你在两个不同的映射中使用相同的字段,通常需要使用
insertable, updatable = false
使其中一个字段变为只读。 - 参见 目标外键、主键连接列、级联主键.
- 这通常是因为你在
一对一
关系中错误地映射了外键。- 参见 目标外键、主键连接列、级联主键.
- 如果你的 JPA 提供程序不支持引用完整性,或者无法解析双向约束,也会发生这种情况。在这种情况下,你可能需要移除约束,或者使用
EntityManager
flush()
来确保对象写入的顺序。
- 确保你设置了对象的
一对一
值,如果一对一
是双向一对多
关系的一部分,确保你在将对象添加到一对多
中时设置了对象的一对一
,JPA 不会为你维护双向关系。 - 还要检查你是否正确定义了
JoinColumn
,确保你没有设置insertable, updateable = false
或使用PrimaryKeyJoinColumn
。
在复杂的数据模型中,如果外键/JoinColumn
与其他 多对一
或 Basic
映射共享,则可能需要使用目标外键或只读 JoinColumn
来映射 多对一
。