Spring 事务不工作 + JAX WS + JDBC

Spring transactions not working + JAX WS + JDBC

我对这个问题有点生气。让我们检查是否有人实施了类似的东西。

我有一个 java 8 Web 应用程序,其中实施了 8 个 WS。其中一些 WS,通过 JDBCTemplate 进行插入和更新(由于性能需要,Hibernate 不是一个选择),如果执行崩溃并出现异常,我需要它们回滚。

我在 spring 应用程序上下文文件(服务器中的 jndi 资源。xml/context。xml of Tomcat)中有以下数据源和事务管理器配置:

  <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/source" />
  </bean>
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
  </bean>

  <tx:annotation-driven transaction-manager="transactionManager" />

另一方面,我有一个唯一的数据库访问点 DBcontroller.class,它有一个用于插入、删除和更新的通用方法:

private NamedParameterJdbcTemplate jdbcTemplate;
private DataSource datasource;

@Autowired
public void setDataSource(DataSource dataSource) {
    this.datasource = dataSource;
    this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
@Override
public boolean queryForModifying(String query, SqlParameterSource parameters) {

  int modifiedRows= 0;
  try {
      modifiedRows= this.jdbcTemplate.update(query, parameters);
  } catch (Exception e) {
      e.printStackTrace();
      numRegistrosAfectados = 0;
  }
  return (modifiedRows> 0) ? true : false;
}

最后我有了一个 WS 接口这样:

@WebService
public interface IService{

    @WebMethod
    public method(MethodRequestType request) throws IllegalArgumentException, IllegalAccessException;

}

及其实施:

@WebService(endpointInterface = "com.package.IService")
@HandlerChain(file = "handler-chain.xml")
public class Service implements IService{

    @Autowired
    IDBController dbController;

使用 "transactional" 方法:

@Transactional
private boolean inserts(HashMap<String, Object> input, MethodRequestType request) {.....

它应该在非 WS 项目上工作正常,但正如我发现的那样,没有那么简单的方法来完成这项工作。

起初我以为它没有回滚,但现在我很确定它没有创建事务。

Whosebug 中有一些类似的 post,但其中 none 解决了我的问题。我有很多 google 它,建议的唯一方法是 WS-AtomicTransactions,我从未听说过它。

我几乎尝试了 XML 配置文件中的所有内容,我什至尝试以编程方式管理事务,但由于它是一个连接池,我无法将自动提交设置为 false,这样我就可以强制回滚。

如果它对任何人都有用,我为每个 WS 实现了 soap 处理程序,看起来是这样的:

public class ServiceHandler implements SOAPHandler<SOAPMessageContext> {

    private SoapFaultHandler soapFaultHandler;

    @Override
    public boolean handleMessage(SOAPMessageContext context) {

        SOAPMessage message = context.getMessage();
        soapFaultHandler = new SoapFaultHandler(message);
        return SoapMessageHandler.handleMessage(context, "Service name", logger);
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return soapFaultHandler.handleFault(context, logger, "ServiceName");

    }
    ...
}

通过阅读spring documentation您可以阅读以下内容(重要句子以粗体显示)

  • 仅仅告诉您使用@Transactional 注释注释您的类、将@EnableTransactionManagement 添加到您的配置 以及然后期望您了解它是如何工作的。本节解释 Spring 框架的声明式事务基础结构在发生事务相关问题时的内部工作原理。

  • 关于 Spring 框架的声明式事务支持,要掌握的最重要的概念是这种支持是通过 AOP 代理启用的,并且事务性建议由元数据驱动(目前 XML- 或基于注释)。 AOP 与事务元数据的组合产生了一个 AOP 代理,它使用 TransactionInterceptor 结合适当的 PlatformTransactionManager 实现来驱动围绕方法调用的事务。

  • 使用代理时,您应该仅将@Transactional 注释应用于具有public 可见性 的方法。如果您使用 @Transactional 注释对受保护的、私有的或包可见的方法进行注释,则不会引发错误,但注释的方法不会显示已配置的事务设置。如果您需要注释非 public 方法

  • ,请考虑使用 AspectJ(见下文)

所以请尝试将您的 "inserts" 方法的修饰符从 private 更改为 public

在何处调用带有 @Transactional 注释的方法很重要。例如,如果您有:

@Service
public class Service1 {

    @Transactional
    public void method1() { ... }

    public void method2() {
        method1();
    }
}

@Service
public class Service2 {

    @Autowired
    private Service1 service1;

    public void method1() {
        service1.method1();
    }

    public void method2() {
        service1.method2();
    }
}
  • 调用service2.method2()不会创建交易。
  • 调用 service2.method1() 将创建一个。

因为 Spring 处理代理和 AOP 的方式。

终于找到方法了! 我总是很接近:

  • 交易方法(如Gavi所说)必须是public(但这不是问题,因为我之前尝试过)。

  • 事务方法应该在其他class,而不是在Webservice注解class。

  • 这个 class 需要自动装配,以便它在 Spring 上下文中。

  • 在这个 class 中,我自动装配了一个 DbController 实例。

这就是一切。

我的主要问题是,我嘲笑了这个 class 并用 "new" 实例化了它,而不是让 Spring 发挥它的魔力。

感谢回复,希望对大家有所帮助!