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 发挥它的魔力。
感谢回复,希望对大家有所帮助!
我对这个问题有点生气。让我们检查是否有人实施了类似的东西。
我有一个 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 发挥它的魔力。
感谢回复,希望对大家有所帮助!