Session和EntityManager代表的是持久化上下文,持久化对象的状态与持久化上下文和底层数据库都有关系
四种状态:
1.new和transient:new出来的对象,没有数据库标识符,也没有关联上持久化上下文
2.managed和persistent:同时关联了持久化上下文和数据库标识符
3.detached:关联了数据库标识符,但是不再关联持久化上下文(可能持久化上下文已关闭或者实体已被evicted)
4.remove:同时关联了持久化上下文和数据库标识符,但是已经被计划从数据库删除
实体对象状态的转变
1.使之持久化
session.save和entityManager.persist
hibernate session也支持persist
如果是generated标识符,save和persist调用后会生成,如果不是auto generated的,需要在调用之前设置标识符。
save和persist的两个区别:1.persist不保证方法调用完后肯定返回数据库标识符,是在flush后才生成数据库标识符,而save保证返回标识符。2.因为1所以persist保证在事务边界外不会调用insert,而save不管是否在事务内部都会执行insert(当需要执行insert才能得到标识符的时候,例如identify(sql server和mysql支持的自增字段))
2.删除实体
session.delete和entityManager.remove
把一个持久实例变成瞬时实例,两个方法的区别:hibernate delete可以删除处于detached状态和managed状态的对象,但是entitymanager remove只能删除managed状态的对象
3.加载实体不加载数据
session.byId.getreference(4.0之前是load)和entityManager.getReference
允许延迟加载,通常是获得的一个运行时代理,如果数据库不存在此数据,当真正调用其方法时,会抛出异常
4.加载实体并初始化数据
session.byId.load(4.0之前是get)和entityManager.find
会查询数据库,如果没有匹配的记录会返回null,如果不确定数据是否存在,应该使用get方法,get方法可以带lock访问,编程select……for update方式
5.加载实体通过自然键
hibernate4.2新特性,和使用标识符一样的可以加载引用或者加载数据
6.刷新实体状态
session.refresh
同步数据库状态的变化到已经加载的实体
7.修改管理持久化状态
session.flush
已经处于managed和persistent的对象,只需调用flush,就能把状态同步到数据库
可以设置session flush的时间,默认会在事务提交和执行一些查询之前,自动flush
8.管理托管状态的实体
四种方式使实体编程托管态
1.close session
2.clear session
3.evicted 一个实体
4.序列化会把反序列化形式的变成托管态(原实体还是处于持久态)
Reattaching detached data
1.session.update和session.saveorupdate
可以吧对象重新编程持久态,但是sql更新不是马上执行,而是在flush的时候。并且如果不设置实体映射为select-before-update,不管是否更新,都会执行update语句
如果新的session已经load了一个相同标识符的持久态对象,则update会报异常
当实体是托管态时,update和saveorupdate是一样的。saveorupdate使用unsaved value来判断是更新还是新增,所以如果主键策略是assign的话是不行的
2.session.merge和entityManager.merge
查询出一个持久态对象,将托管态对象的数据copy到持久态对象上进行更新
3.session.lock
当对象没有改变的时候,lock方法也可以把对象重新关联到session
9.检查持久化状态
1.contains , isIinitialization和javax.persistence.PersistenceUnitUtil jpaUtil.isloaded
检查是否在持久态,和是否懒加载已经加载
10.JPA访问底层实现的API
Session session = entityManager.unwrap( Session.class );
SessionImplementor sessionImplementor = entityManager.unwrap( SessionImplementor.class );
11.复制对象到不同的数据库
session.replication
不重新生成标识符,直接将持久实例以及其关联的实例一起拷贝到其他数据库