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