关于update方法有几个地方不明白。
类似上面的方法,调用 select 方法查询出一个实体类对象,方法外部对该对象进行修改,然后传入 update 方法修改。
由于 select 和 update 使用的是两个独立的session,所以调用 session.update 方法的时候会抛出异常,因为传入的obj状态属于托管状态,不是持久态,是这样没错吧。
public Object doSelectXXX(){ Session session = HibernateUtil.getSession(); Object result = session.get(....); session.close(); return result; } public boolean doUpdateXXX(Object obj){ Session session = HibernateUtil.getSession(); session.beginTr....(); session.update(obj); // commit session.close(); return true; } /*类似上面的方法,调用 select 方法查询出一个实体类对象,方法外部对该对象进行修改,然后传入 update 方法修改。 由于 select 和 update 使用的是两个独立的session,所以调用 session.update 方法的时候会抛出异常,因为传入的obj状态属于托管状态,不是持久态,是这样没错吧。*/ /* 下面是我的问题,在spring里集成了hibernate。使用hibernatetemplate类进行操作,配置了相应的事务,并且设置事务隔离级别为:REQUIRES_NEW,总是开启一个新的事务,我理解的spring对session事务的管理应该是方法执行之前打开事务,方法执行之后提交事务,同时关闭session,那么这就和以上的类似了。 按我预想的应该是会抛出异常的,但是却没有,不知道我哪里理解错了? 以下是spring集成hibernate之后的简略代码。 */ public Object doSelectXXX(){ return getHibernateTemplate().get(......); } public boolean doUpdateXXX(Object obj){ getHibernateTemplate().update(obj); return true; }
你的理解有点错误
Hibernate session中常用的保存操作只有:save, update, saveOrUpdate,delete;还有其他很多操作没有用过:persist(), merge(), lock(), refresh(), evict(), replicate() ,有必要弄清楚这些方法分别是做什么, 实体对象的状态会发生什么变化?
先看看这些方法中,从javadoc的注释可以得出:
临时 —> 持久
save,persist,saveOrUpdate
托管 —> 持久
update,saveOrUpdate,saveOrUpdateCopy , merge,lock,replicate,refresh
持久 —> 托管
evict
持久 —> 临时
delete
根据以上,可以看出托管->持久的方法是最多的。
那么以上各类情况下,各个方法有什么区别?应该怎样取舍?在hibernate3.2环境下,我得出以下结论:
1. save和perisit
几乎一样,都是持久化一个临时对象;
只是persist持久化的时间可能推迟到flunsh之前,而且perisit传入的对象为托管对象时,会报错,而save托管对象不会报错只是将id置null。
可以看出,在持久化一个临时对象时,只用save就行了。
可以看出,只有在session中已经存在一个具有相同标识符的持久对象的时候,应该采用merge,此时用saveOrUpdate会报错。当然如果碰到这类情形,将对象属性copy到已经持久化的那个相同标识符对象上也是可以的,正因为如此我一般都没用过merge。再者merge在session中不存在相同标识对象时,会多一条select,往往我们并不需要。
可以看出,replicate在执行复制的时候,比起merge还是有更多可控行为,ReplicationMode.LATEST_VERSION还可以保证并发修改时只更新最新的版本。
有些不同的是,lock还有检查对象版本的能力,如果指定的锁定模式是READ, UPGRADE 或 UPGRADE_NOWAIT,那么Session.lock()就 执行版本号检查。
refresh提供了比load更方便的查找能力,一个刚脱离了session的持久对象,如果用load还需要用id查找,那么refresh就可以直接传入托管对象刷新其状态了。