【问题标题】:Spring Transactions: Interface v ClassSpring事务:接口v类
【发布时间】:2015-04-07 07:09:53
【问题描述】:

我正在尝试使用 Spring Transactions,但失败了。当我设置它们以便我的网络应用程序将在 Tomcat 下启动时,调用

TransactionAspectSupport.currentTransactionStatus ().setRollbackOnly ();

当我需要回滚事务,但之前的数据库更改未回滚时,我的 localhost.date.log 文件中出现以下错误:

SEVERE: Servlet.service() for servlet model threw exception
org.springframework.transaction.NoTransactionException: No transaction aspect-managed TransactionStatus in scope
    at org.springframework.transaction.interceptor.TransactionAspectSupport.currentTransactionStatus(TransactionAspectSupport.java:122)
    at edu.mayo.bsi.backslapper.model.dao.impl.TransactServiceDAOImpl.giveProps(TransactServiceDAOImpl.java:160)

我有

public interface TransactServiceDAO

public class TransactServiceDAOImpl implements TransactServiceDAO

在我的 application-context-config.xml 我有

<bean id = "transactService" class = "edu.mayo.bsi.backslapper.model.dao.impl.TransactServiceDAOImpl"/>

<!-- enable the configuration of transactional behavior based on annotations -->
<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) -->
<tx:advice id = "txAdvice" transaction-manager = "txManager">
    <!-- the transactional semantics... -->
    <tx:attributes>
        <!-- all methods starting with 'get' are read-only -->
        <tx:method name = "get*" read-only = "true"/>
        <!-- other methods use the default transaction settings (see below) -->
        <tx:method name = "*"/>
    </tx:attributes>
</tx:advice>

<!-- ensure that the above transactional advice runs for any execution of an operation defined by the TransactServiceDAO interface -->
<aop:config>
    <aop:pointcut id = "transactServiceOperation" expression = "execution(* edu.mayo.bsi.backslapper.model.dao.TransactServiceDAO.*(..))"/>
    <aop:advisor advice-ref = "txAdvice" pointcut-ref = "transactServiceOperation"/>
</aop:config>

<bean id = "txManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name = "dataSource" ref = "backDataSource"/>
</bean>

<tx:advice id = "txAdvice" transaction-manager = "txManager">
    <tx:attributes>
        <tx:method name = "*" rollback-for = "Throwable"/>
        <tx:method name = "*" rollback-for = "java.sql.SQLException"/>
    </tx:attributes>
</tx:advice>

这是一个示例,一个 (count == 0) 回滚不会撤消“删除旧用户”的例程。

我做错了什么?

public String setUsers (DataSource dataSource, User theUser, String store, AdminUser[] newUsers)
{
    NamedParameterJdbcTemplate  namedParameterJdbcTemplate = new NamedParameterJdbcTemplate (dataSource);
    Map<String, Object>         params = new HashMap<String, Object> ();

    params.put ("lanID", theUser.getLanID ());
    params.put ("storeName", store);

    int count = namedParameterJdbcTemplate.update (kDeleteOldUsers, params);

    for (AdminUser curUser : newUsers)
    {
        int userID = updateUser (namedParameterJdbcTemplate, curUser.getLanID (), curUser.getFullName (), curUser.getEmail (), null);

        if (userID == kError)
            userID = addUser (namedParameterJdbcTemplate, curUser);

        params.put ("userID", Integer.valueOf (userID));
        count = namedParameterJdbcTemplate.update (kAddStoreUser, params);
        if (count == 0) // Wasn't inserted
            TransactionAspectSupport.currentTransactionStatus ().setRollbackOnly ();

        params.put ("backslapsToGive", Integer.valueOf (curUser.getBackslapsToGive ()));
        params.put ("monthlyBackslaps", Integer.valueOf (curUser.getMaxBackslaps ()));
        count = namedParameterJdbcTemplate.update (kUpdateUserStores, params);
        if (count == 0) // Wasn't updated
            TransactionAspectSupport.currentTransactionStatus ().setRollbackOnly ();
    }

    return null;
}

【问题讨论】:

    标签: java spring transactions spring-transactions


    【解决方案1】:

    我没用过 TransactionAspectSupport.currentTransactionStatus ().setRollbackOnly (); 以此目的。 我认为你应该在这里抛出异常。最好的方法是扩展 RuntimeException。 Spring事务是从头到尾的切面方法。如果引发异常,事务将回滚。

    如果您不希望此异常中断您的流程,您可以在此方法中抛出它并在调用方法中捕获。

    【讨论】:

    • TransactionAspectSupport.currentTransactionStatus ().setRollbackOnly ();抛出异常:严重:Servlet 模型的 Servlet.service() 抛出异常 org.springframework.transaction.NoTransactionException:在 org.springframework.transaction.interceptor.TransactionAspectSupport.currentTransactionStatus(TransactionAspectSupport.java:122 范围内没有事务方面管理的 TransactionStatus ) 在 edu.mayo.bsi.backslapper.model.dao.impl.TransactServiceDAOImpl.giveProps(TransactServiceDAOImpl.java:160)
    • 很明显,您没有将 tx 附加到此方法。所以首先你需要检查你的 aop:pointcut 是否正确。其次,我不确定这是否是配置 tx 的最佳方式。这意味着您每次想要添加新服务时都需要更改配置。这意味着该服务中的每个方法都将是事务性的,这并不总是您想要的。我建议您使用 设置您的 conf,然后使用 @Transactional 注释方法,并在必要时在实现方法上添加 readOnly = true。
    • 我的 aop:pointcut 在中间。有什么问题吗? TransactService 处理所有事务性数据库调用,无论是否启动服务,其中唯一的东西都是事务性的。我尝试在例程上使用 Transactional,其他 8 个类突然无法编译。删除它,他们编译。所以我想避免事务性
    • 尝试抛出运行时异常,它不会强制回滚。
    猜你喜欢
    • 2020-02-13
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 1970-01-01
    • 2016-09-29
    • 2015-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多