Hibernate操纵对象

2014/04/16 22:38
注意的地方
1.一个Java对象应该避免同时被多个session关联,这样做会导致执行重复的sql,并极易引起一些并发的问题。
2.session的save不应该来保存游离态或持久态对象,它是用来将临时态对象转为持久态的,那样做会导致数据重复。
3.使游离态对象变成持久态应该调用update方法。
4.delete()方法,能将持久态对象或游离态对象变为被删除对象,删除的对象为无用对象,程序不应该再去使用这些对象。
5.定义model类时,应该将每个属性都进行初始化,否则容易出同空指针异常。

一、什么时脏检查?
当一个对象被加入的session中时,session会为这个对象的属性建立一个快照。当session清理缓存时,会将当前对象与快照进行比较(这个过程称为脏检查),如果不相同,则这个对象称为脏对象,session会根据这个脏对象的最新属性执行相关SQL更新数据。

二、session缓存会在如下情况下清理:
2.1.tx.commit();
2.2.应用程序执行一些查询操作。
2.3.session.flush();
一般来说,程序都不需要显式的调用flush(),显式调用适用以下场合:
2.3.1.插入、更新或删除会引起数据库触发器的工作。
2.3.2.在应用程序中混合使用hibernate api和jdbc api。
2.3.3.jdbc驱动不健全,导致hibernate在自动清理缓存模式下无法正常工作。

三、Java对象在hibernate中的状态
3.1.临时态:刚被new出来的对象,不存在session缓存当中。
3.2.持久态:被session的get、save,load等方法处理后加入到session缓存中的对象。
3.3.删除态:不再存在session缓存当中,并且session已经计划在数据库中删除这个对象信息的对象。被delete方法处理之后
3.4.游离态:已经被持久化(session执行close()或flush()方法清理缓存之后),但是不在session缓存中的对象。

四、session主要接口用法
4.1.save():使临时对象转换为持久化对象。
4.1.1当对象的OID由Hibernate来管理时,临时对象手动设置其OID是无效的。
代码
tx.begin();
Teacher teacher = new Teacher();
teacher.setRowId(99L);
session.save(teacher);
tx.commit();
其执行结果teacher的OID并不是99

4.2.2
当一个对象处于持久化状态时,不能手动更新其OID,否程序会抛出异常。
代码
tx.begin();
Teacher teacher = new Teacher();
session.save(teacher);
teacher.setRowId(99L);
tx.commit();
此时程序就会抛出以下异常 
identifier of an instance of hibernate.model.Teacher was altered from 5 to 99

4.2.update()方法:使游离态对象转换为持久态,此方法有两个特点:
4.2.1.只会在session清理缓存时才执行SQL。
4.2.2.不管这个游离态对象的属性是否有更改,都会执行update语句。
代码
tx1.begin();
Teacher teacher1 = (Teacher)session1.get(Teacher.class, 1L);
tx1.commit();
session1.close();
tx2.begin();
session2.update(teacher1);
tx2.commit();
session2.close();
发现程序执行了update语句

4.2.3.如果希望session仅当修改了属性时,才执行update语句,则需要在<class>元素中加上 select-before-update="true" 属性,如果程序经常修改属性,则不用加这个判断,因为这个判断会在更新之前多执行一次select操作。

4.2.4.如果session中已经存在了这个游离态对象,则不允许再次将这个游离态对象放入session,否则会抛出异常
代码
tx1.begin();
Teacher teacher1 = (Teacher)session1.get(Teacher.class, 1L);
tx1.commit();
session1.close();
tx2.begin();
session2.get(Teacher.class, 1L); //session中已经有了OID为1的对象
session2.update(teacher1);
tx2.commit();
session2.close();
结果抛出异常:
a different object with the same identifier value was already associated with the session: [hibernate.model.Teacher#1]
(测试:如果这个方法用在临时态对象上会如何?)。

4.3.saveOrUpdate()方法:同时包含了save和update方法的功能,如果传入的对象是临时态的,则执行save方法,如果游离态的则执行update方法。如果对象满足以下情况,Hibernate就认为是临时对象
4.3.1.对象的OID为null
4.3.2对象具有version版本控制并且取值为null
4.3.3在<id>元素中设置了unsaved-value属性,且对象的OID值与此值相同
4.3.4映射文件中为version版本控制属性设置了unsaved-value属性,且对象的version版本控制属性的值与此值相同
4.3.5为Hibernate的Interceptor提供了自定义的实现,且isUnsaved()方法返回true

4.4.merge()方法:将游离态对象的属性复制到一个持久态对象中。主要是为了解决4.2.4的异常。其传入的参数可以是游离态对象也可以是临时对象。
4.5.persist()方法:功能与save()一样,有以下两个不同点
4.5.1.此方法不保证会立即给对象赋值OID,有可能是在session清理是才赋值 。
4.5.2.如果在事物边界以外,该方法不会计划SQL,但是save()方法无论是否在事物边界内外都会计划执行sql。

4.6.get/load方法:
get
load
立即抓取
延迟加载(需要在hbm.xml中设置lazy = true),当访问对象属性时才加载对象。
如果在数据库中查询不到对象,则返回null
如果查询不到对象,则抛出 ObjectNotFoundException
返回的可能是代理类,比如在session缓存中找到了一个类,
而这个类刚好被load加载过,那么这个类就是一个代理类了
查询顺序,一级缓存、二级缓存、数据库。
返回的一定是一个代理类,因此才会有延迟加载的机制
它先创建一个该类的代理类,但只赋值OID,
然后当这个类被调用时,根据其OID加载这个类,
找到则继续赋值,找不到 则抛出异常。
4.7delete()方法: 将持久态对象或游离态对象变为被删除对象

五、cascade属性表
    
none
当session操纵当前对象时,忽略其它关联的对象,是cascade属性的默认值
save-update
保存时会级联保存所有关联的临时对象或游离对象
persist
调用persist()方法时,会级联保存所有关联的临时对象
merge 
调用merge()方法时,会级联融合所有关联的游离对象
delete
调用delete()方法时,会级联删除所有关联的对象
lock
调用lock()方法时,将游离对象加入到session中时,会将所有关联的游离态对象也加入到session中
replicate
调用replicate()方法时,会级联复制所有关联的对象
evict
调用evict()方法清除对象时,会级联清除所有关联的对象
refresh
调用refresh()方法时,会级联刷新的有关联的对象
all
包含以上所有行为
delete-orphan
删除所有和当前对象解除关联的关系对象
all-delete-orphan
包含all和delete-orphan行为






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值