传智播客--hibernate关系映射和性能优化(徐培成)

今天学习到了 hibernate 中的关键地方了,对象之间的关系和映射文件的配置和编写.Hibernate的学习主要就是学习映射文件.映射文件是 Java 对象和关系型数据库之间的桥梁.通过配置文件对 Java 对象进行配置就是要映射出表与表之间的关系.听懂很容易,要想用好就不是那么容易的事情了.好好总结一下今天学习到的知识吧.

1.一对多
<set name=“orders”
        cascade=“save-update”>
      <key column=“CUSTOMER_ID” />
      <one-to-many class=“..Order” />
</set>
属性注释:
name:设定待映射持久化类的属性名。
cascade:设定级联操作的程度。
key 子属性:设定与所关联的持久化类对应的标的外键。
one-to-many子属性:设定所关联的持久化类。
总结:
在一对多的时候,属性声明成Set还是List呢?
Set是不容许有重复,插入元素无序.
List是容许有重复,插入元素有序.
用List有重复元素,在插入的时候有插入数据重复提示.所以,要声明成Set.
使用一对多的时候,要慎重,效率很低.
通常在定义集合属性时,直接初始化为一个实现类的实例。 private Set orders = new HashSet(); 可避免空指针异常.
在映射一对多的双向关联关系时,应该在one方把inverse属性设为true,这可以提高性能。
在建立两个对象的关联时,应该同时修改关联两端的相应属性:
   Customer.getOrders().add(order);
   Order.setCustomer(customer);
这样才会使程序更加健壮,提高业务逻辑层的独立性,使业务逻辑层的程序代码不受Hibernate实现类的影响。同理,当删除双向关联的关系时,也应该修 改关联两端的对象的相应属性:
Customer.getOrders().remove(order);
Order.setCustomer(null);

2.多对一
<class name="Order" table="hib_orders" lazy="false">
    <id name="id" column="id" type="integer">
        <generator class="identity" />
    </id>
    <property name="orderNo" column="orderno" type="string" length="15" />
    <property name="price" column="price" type="float" />
    <!-- 映射多对一关联关系 -->
    <many-to-one name="customer" column="cid" class="Customer" cascade="save-update" />
</class>
总结:
就的一对多,从另外一个角度看. 这个关系是经常用到的.
属性中不用private Department depart;这个而用private int pepartid;也是可以的,但这就不能发挥Hibernate的优势了
在维护关系上,常是用这个多的一端来维护,这样和数据库交换的少,可以大大的提高系统的性能.
这里会有一个问题,注意使用数据的位置,涉及到了懒加载的问题.
通过Hibernate.initialize(emp.getDepart());来解决这个问题.这里是强制它查询数据库,给对象进行初始化.

3.一对一
一对一分两种情况
1)外键:多对一的特例,将不能重复设置成真.
<!-- 影射一对一外键关联用many-to-one进行模拟,增加唯一性约束 -->
<many-to-one name="addr" column="aid" class="AddrFk" unique="true" />
<one-to-one name="user" property-ref="addr"/>
2)主键
<!-- 影射一对一主键关联 -->
<one-to-one name="addr" class="AddrPk" />
<class name="AddrPk" table="hib_addrpks" lazy="false">
    <id name="id" column="id" type="integer">
        <generator class="foreign">
            <param name="property">user</param>
        </generator>
    </id>
    <property name="province" column="province" type="string" length="20" />
    <property name="city" column="city" type="string" length="20" />
   
    <one-to-one name="user" class="UserPk" constrained="true"/>
</class>

4.多对多
<!-- 影射多对多关联 -->
<set name="teas" table="hib_tea_stu_links" lazy="false" inverse="true">
    <key column="sid" />
    <many-to-many class="Tea" column="tid" />
</set>
<!-- 影射多对多关联 -->
<set name="stus" table="hib_tea_stu_links" lazy="false">
    <key column="tid" />
    <many-to-many class="Stu" column="sid" />
</set>
总结:
多对多的时候,会产生一个中间表.用来维护表之间的关联关系.
并要明确的指定中间表的名字.

5.session
session的缓存:当session的save()方法持久化一个对象时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象 仍然处于生命周期中。当试图load()对象时,会判断缓存中是否存在该对象,有则返回。
缓存的作用:
尽量减少访问数据库的次数,提高系统的效率.
保证缓存中的对象与数据库中的相关记录保持同步。
当session加载了customer对象后,会为customer对象的值类型的属性复制一份快照。当清理缓存时,通过比较对象的当前属性和快照,来 判断对象的那些属性发生了变化。
Session 清理缓存执行sql语句的顺序:
按照应用程序调用save()方法的先后顺序,执行所有的对实体进行插入的insert语句。
所有对实体进行更新的update语句。
所有对实体进行删除的delete语句。
所有对集合元素进行删除、更新或插入的sql语句。
执行所有对集合进行插入的insert语句。
按照应用程序调用delete()方法的先后执行。

6.inverse:
让一的一端, 集合端,放弃更新,放弃维护关系.默认是关闭的.
<set>元素的inverse属性
Hibernate会自动清理缓存中的所有持久化对象,按照持久化对象的改变来同步更新数据库,因此执行了上述的两条更新语句。重复执行多余的sql语句 会影响java性能,解决这也问题的办法是把<set>元素的inverse属性设为true,该属性的默认值是false。
在映射一对多的双向关联关系时,应该在one 方把inverse属性设为true,这可以提高性能。
在建立两个对象的关联时,应该同时修改关联两端的相应属性:
   Customer.getOrders().add(order);
   Order.setCustomer(customer);
这样才会使程序更加健壮,提高业务逻辑层的独立性,使业务逻辑层的程序代码不受Hibernate实现类的影响。同理,当删除双向关联的关系时,也应该修 改关联两端的对象的相应属性:
Customer.getOrders().remove(order);
Order.setCustomer(null);

7.cascade
这个属性要小心设置,否则因为错误的设置对系统数据的破换性很大,不容易恢复.
Customer customer = (Customer) s.load(Customer.class,new Long(2));
Session.delete(customer);
tx.commit();
如果cascade属性取默认值none,不会自动删除和customer关联的其他持久化对象。如果希望删除customer时,自动删除和 customer关联的order对象,可把cascade属性设为delete。
<set name=“orders” cascade=“delete” inverse=“true”>
        <key column=“CUSTOMER_ID” />
        <one-to-many class=“mypack.Order” />
</set>
再运行删除方法的时候,会自动删除order对象.

8.父子关系
就是父方来控制子方的持久化生命周期,子方对象必须和一个父方对象关联。
当customer.hbm.xml 的<set>元素的cascade属性取值为all-delete-orphan,Hibernate会按照如下方式处理customer对 象:
当保存或更新customer对象时,级联保存或更新所有关联的order对象,相当于save-update.
当删除 customer对象时,级联删除所有的order对象,相当于delete。
删除不再和customer对象关联的所有order对象。当关联双方存在父子关系时,就可以把父方的cascade属性设为 all-delete-orphan.

9.这几个方法的不同之处:
commit() 先调用flush方法,然后提交事务。提交事务意味着对数据库操作永久保存下来。
flush()清理,刷出;不提交,就能回滚  和 s.setFlushMode()的设置讲解
refresh()刷新缓存;数据库→缓存
clear()清空缓存内容.

10.hibernate 中java对象的状态
1)持久化对象
位于一个session缓存中,总是被一个session关联。持久化对象和数据库记录相对应。清理缓存时,会根据对象属性变化,同步更新数据库。 save把临时对象转变为持久化对象。load或find或get返回的对象总是持久化状态。find方法返回的list存放的都是持久化对象。 update、save、SaveOrUpdate和Lock方法使游离对象装变为持久化对象。在实际的应用程序中应该避免一个java对象被多个 session实例关联,会导致重复执行sql语句,并且极容易出现一些并发问题。
2)游离对象
不再位于 session的缓存中,游离对象不被session关联。游离对象由持久化转变过来的,因此在数据库中可能还存在与它对应的记录(前提条件是没有其他程 序删除了这条记录)。
3)临时对象 :
刚刚被new出来的对象,还没有和session有任何操作.

11.unsaved- value 和 s.saveOrUpdate()
Hibernate是怎么区分是保存还是更新呢.unsaved-value就是用来区分是不是被保存过.Hibernate中用对象表示符(OID)来 区分对象.

12.s.load()和 s.get()的区别.
load()是在需要数据的时候才访问数据库.
get()是执行了就马上访问数据库.

13.检索策略 lazy的配置
这个很重点,对系统的性能优化和提升有很大的帮助.
一对多和多对多关联的检索策略有:立即检索,延迟检索,批量延迟检索,批量立即检索,迫切左外连接检索

总结:
联合主键不推荐使用,Hibernate中有联合主键,其官方的说法是为了适应已经存在的老系统.
debug 的使用,调试的表达式里不要有表达式.调试进程要有一个进程

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值