hibernate实体层设计

 

hibernate中支持3种类型的继承形式

-        Table per concrete class

表与子类中的一对一关系

-        Table per subclass

每个子类对应一张子表,并与主类共享主表

-         Table per class hierarchy

表与类的一对多关系

现在我们围绕这个实例,对hibernate中关于继承关系的3种映射类型进行讨论
-        Table per concrete class
在这个实例中,TItem有两个子类,分别是TBook和TDVD,所谓的表与子类中的一对一关系,也就是说每个子类对应一张数据库表,那么我们需要两个*.hbm.xml文件
         
这个和我们之前的设计很相似,不过大家也看出了吧..有点不现实..冗余太多了
- Table per subclass
从上面的设计我们看出冗余太对,那么我们自然就会想到把重复的字段提取出来,做为一张主表,TBook,TDVD做为他们的子表,通过ID进行关联
然后写POJO类,TItem,TBook,TDVD具体我就不多说了,
TBook和TDVD继承TItem的
主要说一下TItem.hbm.xml这个文件,我们虽然表有3张,但却只有一个映射文件
<hibernate-mapping>
         <class name="org.luna.hibernate.demo2.TItem" table="TITEM" schema="SCOTT">
             <id name="id" type="java.lang.String">
                 <column name="ID" length="32" />
                 <generator class="assigned" />
             </id>

             <property name="name" type="java.lang.String">
                 <column name="NAME" length="20" not-null="true" />
             </property>
             <property name="manufacturer" type="java.lang.String">
                 <column name="MANUFACTURER" length="20" />
             </property>

             <joined-subclass name="org.luna.hibernate.demo2.TBook" table="TBOOK">
              <key column="ID"></key>
              <property name="pageCount" type="java.lang.Integer" column="pagecount"></property>
             </joined-subclass>

             <joined-subclass name="org.luna.hibernate.demo2.TDVD" table="TDVD">
              <key column="ID"></key>
              <property name="regioncode" type="java.lang.String" column="regioncode"></property>
             </joined-subclass>

         </class>
</hibernate-mapping>
从上面的代码中我们看到了多了一个标签 joined-subclass ,这个标签表示关系, 他的 name 属性表示对应的哪个类, table 是哪张表,他下面有个 Key 的标签,这个表示他们是通过什么来进行关联的.而 Key 下的 column 表示他们是通过哪个字段来进行关联的,这里我们是ID,然后他下面就不多说了..大家一看就明白了.
然后我们进行操作,写一个 TItemOperate 的类,他下面有个 insert 方法
public void insert(TItem tItem){
       session.save(tItem);
       session.beginTransaction().commit();
       session.close();
}
然后我们再建个TestHibernate的类,来测试一下,这是 main 下的代码,
       TItemOperate to = new TItemOperate();
//        我们在这里试下插入一本书
//       TBook tBook = new TBook();
//       tBook.setId("first");
//       tBook.setName("Luna");
//       tBook.setManufacturer("shenzhen");
//       tBook.setPageCount(500);
//  
//       to.insert(tBook);
//        我们试下插入一张DVD
//       TDVD tDVD = new TDVD();
//       tDVD.setId("next");
//       tDVD.setName("火影228");
//       tDVD.setManufacturer("日本");
//       tDVD.setRegioncode("no");
//  
//       to.insert(tDVD);
我们能发现,他会自动关联,插入了主表后,子表一样能加进去,因为表删了,没能给大家看效果,有兴趣的人可以自己去试下.你会发现,主表和子表的ID名一样,共有信息他会保存的主表,子表的专有信息他会保存到子表去.
但现在又有个问题,这真的是唯一的吗?
此设计不是解决此类问题的唯一标准
-      Table per class hierarchy
我们来看看这张图
从这张表我们能看把TDVD和TBOOK表中的信息都加到这张表中,然后用 category 进行区分
我们第一行 category 的值是 1 , 表示 ,而他的 regioncode 的值为 null
我们第二行 category 的值为 2 , 表示 DVD , 而他的 pagecount 的值为 null
我们来看看在hibernate中是怎么实现的
还是来看看我们最关心的 TItem.hbm.xml 这个文件吧..
<hibernate-mapping>
        <class name="org.luna.hibernate.demo3.TItem" table="TITEM" schema="SCOTT">
             <id name="id" type="java.lang.String">
                <column name="ID" length="32" />
                <generator class="assigned" />
            </id>
      <discriminator column="category" type="java.lang.String"></discriminator>
  
      <property name="name" type="java.lang.String">
                <column name="NAME" length="20" not-null="true" />
            </property>
            <property name="manufacturer" type="java.lang.String">
                <column name="MANUFACTURER" length="20" not-null="true" />
            </property>

      <subclass name="org.luna.hibernate.demo3.TBook" discriminator-value="1">
      <property name="pageCount" type="int">
                <column name="PAGECOUNT" precision="22" scale="0" />
            </property>
      </subclass>
  
  
      <subclass name="org.luna.hibernate.demo3.TDVD" discriminator-value="2">
      <property name="regioncode" type="java.lang.String">
                <column name="REGIONCODE" length="2" />
            </property>
      </subclass>
  
  
        </class>
</hibernate-mapping>
这里我们用到了 discriminator (识别器) 这个标签,说也不好说.识别器字段包含标志值,用于告知持久化层应该为某个特定的行创建哪一个子类的实例. 详细的话请看 http://www.hibernate.org/hib_docs/reference/zh-cn/html/mapping.html
里面有很详细的介绍
subclass也不多说了,表示子类,他里面有个 discriminator-value ,用来区别不同子类的值

discriminator-value(辨别值) (可选 - 默认和类名一样):一个用于区分不同的子类的值,在多态行为时使用。

然后我们用上面那个 TItemOperate 这个类
public class TestDemo03 {
public static void main(String[] args) {
      TItemOperate to = new TItemOperate();
//      TBook tBook = new TBook();
//      tBook.setId("luna008");
//      tBook.setName("luna");
//      tBook.setManufacturer("深圳");
//      tBook.setPageCount(500);
  
//      to.insert(tBook);
  
      TDVD tDVD = new TDVD();
      tDVD.setId("LunaDVD");
      tDVD.setName("luna");
      tDVD.setManufacturer("深圳");
      tDVD.setRegioncode("12");
      to.insert(tDVD);
}
}
你会发现你得到数据和刚开始的那个效果一样.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值