每个带有联合的具体类一张表
使用<union-subclass>继承策略
<hibernate-mapping package="cn.jbit.hibernate.entity2"> <class name="BillingDetails2" abstract="true"> <id name="id" column="BILLING_DETAILS_ID" type="integer"> <generator class="native"/> </id> <property name="owner"> <column name="OWNER" not-null="true"/> </property> <union-subclass name="CreditCard2" table="CREDIT_CARD"> <property name="number" column="CC_NUMBER" length="20" not-null="true"/> <property name="expMonth" column="EXP_MONTH" length="20" not-null="true"/> <property name="expYear" column="EXP_YEAR" length="20" not-null="true"/> </union-subclass> </class> </hibernate-mapping>你可能注意到了,这种策略的第一个好处是超类(或者接口)属性的共享声明。你不再非得给所有具体的类复制这些映射了——Hibernate会替你完成。记住,SQL模式仍然不知道继承;实际上,我们已经把两个不相关的表映射到了一个更富有表现力的类结构。
在JPA注解中,这个策略称作TABLE_PER_CLASS
@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public abstract class BillingDetails3 { @Id @GeneratedValue @Column(name = "BILLING_DETAILS_ID", nullable = false) private Integer id; @Column(name = "OWNER", nullable = false) private String owner; }数据库标识符和它的映射必须出现在超类中。
@Entity @Table(name = "CREDIT_CARD2") public class CreditCard3 extends BillingDetails3 { @Column(name = "CC_NUMBER", nullable = false) private String number; @Column(name = "EXP_MONTH", nullable = false) private String expMonth; @Column(name = "EXP_YEAR", nullable = false) private String expYear; }注意,TABLE_PER_CLASS在JPA标准中被指定为可选,因此并非所有的JPA实现都可以支持它。实际的实现也是由供应商决定的——在Hibernate中,它相当于XML文件中的<union-subclass>映射。
同样的映射在JPA XML描述符中看起来像这样:
<entity class="cn.jbit.hibernate.entity2.BillingDetails2" access="FIELD"> <inheritance strategy="TABLE_PER_CLASS"/> <attributes> <id name="id"> <column name="BILLING_DETAILS_ID" nullable="false"/> <generated-value strategy="AUTO"/> </id> <basic name="owner"> <column name="OWNER" nullable="false"/> </basic> </attributes> </entity> <entity class="cn.jbit.hibernate.entity2.CreditCard2" access="FIELD"> <attributes> <basic name="number"> <column name="CC_NUMBER" nullable="false"/> </basic> <basic name="expMonth"> <column name="EXP_MONTH" nullable="false"/> </basic> <basic name="expYear"> <column name="EXP_YEAR" nullable="false"/> </basic> </attributes> </entity>如果超类是具体的,就需要另外一张表来存放这个类的实例。必须再次强调,数据库表之间仍然没有关系,除了它们共享一些类似的列之外。如果检验多态查询,这个映射策略的好处会更加明显。