JPA @OneToOne
、@ManyToOne
、@OneToMany
和@ManyToMany
几个注解提供用以定义实体类之间的关系。
OneToOne关系
OneToOne 表示一对一的关系,先来看 OneToOne 的属性:
@OneToOne
- targetEntity属性表示默认关联的实体类型,默认为当前标注的实体类,绝大数据情况下不需要进行设置。
- cascade属性表示级联操作策略:
- 不定义, 则对关系表不会产生任何影响
- CascadeType.PERSIST: 级联新建
- CascadeType.REMOVE: 级联删除
- CascadeType.REFRESH: 级联刷新,即重新同步到数据库中状态,会覆盖掉已经修改但是还没保存的实体类属性
- CascadeType.MERGE: 级联更新
- CascadeType.ALL: 表示选择全部四项
- fetch属性表示实体的加载方式,有LAZY和EAGER两种取值,默认值为EAGER
- optional属性表示关联的实体是否能够存在null值,默认为true,表示可以存在null值
关于fetch属性,所有@XXXToOne,默认值为EAGER,所有@XXXToMany,默认值为LAZY。
@JoinColumn
OneToOne 注释属性自动映射的字段名按照如下方式命名:
关联表的名称 + "_" + 关联表主键的字段名
如果对应的字段名是其他名字,则可以通过@JoinColumn来定义外键关联的字段名称。
- name:表示字段名
- referencedColumnName: 使用的外键名
- unique:是否设置为唯一key
双向 @OneToOne 关联
通过属性mappedBy
标明,设置了mappedBy属性的关系标注(各种@XXXToXX),表明当前类是关系的被维护方,而另外一个类则是关系维护方,你可以这样理解:
- 关系维护方对应的是定义外键约束的数据库表
- 关系被维护方对应于外键所在的数据库表
最后需要注意的一个问题是,关系维护方才能够操作两者的关系。
看两段代码:
- 对于操作 1:由于cascade级联操作,将会向Customer和 Portrait 表插入数据,但是不会设置两者之间的关系,即Portrait表的 customer_id 字段值为空,因为Customer类是关系被维护方
- 对于操作 2:由于cascade级联操作,两个表都会插入数据,而且 customer_id 的值得到正确设置
ManyToOne关系
@ManyToOne的属性选项与@OneToOne是类似的:
- targetEntity属性表示默认关联的实体类型,默认为当前标注的实体类。
- cascade属性表示级联操作策略:
- 不定义, 则对关系表不会产生任何影响
- CascadeType.PERSIST: 级联新建
- CascadeType.REMOVE: 级联删除
- CascadeType.REFRESH: 级联刷新
- CascadeType.MERGE: 级联更新
- CascadeType.ALL: 表示选择全部四项
- fetch属性表示实体的加载方式,有LAZY和EAGER两种取值。
- optional属性表示关联的实体是否能够存在null值,默认为true,表示可以存在null值。如果为false,则要同时配合使用@JoinColumn标注。
ManyToMany关系
直接上代码示例,不多讲。
自定义查询
Spring Data 内建的查询构造机制可能是最有特色的一个地方。
一个例子:
所有支持的有:
更多的spring-data相关的可以在spring-data 官方文档查看。