春季和冬眠的嵌套交易

时间:2019-05-29 20:56:13

标签: java spring hibernate

我一直在对一个项目中存在一些事务完整性问题的代码进行重做。我和团队基本得出的结论是,将多个事务(当前是独立的)作为嵌套事务在一个全局事务下运行是引入解决方案的最佳和最简便方法,并且也使系统推理变得简单

通过将HibernateTransactionManager配置为将globalRollbackOnParticipationFailure设置为false,将nestedTransactionAllowed设置为true,可以实现嵌套传播。如果您直接使用数据源/ JDBC,那么使用保存点就可以很好地工作,但是这里出现了问题...

我们需要使用休眠模式。要将其取出来进行繁琐的工作,而且休眠不支持嵌套事务。我们计划实施的“解决方案”(似乎可以正常工作)遵循休眠语义,即“如果在处理过程中引发异常,则会话中使用的实体处于未知状态,并且事务应回滚。然后重新开始”。。。除了在回滚整个事务的过程中,我们是在嵌套事务方法的边界捕获异常,然后清除休眠会话并重新抛出异常,以便我们可以继续进行全局事务。这似乎工作得很好,并且我们意识到我们实际上应该丢弃休眠的实体(每个嵌套事务和全局事务完全使用不同的实体,因此这样做的风险很小)。代码如下:

begin global tx

    doWork();

    try {
        begin nested tx
                try {
                    getCurrentSession().flush(); //flush anything pending so we don't potentially lose it when we clear the session below
                    throwSomeHibernateException();
                }
                catch (Exception aE) {
                    getCurrentSession().clear();
                    throw aE;
                }
        end nested tx

    } catch (Exception aE) {
        doSomeErrorHandlingRequiringHibernate();
    }

end global tx

现在,代码中只有少数几个地方实际上是我们在启动嵌套事务(还有一些其他地方,我们也知道发生了来自休眠的异常),因此上述逻辑基本上可以在所有这些地方实现地方。

我们尝试的另一种解决方案是查看旧版本的HibernateTemplate-我知道不鼓励使用此类,但executeWithNewSession方法看起来很诱人,因为这正是我们需要告诉spring要做的-即在a下执行嵌套事务。不同的休眠会话。从我在网上阅读的内容来看,spring似乎假设1个事务= 1个休眠会话,是否有一种方法可以声明/配置spring来更改此行为而无需编写新的事务/会话mananger?

是否有更简单的方法来处理或支持上述用例?我们计划做的是“足够好”吗?我们主要关心的是这项工作是为了给系统带来完整性,但是我们必须通过直接玩会话来积极地解决局限性,这是危险的imo

0 个答案:

没有答案