不在事务中时如何回滚Spring JDBC操作

7

我正在使用Spring JDBC的注解驱动事务管理。

当我不小心忘记在插入/更新/删除服务方法上注释@Transactional时,我希望Spring抛出异常。

默认情况下,即使不在事务中,也可以插入/更新/删除数据。


1
你可以在DAO层中使用Propagation.MANDATORY。 - user3769706
选择仅在服务层使用 @Transactional,因为事务始终从那里开始。 - yannisf
你可以通过反射迭代所有的服务类,并检查它们是否都包含@Transactional注解。 - Grzegorz Gajos
Propagation.MANDATORY如果没有事务,则不会启动事务;它将抛出一个错误。 - Fabien Benoit-Koch
所有关于 Propagation.MANDATORY 的回复都是正确的,但始终要考虑通过 JUnit 进行测试以确认任何预期的行为。 - Manuel Jordan
@sam_eera 请将您的评论作为答案提供,以便我选择它作为解决方案。由于没有其他替代方案,因此按照您的建议进行了实施,并且它起作用了! - yannisf
2个回答

1
你可以在DAO层使用Propagation.MANDATORYPropagation.MANDATORY不会启动一个事务。它将检查特定方法是否附加到事务中,如果没有,容器将抛出异常。

0
根据文档(Spring文档),它只是元数据,用于指示方法或接口可以被“具有事务意识”的某些内容配置(即使用tx:annotation-driven而没有@Transactional属性,我认为您会得到“默认”的事务性应用程序:传播设置为REQUIRED。隔离级别为DEFAULT。事务是读/写。事务超时默认为基础事务系统的默认超时,如果不支持超时,则为none。ny RuntimeException触发回滚,任何已检查的异常都不会。假设您正在使用tx:annotation通过事务管理器来驱动它,那么省略@Transactional属性意味着无法应用readOnly、isolation、propagation、rollbackFor、noRollbackFor等属性。
我认为MVC略有不同- Hibernate会话直接绑定到MVC请求-即收到请求时开始事务。
回到您的示例,在HibernateDAOSupport中getSession()的代码如下:
protected final Session getSession()
    throws DataAccessResourceFailureException, IllegalStateException 
{
    return getSession(this.hibernateTemplate.isAllowCreate());
}

这反过来调用:

/** * 获取一个Hibernate Session,可以从当前事务或新事务中获取。只有在“allowCreate”为true时才允许后者。 *.......

protected final Session getSession()
    throws DataAccessResourceFailureException, IllegalStateException {
return getSession(this.hibernateTemplate.isAllowCreate());
}

最终调用:

/** * .... * @param allowCreate 当前线程找不到事务性Session时,是否应该创建非事务性Session * .... */

private static Session doGetSession(
    SessionFactory sessionFactory, Interceptor entityInterceptor,
SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)

从根本上讲,Transaction:Session 是一对一绑定的,而且如果我没记错的话,唯一无需事务运行的方法是使用内置持久化层提供事务处理的 JBoss(在后台)。即使在 getSession() 后调用 getQuery(),仍然会有效地发生事务,因为它是一个 JDBC/Hibernate 连接。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接