3.2 Hibernate-Inheritance
hibernate应用中,继承的用途或目的主要有两点:(摘自:https://www.cnblogs.com/hvicen/p/6337871.html)
组件化:把重复性的代码抽取成组件,以便重用和维护。hibernate应用中,一些重复的字段,重复的映射配置,就需要抽取成组件。
多态性:类的多态性是指下层业务所需一个父类对象,而上层业务根据所需的父类对象,传递一个子类对象。hibernate应用中,下层业务操作父类对象进行持久操作,如增删改查,上层业务则传递一个子类对象。
所以,在应用hibernate的继承时,需要明确设计所需,即究竟是组件化需求,还是多态性需求。
@MappedSuperclass:组件化需求的继承注解。虽然它可以应用于类的多态性业务中,但它不能应用于hibernate持久操作的多态性业务中。
@Inheritance:多态性需求的继承注解。虽然它可以达到组件化的目的,但它要比@MappedSuperclass多负出一些代价。
i.使用@MappedSuperclass
如果父类是抽象的,则意味着父类不能使用 @Entity 作为注解。
就可以把父类设置为【映射的父类】,此时父类不会生成表。也不能创建父类来进行保存,必须用子类的实例进行保存。1、父类(此时Account相当于抽象类,可添加Abstract使Account成为抽象类)
2、子类
测试结果:
遇到错误:
(1)
原因:
@MappedSuperclass和@Entity不能同时使用,也就是说如果要使用@MappedSuperclass,该类就无法进行持久化。
ii.使用@Inheritance继承的三种方式
1.Single table——所有的类、子类都放在一个表里面,通过【Discriminator】来识别哪个子类。Discriminator就是一个【列】。
好处:查询一个表即可,性能比较好。
缺点:子类很多、不同的属性很多,会造成表里面有很多的列。
(1)父类:
(2)子类:
测试结果:
2.Joined table——父类通用在放在一个表,子类特殊的放在各自的表里面。
比较常见、常用。
好处:不会造成表里面列过多,并且非常清楚每个记录对应哪个对象。
缺点:在看子类的记录的时候,需要根据外键查询父类里面的记录,才能得到完整的记录。需要连表查询,性能比较差。
(1)父类:
(2)子类:
测试结果:
3.Table per class——每个类一个表。
不需要鉴别器(Discriminator),每个类对应不同的表。每个表里面,都会包含父类的属性。
好处:如果数据量大的时候,这种继承可以避免一个表里面的数据量特别大。
缺点:如果要按照父类查询所有的记录(包括子类),需要连表(union)。实现多态查询性能比较差。
(1)父类:
(2)子类:
测试结果:
注意:不能使用IDENTITY在父类声明主键生成器,测试的时候发现使用uui2、AUTO是可以的。
否则出现异常如下: