Professional Hibernate第5章读书笔记

      这一章介绍的内容很多,不像前面几章,我可以每天一章 ,这章我就放慢了脚步,用了3天的时间看完,因为这章确实也比较的重要。

     这章的题目是Creating Persistent Classes。Hibernate里面核心问题之一。为了能把oop中的所有特性完全的映射到关系数据库里面,hibernate用了很多的方法。从这一章开始就是一一的开始讲解。

   在持久化的时候要注意以下几点:

  • Hibernate只持久那些在mapping documet里面出现的属性,所以你就可以在类里面自由定义临时的属性,这些属性在Hibernate从数据库里面load对象的时候将消失。
  • 所有要被持久的属性都要声明为private,有setter和getter,遵从javabean规范。setter和getter不必声明为public,你可以声明为protected甚至private,因为Hibernate会利用反射机制来找到他们。
  • 所有的要持久化的类都必须定义id属性,方便Hibernate和数据库定义主键
  • 所有要被持久化的类要定义一个默认的构造函数。

下面就来说下映射一个类时的要做的具体的事情:

  1. 首先你要建立一个mapping document,Hibernate用这个xml文件来定义如何将Java class映射到数据库的表里面,mapping document的命名一般就是PersistedClassName.hbm.xml。
  2. mapping document有一个root element-<hibernate-mapping>,里面有一个package属性值得注意一下,定义了package属性,这个映射文件将以定义的目录来找要持久的类。比如:<hibernate-mapping package="example.code">.这样下面的class element的name属性将以example.code为根目录去查找所需要的类。
  3. class tag就描述了要被持久类。比较重要的属性是name--类的路径,table--数据库里面对应的表。如:<class name="example.products.Book" table="books">
  4. id tag是class的subelement,定义了这个类的id属性,前面已经说了每个要持久的类都必须有个id属性。这个tag比较重要的属性是name--id的名字,unsaved-value--当一个对象被实例化时id属性的值,Hibernate用这个值来判断这个对象是应该save(insert into..)还是update(update table...)。id element还有个<generator>subelement,这个element比较重要的属性是class--生成id所用到的方案。
  5. <property>描述了Java class里面要被持久的属性,比较重要的属性是name--属性的名字,not-null--是否可以为null,column--对应到表里面的列,type--数据的类型。当type没有指明的时候,Hibernate会用到反射机制来确定数据的类型,当column没指明的时候,将把此属性持久到表里面和name相同的列。<property>还可以有一个subelement就是column,功能和属性column差不多,只不过可以通过<column sql-type="">来定义sql数据类型。

下面帖出一个mapping dcument例子来:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="example.products.Book" table="books">
<id name="id"
type="int"
unsaved-value="0">
<generator class="hilo"/>
</id>
<property name="title"/>
<property name="author"/>
<property name="isbn"
not-null="true"/>
<property name="pages"
type="integer"
column="pagecount" />
<property name="copyright"/>
<property name="cost">
<column name="cost"
sql-type="NUMERIC(12,2)"/>
</property>
</class>
</hibernate-mapping>

比较基本的类的映射文件可以通过这些来描述持久化,当然还有一些其他特殊的东西会出现,比如持久一个2进制数据等等。。。。

持久一个2进制属性:只要javabean class的类的相关属性定义为Bolb数据类型,然后映射文件里这样定义这个属性:<property name="data"
type="binary">
<column name="data"
sql-type="blob"/>
</property>  type--为binary,sql-type为blob。

持久一个串行化属性:大部分情况下,持久一个object,你要指明这个object所属类的属性,添加到配置文件里面。Hibernate取出数据库里面存放的object是这样完成的,首先实例化一个新的object,然后把数据库一行里存放的属性数据取出放到新实例化的object对应的属性里。还有另外一个办法,就是用Serializable接口。我们可以这样定义一个<property>来实现他:

<property name="ivalue" type="serializable" >
<column name="value" sql-type="blob"/>
</property>

ivalue属性的type改成serializable,而不是java class里面声明的type,这样Hibernate会串行化这个属性(也就是这个object),sql-type也要相应的改成blob。

注意,这种方法只能用在Java application中。

映射一个Data/Calendar属性:

private Date setupdate;

<property name="setupdate">
    <column name="setup" sql-type="Date"/>
</property>

映射一个只读类:

<class name="example.util.Support" table="support" mutable="false">

映射一个version/timestamp属性:

private int version;

<version name="version"
                 column="version"
                 type="integer"
                 unsaved-value="undefined"/>和id element差不多。

private Timestamp timestamp;

<timestamp name="timestamp"
column="stamp"
unsaved-value="undefined"/>

好了,现在要来说下非常重要的一部分了。。。。。

持久有继承关系的类:

持久有继承关系的类有以下3种方案:

  • Table-per-class hierarchy
  • Table-per-subclass
  • Table-per-concrete class

第一种方案是一个继承链上的所有类被持久化到一个表里面。这样就要从继承链最低层的类开始,将所有出现过的属性都放到一个table里面,然后用一个<discriminator>元素来定义一个列用来区分是哪一个类被持久化的。

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping package="example.products">
<classname="CD" table="cd" discriminator-value="cd">
<id name="id" type="integer" unsaved-value="0">
<generator class="hilo"/>
</id>
<discriminator column="cd_type" type= "string"/>
<property name="title"/>
<property name="artist"/>
<property name="purchasedate" type="date"/>
<property name="cost" type="double"/>
<subclass name="SpecialEditionCD" discriminator-value="SpecialEditionCD">
<property name="newfeatures" type="string"/>
</subclass>
<subclass name="InternationalCD" discriminator-value="InternationalCD">
<property name="languages"/>
<property name="region"/>
</subclass>
</class>
</hibernate-mapping>

注意红色的部分,<class/subclass .....discriminator-value="">定义了这个类的标识值,<discriminator column....>定义了表里面分辨是哪个类的列名,这个列里面的值则是<class/subclass .....discriminator-value="">里面定义的。

 

第2中方案是每个类一张表,但是父类的所有要持久的属性将被映射到对应的表里面,而子类表里面只有自己特殊的属性。

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping package="example.products">
<class name="CD" table="cd">
<id name="id" type="integer" unsaved-value="0">
         <generator class="hilo"/>
</id>
<property name="title"/>
<property name="artist"/>
<property name="purchasedate" type="date"/>
<property name="cost" type="double"/>
<joined-subclass name="SpecialEditionCD" table="secd">
<key column="id"/>
<property name="newfeatures" type="string"/>
</joined-subclass>
<joined-subclass name="InternationalCD" table="icd">
<key column="id"/>
<property name="languages"/>
<property name="region"/></joined-subclass>
</class>
</hibernate-mapping>

<key>tag指明了父类的哪个属性用来指明父子关系。<key>tag还可以用来定义外键。

第3种方案是不管是父类还是子类,都建一个完整的表,第2种方案是父类的表里面有子类的部分属性信息,而第3种方案则是哪个类被持久了,所有的属性都在所对应的表里面存储。

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping package="example.products">


<class name="CD" table="cd" discriminator-value="cd">
<id name="id" type="integer" unsaved-value="0">
     <generator class="hilo"/>
</id>
<property name="title"/>
<property name="artist"/>
<property name="purchasedate" type="date"/>
<property name="cost" type="double"/>
</class>
<class name="SpecialEditionCD" table="secd">
<id name="id" type="integer" unsaved-value="0">
     <generator class="hilo"/>
</id>
<property name="title"/>
<property name="artist"/>
<property name="purchasedate" type="date"/>
<property name="cost" type="double"/>
<property name="newfeatures" type="string"/></class>
<class name="InternationalCD" table="icd">
<id name="id"type="integer" unsaved-value="0">
        <generator class="hilo"/>
</id>
<property name="title"/>
<property name="artist"/>
<property name="purchasedate" type="date"/>
<property name="cost" type="double"/>
<property name="languages"/>
<property name="region"/>
</class>
</hibernate-mapping>

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值