hibernate的映射处理

      最近闲着没事,就整理了hibernate的一些东西,供大家参考。
一、一对一关联在hibernate中的实现
一对一关联有两种实现方法:主键关联和外键关联。
主键关联是使两个表共享一个主键。比如,有表A和B,表A的主键为aid,那么表B

就把A的主键aid同时作为主键和外键使用。
A的映射文件:
<class name="A" table="A">
        <id name="aId" type="java.lang.String">
            <column name="aid"  length="10" />
            <generator class="guid"></generator>
        </id>
        <property name="aname" type="java.lang.String">
            <column name="aname" length="10" />
        </property>
        <one-to-one name="b" class="B" cascade="all"></one-to-one>
    </class>
cascade="all"表示级联操作,当cascade="false"时表示不进行级联操作。
<one-to-one name="b" class="B" cascade="all"></one-to-one>中的name="b"

在类A对应了属性b(类型为B);
B的映射文件:
<class name="B" table="B" >
<id name="bId" type="java.lang.String">
   <column name="bid" />
   <!-- 使用foreign的主键生成方式,引用A对象的主键作为B对象的主键 -->
     <generator class="foreign">
     <!-- 此a对应下面one-to-one的name名称一样 -->
     <param name="property">a</param>
    </generator>
</id>
<property name="bname" type="java.lang.String">
<column name="bname" length="20" />
</property>
<one-to-one name="a" class="A" constrained="true"></one-to-one>
</class>
<one-to-one name="a" class="A" constrained="true"></one-to-one>中的

name="a"在类B中对应了属性a(类型为A)
constrained="true"指明了B引用了A的主键作为外键,且是强制的一一对应关系。
使用外键关联,两个表都有各自的主键,比如,有表A和B,表A的主键为aid,那么表B就把A的主键aid同时作为外键使用。这种关联方法也可以用于一对多的关联。
A的映射文件:
<class name="A" table="A">
        <id name="aId" type="java.lang.String">
            <column name="aid" />
            <generator class="native"></generator>
        </id>
        <property name="aname" type="java.lang.String">
            <column name="aname" length="10" />
        </property>
        <one-to-one name="b" class="B" cascade="all" property-

ref="a"></one-to-one>
    </class>
A的映射文件中的property-ref="a"是必须的,它跟B的映射文件中name="a"的<many-to-one>对应。
B的映射文件:
<class name="B" table="B" >
<id name="bId" type="java.lang.String">
   <column name="bid"  length="10" />
     <generator class="native"></generator>
</id>
<property name="bname" type="java.lang.String">
<column name="bname" length="20" />
</property>
<many-to-one name="a" class="A" unique="true" column="aid"/>
</class>

B的映射文件中的<many-to-one name="a" class="A" unique="true"

column="aid"/>指定了B的一个外键aid,unique="true"为外键aid生成一个唯一的约束,并使有一对一的关联关系。

对于一对一的检索策略,一般使用预先抓取,当另一端比较少使用时,可以使用延迟加载。
A.hbm.xml的<one-to-one>节点的fetch属性,A.hbm.xml的<one-to-one>节点的constrained属性,B.hbm.xml的<class>节点的lazy属性,不同的配置对应了不同的检索策略:
预先:无,无,无
预先:join,false,任意
立即:select,任意,任意
延迟:任意,true,true

 

二、一对多关联在hibernate的单向关联实现
一对多单向关联,它存在了一定的缺陷。
在hibernate中,在“一”的一端使用集合来实现对应关系,把“一”的一端作为控制方,而“多”的一端作为被控制方,“多”的一端不需要任何特殊的配置。被控制方并不知道控制方是谁。例如,表A是“一”的一端,表B是“多”的一端。
A的映射文件:
<class name="A" table="a" >
        <id name="aId" type="java.lang.Integer">
            <column name="aid" />
            <generator class="native"></generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name" length="10" />
        </property>
        <set name="bs" order-by="bid" cascade="all" fetch="join">
         <key column="aid" />
         <one-to-many class="B"></one-to-many>
        </set>
    </class>
order-by="bid"指定了排列顺序
<set ...></set>在类A中对应了属性bs(类型为HashSet<B>)
<one-to-many class="B"></one-to-many>指定了“多”的一端<key column="aid" />指定了“多”一端的外键。
B的映射文件:
<class name="B" table="b" >
        <id name="bId" type="java.lang.Integer">
            <column name="bid" />
            <generator class="native"></generator>
        </id>
        <property name="aId" type="java.lang.Integer">
            <column name="aid" />
        </property>
</class>
当A进行级联操作时,hibernate就会执行大量的sql语句,大大地影响了性能(可以在hibernate.cfg.xml设置<property

name="hibernate.jdbc.batch_size">30</property>实现批量更新,这个值一般取5~30)。如果把映射文件A中的<key column="aid" />设为<key column="aid" not-null="true" />则在级联删除时会抛出异常,因为在删除表B的记录之前会把aid设为NULL。

一对多关联的检索策略,优先考虑延迟加载,不同的<set/>的属性fetch,lazy的值,对于不同的检索策略
延迟:select,true
立即:select,false
预先:join,任意

 

三、一对多(多对一)关联在hibernate的双向关联实现
一对多(多对一)双向关联,在两端都知道各自的对方,解决了单向关联的缺陷。
一对多(多对一)双向关联,一般把“多”的一端作为控制方,如果把“一”的一端作为控制方的话,当加载“一”的一端的一条记录时就会加载“多”的一端相关的所有记录,这样就会影响性能。
例如,表A是“一”的一端,表B是“多”的一端。
A的映射文件:
<class name="A" table="a" >
        <id name="aId" type="java.lang.Integer">
            <column name="aid" />
            <generator class="native"></generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name" length="10" />
        </property>
        <set name="bs" order-by="bid" cascade="all" lazy="true"

inverse="true">
         <key column="aid" />
         <one-to-many class="B"></one-to-many>
        </set>
    </class>
inverse="true",标识了被控制方一端,inverse="false"的一方为控制方,负责维护关联关系。
<set name="bs" ...></set>在类A中对应了属性bs(类型为java.util.HashSet<B>)
B的映射文件:
<class name="B" table="B" >
<id name="bId" type="java.lang.String">
   <column name="bid" />
     <generator class="native"></generator>
</id>
<property name="bname" type="java.lang.String">
<column name="bname" length="20" />
</property>
<many-to-one name="a" class="A" column="aid" cascade="none"/>
</class>
<many-to-one name="a" class="A" column="aid" cascade="none"/>指定了外键aid,name="a"对应了类B中的属性a(类型为A)inverse的默认值为false。

 

四、多对一关联在hibernate的单向关联实现
多对一单向关联。在hibernate中,在“多”的一端使用集合来实现对应关系,把“多”的一端作为控制方,而“一”的一端作为被控制方,“一”的一端不需要任何特殊的配置。被控制方并不知道控制方是谁。例如,表A是“一”的一端,表B是“多”的一端。
A的映射文件:
<class name="A" table="a" lazy="false">
        <id name="aId" type="java.lang.Integer">
            <column name="aid" />
            <generator class="native"></generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name" length="10" />
        </property>
    </class>

B的映射文件:
<class name="B" table="b" >
        <id name="bId" type="java.lang.Integer">
            <column name="bid" />
            <generator class="native"></generator>
        </id>
        <many-to-one name="a" class="A" >
            <key column name="aid" />
        </property>
</class>
<many-to-one name="a" class="A" >对应了在类B的属性a(类型为A)可见,在“一”的一端相应的类A,并没有集合属性,类A不能获取“多”的一端对应的记录,这是多对一单向关联的特点。

对于多对一关联的检索策略,和一对一关联一样,也是首先考虑预先抓取,如果“一”的一端不常用,就用延迟加载检索策略。
B.hbm.xml的<many-to-one>节点的fetch属性,B.hbm.xml的<many-to-one>节点的lazy属性,A.hbm.xml的<class>节点的lazy属性,不同的配置对应不同的策略:
预先:join,任意,false
预先:无,无,false
延迟:任意,proxy,true
立即:任意,false,任意
立即:select,任意,false

 

五、多对多关联在hibernate的实现
如果两个表是多对多的关系,就需要一个中间表来实现多对多的对应关系。多对多关系是双向的。
<class name="A" table="a" >
        <id name="aId" type="java.lang.Integer">
            <column name="aid" />
            <generator class="native"></generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name" length="10" />
        </property>
        <set name="bs" table="a_b" cascade="save_update"

inverse="false" lazy="true">
         <key column="aid" />
         <many-to-many class="B" column="bid"></many-to-many>
        </set>
    </class>
<set name="bs" ...></set>在类A中对应了属性bs(类型为HashSet<B>)
<key column="aid" />指定了在表a_b中的字段aid为表A的主键aid
<many-to-many class="B" column="bid"></many-to-many>指定了另一端

B的映射文件:
<class name="B" table="B" >
<id name="bId" type="java.lang.String">
   <column name="bid" />
     <generator class="native"></generator>
</id>
<property name="bname" type="java.lang.String">
<column name="bname" length="20" />
</property>
<set name="as" table="a_b" cascade="save_update" fetch="join"

lazy="true">
         <key column="bid" />
         <many-to-many class="A" column="aid"></many-to-many>
        </set>
</class>
<set name="as" ...></set>在类B中对应了属性as(类型为HashSet<A>)

多对多关联的检索策略,优先考虑延迟加载,不同的<set/>的属性fetch,lazy的值,对于不同的检索策略
延迟:select,true
立即:select,false
预先:join,任意

 

六、集合映射
有Map,集合中的每个元素都包好一对关键字和值对象,集合中的关键字不能重复;Set,集合中的每个元素都不会重复,可以是一个null对象,加入Set的元素都必须重新定义equals和hashCode方法,以便元素进行排序;List,是有序的排列

集合,允许元素重复,可以通过索引访问元素;Bag也是集合,允许元素重复,是无序的;idbag在bag在基础上添加了collection-id,是hibernate可以直接操作要更新的数据,提高效率。

每个集合映射值类型的配置都有相同之处:
<xxx name="" table=""><key column=""/><element column="" type=""/></xxx>

 

对于映射实体类型的配置:
bag和idbag没有映射实体类型;
Map和List有一个<index column="" type=""/>节点,Map的index节点是指定Map的key,List的index节点是维护排序的,正因为Map和List需要index节点,在设置inverse="true"时,保存集合中对象时,无法设置index的值,所以Map和List无法使用inverse="true"来实现的“多”端作为控制方,这样会影响性能;

 

集合的排列:
数据库读取时排列:在每个映射配置上加order-by属性,list不支持该属性;
读取后进行内存排列:使用sort属性,只有Map和set支持该属性。

 

值类型没有自己的生命周期,它依赖于附属的实体,随着实体的消亡而消亡;而实体类型作为一个独立的实体存在,有自己的生命周期。使用值类型不可以实现延迟加载会影响性能,而实体类型可以实现。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值