2011-05-04 40 views
0

我有一个代码保存一个bean,并通过Hibernate更新数据库中的另一个bean。它必须在同一个事务中执行,因为如果发生错误(f.ex启动一个Exception),必须为这两个操作执行回滚。如何做不失密封的交易?

public class BeanDao extends ManagedSession { 

public Integer save(Bean bean) { 
    Session session = null; 
    try { 
     session = createNewSessionAndTransaction(); 

     Integer idValoracio = (Integer) session.save(bean); // SAVE 
     doOtherAction(bean);         // UPDATE 

     commitTransaction(session); 

     return idBean; 
    } catch (RuntimeException re) { 
     log.error("get failed", re); 
     if (session != null) { 
      rollbackTransaction(session); 
     } 
     throw re; 
    } 
} 

private void doOtherAction(Bean bean) { 
    Integer idOtherBean = bean.getIdOtherBean(); 
    OtherBeanDao otherBeanDao = new OtherBeanDao(); 
    OtherBean otherBean = otherBeanDao.findById(idOtherBean); 
    . 
    . (doing operations) 
    . 
    otherBeanDao.attachDirty(otherBean) 
} 
} 

的问题是:

在情况下

session.save(bean) 

启动一个错误,然后我得到AssertionFailure,因为函数doOtherAction(即在项目的其他部分使用)用途会抛出异常之后的会话。

我想的第一件事是提取功能doOtherAction的代码,但后来我有相同的代码复制,并没有似乎做它的最佳实践。

什么是重构这个最好的方法?

回答

0

这是一个普遍的做法,在一个水平之上的DAO来管理交易,服务或其他业务逻辑类。这样,您可以基于业务/服务逻辑在一个事务中执行两个DAO操作,而在另一种情况下,可以在单独的事务中执行这些操作。

0

我是Declarative Transaction Management的忠实粉丝。如果你可以腾出时间让它工作(一块Application Server如GlassFish或JBoss,并易于Spring)。如果您使用@TransactionAttribute(REQUIRED)注释业务方法(甚至可以将其设置为默认设置),并调用两个DAO方法,您将获得所需的所有内容:所有内容都立即提交或通过异常回滚。 这个解决方案就像它松散耦合一样。

0

其他人是正确的,因为他们考虑了目前常见的做法。

但这并不能真正帮助你解决目前的问题。

你应该做的是创建两个新的DAO方法。如CreateGlobalSession和CommitGlobalSession。

这些与您当前的创建和提交例程相同。

不同的是,他们成立一个“全球性”的会话变量(一个ThreadLocal的最有可能的最好的做法)。然后你改变当前的例程,以便检查这个全局会话是否已经存在。如果您的创建检测到全局会话,那么只需返回它。如果您的提交检测到全局会话,则它不会执行任何操作。

现在,当你想使用它,你这样做:

try { 
    dao.createGlobalSession(); 
    beanA.save(); 
    beanb.save(); 
    Dao.commitGlobalSession(); 
} finally { 
    dao.rollbackGlobalSession(); 
} 

确保你包在一个try块的过程,这样,如果有一个错误,你可以重置您的全球会议。

而其他技术被认为是最佳做法,最好你有一天发展到这样的事情,这将让你渡过了难关很少超过3个新的方法和改变现有的两个方法。之后,其余代码保持不变。

+0

作为一个不得不维护大量使用共享会话/事务(反)模式的代码的人,我可以说在开发阶段使用它并不明智,只是为了避免一些配置工作和重构。这种解决方案往往会增加维护成本。在某种程度上,有人会忘记进行交易,会话会泄漏,您将遇到计划任务或应用程序集群问题等问题。从完全务实的角度来看,我并不是在谈论“理想”方法,只是“长期证明廉价”。 – 2011-05-05 14:36:20

+0

只是为了修改我所说的话:共享会话/事务是一种解决方法,它可以快速复制和粘贴到任何地方,而早期或后期会成为项目中事务管理的某种标准。请不要创造一个怪物。 – 2011-05-05 14:56:10

+0

@安东尼,当然,但这是事情。这种情况只需要实际的交易,这对于这种情况来说(显然)是非常罕见的。所以,DAO的正常机制仍然存在(当然,这仍然可能会泄漏)。然后,如果有人想稍后添加另一个多bean事务,他们可能会剪切并粘贴这个原始代码,从而保留该模式。当然,作为一个副作用。但是,他也没有提到他的代码是在服务器上,在客户端上还是在服务器上。做你认为他需要EJB或Spring或其他框架的东西。这对他来说可能不实际。 – 2011-05-05 23:07:38