继承
为了在RDBMS中支持面向对象继承,JPA定义了若干映射策略,具体如下
1.各类继承结构使用单个表(Single table per class hierarchy)
在类继承结构不含有太多属性时,开发者可以考虑使用这一策略。否则,表的字段非常多。如果使用这一映射策略,应用应该能够接受存在NULL值的列。
2.各个子类使用单独的表(Separate table per subclass)
必须连接表才能获得子类的所有属性。尽管这一策略支持多态,但如果类继承结构很深,这一策略的表现会很差。类继承结构越深(子类越多),则需要完成更多的连接操作。最终,将严重影响到整个系统的运行性能。性能逊于Single table
3.各具体实体类使用单个表(Single table per concrete entity class)
这一策略并不支持多态,但EJB3.0规范对此策略并不做要求。
实体继承应遵循的若干通用原则:
1.实体可以继承非实体类
2.非实体类可以继承实体类
3.实体可以是抽象类
4.实体类可以继承其他实体类
为了实现实体类继承非实体类,需要在非实体类前使用@MappedSuperclass注释。
如果实体继承了未使用@MappedSuperclass注释的非实体类,JPA也支持这一场景。但是,这时的父类中的任何属性都不会持久化到RDBMS中。
关系
1:1,1:N,M:1,M:N,关系存在双向性,就有8中组合,因为双向的1:N关系与双向的M:1关系是相同的,因此只存在7种。
双向1:1同单向1:1关系生成的表结构完全一致。这告诉我们一个事实:底层数据库表结构并不总是与类中定义的相吻合。
CascadeType取值:PERSIST、MERGE、REMOVE、REFRESH、ALL。
1:1和M:1,FetchType默认值是EAGER。
1:N和M:N,FetchType默认值是LAZY。
单向1:1,主类@OneToOne(cascade={CascadeType.PERSIST}),附类没有annotation
双向1:1,除主类外有如上注释外,附类要添加主类属性,且在Getter前加@OneToOne(mappedBy="主表中的附表属性")。
在实际应用对象模型中,1:N关系更为常见。
单向1:N,
通常我们需要通过RDBMS中的外键实现1:N关系。
在单向1:N关系中,持久化提供者能够自动生成中间表。
附类没有annotation
双向1:N,
在双向1:N关系中不需要使用中间表。
主类@OneToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER/FetchType.LAZY,mappedBy="附类中的主类属性"),
附类添加主类属性,且在Getter前加@ManyToOne。
单向M:1比较简单
主类@ManyToOne(cascade={CascadeType.ALL}),附类没有。
单向M:N
在处理M:N关系时,需要在RDBMS中引用中间表。
主类@ManyToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER/FetchType.LAZY)
@JoinTable(name="A_B"),附类没有。
双向M:N
主类不变,
附类添加主类属性,并在相应的Getter前加注释@ManyToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER/FetchType.LAZY,mappedBy="主类中的附类属性")