zfc827 2009-04-18 03:05
浏览 172
已采纳

hibernate及spring的一些细节问题

关于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;
}

 

  • 写回答

1条回答 默认 最新

  • wanghaolovezlq 2009-04-18 09:26
    关注

    你的理解有点错误

    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就行了。

    1. saveOrUpdate和merge saveOrUpdate将unsaved对象持久化或托管对象持久化; merge,从名字也能猜到是合并,跟saveOrUpdate相似,可以持久化托管和临时对象。 不同的是:在更新时候,merge将托管对象的属性复制到session中有相同标识符(但不相等)的持久对象(如果不存在,就从db load),也就是先select 后 update;倘若找不到相同标识符的对象,则置id为null,保存临时对象。返回的是持久对象,但是merge传入的对象还是托管的。

    可以看出,只有在session中已经存在一个具有相同标识符的持久对象的时候,应该采用merge,此时用saveOrUpdate会报错。当然如果碰到这类情形,将对象属性copy到已经持久化的那个相同标识符对象上也是可以的,正因为如此我一般都没用过merge。再者merge在session中不存在相同标识对象时,会多一条select,往往我们并不需要。

    1. merge和replicate replicate,通过复制来持久化当前已经脱离session的托管对象,这点上看有点像merge,但是当传入一个临时对象则会报错,而且replicate后的传入的那个对象将是持久的,这也是跟merge不同。 通过参数ReplicationMode可以控制遇到相同记录时的行为。 如果是 ReplicationMode.EXCEPTION,则在复制时如果有重复的行数据,则抛出异常。ReplicationMode.IGNORE则忽略 异常。 ReplicationMode.OVERWRITE则会覆盖掉已有行数据。ReplicationMode.LATEST_VERSION则是在有重复时使用最新的版本进行控制。

    可以看出,replicate在执行复制的时候,比起merge还是有更多可控行为,ReplicationMode.LATEST_VERSION还可以保证并发修改时只更新最新的版本。

    1. lock和refresh 相类似的,都将托管对象又重新持久化,而且可以指定查询时候的锁:
      • 当用户显式的使用数据库支持的SQL格式SELECT ... FOR UPDATE 发送SQL的时候,锁定级别设置为LockMode.UPGRADE
      • 当用户显式的使用Oracle数据库的SQL语句SELECT ... FOR UPDATE NOWAIT 的时候,锁定级别设置LockMode.UPGRADE_NOWAIT *当Hibernate在“可重复读”或者是“序列化”数据库隔离级别下读取数据的时候,锁定模式 自动设置为LockMode.READ。这种模式也可以通过用户显式指定进行设置。 *LockMode.NONE 代表无需锁定。在Transaction结束时, 所有的对象都切换到该模式上来。与session相关联的对象通过调用update() 或者saveOrUpdate()脱离该模式。 以上只有 LockMode.NONE,先从缓存查找持久对象;其他的都直接从数据库查找。

    有些不同的是,lock还有检查对象版本的能力,如果指定的锁定模式是READ, UPGRADE 或 UPGRADE_NOWAIT,那么Session.lock()就 执行版本号检查。

    refresh提供了比load更方便的查找能力,一个刚脱离了session的持久对象,如果用load还需要用id查找,那么refresh就可以直接传入托管对象刷新其状态了。

    1. delete和evict evict,从session的缓存中去除当前实例。执行后对象的改变将不再和数据库保持同步。当指定级联风格为'evict’时,会级联操作关联对象。在用于批量操作的时候,清空缓存,防止内存紧张。 delete,也会从session的缓存中去除当前实例,但flunsh时会执行数据库delete,之后对象就成了临时状态。 可以看出delete比起evict,不仅从session删除,还会从数据库删除。
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 数学的三元一次方程求解
  • ¥20 iqoo11 如何下载安装工程模式
  • ¥15 本题的答案是不是有问题
  • ¥15 关于#r语言#的问题:(svydesign)为什么在一个大的数据集中抽取了一个小数据集
  • ¥15 C++使用Gunplot
  • ¥15 这个电路是如何实现路灯控制器的,原理是什么,怎么求解灯亮起后熄灭的时间如图?
  • ¥15 matlab数字图像处理频率域滤波
  • ¥15 在abaqus做了二维正交切削模型,给刀具添加了超声振动条件后输出切削力为什么比普通切削增大这么多
  • ¥15 ELGamal和paillier计算效率谁快?
  • ¥15 蓝桥杯单片机第十三届第一场,整点继电器吸合,5s后断开出现了问题