通过Session接口来操作Hibernate
新增——save方法、persist方法
1:persist() 使一个临时实例持久化。然而,它不保证立即把标识符值分配给持久性实例,这会发生在flush的时候。persist() 也保证它在事务边界外调用
时不会执行 INSERT 语句。这对于长期运行的带有扩展会话/持久化上下文的会
话是很有用的。
2:save() 保证返回一个标识符。如果需要运行 INSERT 来获取标识符(如
"identity" 而非"sequence" 生成器),这个 INSERT 将立即执行,不管你是否
在事务内部还是外部。这对于长期运行的带有扩展会话/持久化上下文的会话来
说会出现问题。
我的观察:save方法做下面的事:
1:如果对象已经在本session中持久化了,不做任何事 (注意:对于一个已经持久化的对象进行保存是没有意义的,而且通过分析代码, save和saveOrUpdate的行为有点类似)
2:如果另一个与本session关联的对象拥有相同的持久化标识,抛出一个异常。
3:否则save()这个对象,具体行为见上面。
注意:对于save来说, 不管数据库中存不存在相同id的数据, 它都会执行insert语句。对于<generator=“native”>来说,这个没有问题, 数据库中都会新增一条记录;如果<generator="assigned">, 而save的对象的主键值已在数据库中存在, 就会抛出键重复异常。
删除——delete方法
修改——有四种方法来做,分别是:
1:直接在Session打开的时候load对象,然后修改这个持久对象,在事务提交的时候,会自动
flush到数据库中。
2:修改托管对象,可用update或merge方法
3:自动状态检测:saveOrUpdate方法
update方法做下面的事:
1:如果对象已经在本session中持久化了,不做任何事 (注意: 对持久化对象,会在事务提交的时候自动flush修改的数据,所以在提交之前对持久化数据进行任何修改操作都是没有效果的)
2:如果另一个与本session关联的对象拥有相同的持久化标识,抛出一个异常
3:否则update()这个对象
merge做如下的事情
1:如果传递的对象本身已经在本session中持久化了,不做任何事。
2:如果传递的对象是瞬时对象或者是托管对象,并且在session中存在相同持久化标识的实例,用用户给出的对象的状态覆盖旧有
的持久实例
3:如果session中没有相应的持久实例,则尝试从数据库中加载,或创建新的持久化实例
4:最后返回该持久实例
5:用户给出的这个对象没有被关联到 session 上,它依旧是脱管的
saveOrUpdate方法做下面的事:
1:如果对象已经在本session中持久化了,不做任何事
2:如果另一个与本session关联的对象拥有相同的持久化标识,抛出一个异常
3:如果对象没有持久化标识属性,对其调用 save()
4:如果对象的持久标识表明其是一个新实例化的对象,对其调用 save()。
5:如果对象是附带版本信息的(通过 <version> 或 <timestamp>)并且版本属性
的值表明其是一个新实例化的对象,save() 它。
6:否则update()这个对象
update和merge方法的区别:
1:如果数据库里面存在你要修改的记录,update每次是直接执行修改语句;而merge是先在缓
存中查找,缓存中没有相应数据,就到数据库去查询,然后再合并数据,如果数据是一样
的,那么merge方法不会去做修改,如果数据有不一样的地方,merge才真正修改数据库。
2:如果数据库中不存在你要修改的记录,update是报错;而merge方法是当作一条新增的值,
向数据库中新增一条数据。
3:update后,传入的TO对象就是PO的了,而merge还是TO的。
4:如果你确定当前session没有包含与之具有相同持久化标识的持久实例,使用update()。如
果想随时合并改动而不考虑session的状态,使用 merge()。换句话说,在一个新 session
中通常第一个调用的是update()方法,以保证重新关联脱管对象的操作首先被执行。
5:请注意:使用update来把一个TO变成PO,那么不管是否修改了对象,都是要执行update sql语句的。
我的观察:
update, merge, saveOrUpdate在使用中最大的区别, 我认为就是 update和saveOrUpdate在操作对象时候, 如果session上下文中存在拥有相同的持久化标识的另一个对象,这两个操作都会抛出异常,而merge没有影响, 和session状态无关。
另外, 对于“session上下文中存在拥有相同的持久化标识的另一个对象”这一条, 要注意通过session.load加载和通过session.get加载的对象的区别:
因为, 通过load加载的持久化对象, 只要你没有真正去使用对象加载的数据,那么load返回的对象都是一个代理的假持久化对象, 这个时候该代理对象的持久化标识是空的(实际上标识值是有的(load的时候要给,只是放在一个内置对象里了), 所以update或者saveOrUpdate在判断session中是否存在另一个持久化对象的时候,这个对象如果是通过load加载的,判断的结果都是“没有”, 所以这个时候,update 和saveOrUpdate都可以顺利执行, 没有异常抛出。对于通过get加载的对象, 因为get操作总是从数据库返回持久化实例, 所以持久化标识总是存在的,update和saveOrUpdate对象就会抛出异常。
通常下面的场景会使用 update() 或 saveOrUpdate()
1:程序在第一个 session 中加载对象
2:该对象被传递到表现层
3:对象发生了一些改动
4:该对象被返回到业务逻辑层
5:程序调用第二个session的update()方法持久这些改动
按主键查询
1:load方法:load的时候首先查询一级缓存,没有就创建并返回一个代理对象,等
到使用的时候,才查二级缓存,如果二级缓存中没有数据就查数据库,如果数据
库中没有,就抛例外
2:get方法:先查缓存,如果缓存中没有这条具体的数据,就查数据库,如果数据
库没有值,就返回null,总之get方法不管用不用,都要拿到真实的数据
注: load和get方法的区别可以见前面的文章。

7万+

被折叠的 条评论
为什么被折叠?



