Entity的继承以及泛型Dao(一)

Entity的继承以及泛型Dao(一)

一、两张类似的表与两个类似的实体类

现在我有一个betspider数据库,里面放着我自己的爬虫爬来的足球赔率,以bs_odds_1x2(胜负平赔率)、bs_odds_handicap(让球赔率)这两张表作为例子,他们在数据库中的表结构是这样的:

屏幕快照 2016-03-11 下午8.36.19

屏幕快照 2016-03-11 下午8.36.45

首先不考虑实体类的继承,这两张表对应着两个独立的实体类:(请暂时忽略下面实体类属性的数据类型与mysql的表字段类型的不完全匹配 =。=#)

但实际上我的betspider库里有好多odss_xxx表,我可不想为每种赔率都写一大段的实体类定义。

二、提取父类

从上面的描述我们可以看到,Odds1x2与OddsHandicap这两种赔率其实很类似,他们共同的属性包括id、关联的比赛id、更新时间、博彩数据供应商id、有效性字段。

那么从面向对象的角度来看的话,我们可以把他们的共同属性提取出来,作为一个父类叫做Odds。

但是如何将类之间的继承关系映射到数据库的表中呢,而且先说明的是,我希望映射到数据库后,orm框架为我们自动生成的数据库表依然如上面描述的那样,只有bs_odds_1x2与bs_odds_handicap表,而不存在odds表。

那么,来看一下jpa规范中提供的实体类继承策略。

三、javax.persistence.Inheritance

jpa的@Inheritance注解规定了三种策略:JOINED、SINGLE_TABLE、TABLE_PER_CLASS

3.1 JOINED

使用这种映射策略,继承链中的每个实体类都各自映射到数据库中独立的表,子类表只拥有自身的属性,从父类继承的属性都放在父类表中,同时在父类中定义的主键、将会被所有子类共享作为主键+外键。下面是例子:

将hibernate的hibernate.hbm2ddl.auto属性配置为create-drop。运行后看控制台的输出:

可以看到,hibernate为我们创建了三个数据库:Odds(因为我没有给Odds实体类配置表名,所以默认表名为类名)、bs_odds_1x2、bs_odds_handicap。同时用Odds的id作为外键将两个子类表与父类表关联起来。

3.2 SINGLE_TABLE

使用这种映射策略的话,实体类的继承链中,所有的类都会被叠加到一起映射到数据库的唯一的一张表中,该表名以父类对应的表名为准。另外,这张表中,会额外增加一个字段DTYPE,用来判断一行数据是属于哪一个子类

Odds1x2与OddsHandicap两个子类的定义不变。运行后检查hibernate的输出:

屏幕快照 2016-03-11 下午11.25.15

3.3 TABLE_PER_CLASS

使用这种策略,会对继承链中的每个类创建对应的表,父类的表中只有父类属性,子类的表中则包括了自身属性以及从父类继承过来的属性,而且子类表与父类表不在有任何关系。

但是使用这种策略有一个弊端,就是不能再将主键的生成策略设置为数据库自动生成(AUTO/IDENTITY/SEQUENCE),而只能使用GenerationType.TABLE来自动生成主键或者不使用自动生成主键。

这样,我们将会得到三张无任何关系的表:

四、父类非实体类

三种介绍的例子,我们使用的父类都是实体类,即都用@Entity注解过。如果不使用@Entity注解父类的话,结果可想而知,实体的子类虽然依然可以继承父类属性,但这些属性将无法被映射到数据库表字段中。但从我现在的应用场景考虑,我就是需要将Odds作为非实体类,因为我不需要在数据库中有一张odds的父类表,但我又希望父类的属性能被写入到子类的表中。为了满足这种需求,jpa提供了@MappedSuperclass注解。

对于的hibernate输出为:

来看一下自动创建出来的数据库表:

屏幕快照 2016-03-12 上午12.44.32 屏幕快照 2016-03-12 上午12.44.41

跟本文开头想要的一模一样(当然除了数据类型呀,因为在类定义中没有匹配好)

 

参考:

https://www.ibm.com/developerworks/cn/java/j-lo-hibernatejpa/

One thought on “Entity的继承以及泛型Dao(一)

发表评论

电子邮件地址不会被公开。 必填项已用*标注