Spring Jdbc声明式事务已创建但未执行任何操作 [英] Spring Jdbc declarative transactions created but not doing anything

查看:68
本文介绍了Spring Jdbc声明式事务已创建但未执行任何操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在基于Spring的Web应用程序中配置声明式事务管理,但它拒绝与我合作。

I have tried to configure declarative transaction management within my Spring-based web application and it refuses to cooperate with me.

我有两个主要问题:


  1. 在我们的dataSource(我们的应用程序需要)上将defaultAutoCommit设置为false会导致所有查询回滚,无论是否涉及的交易。

  2. 已配置交易,并且已创建代理类和交易方法,但似乎没有使用任何交易。

  1. Setting defaultAutoCommit to false on our dataSource (which we need for our application) causes all queries to rollback, with or without transactions being involved.
  2. Transactions are configured and proxy classes as well as transactional methods are created, however no transactions appear to be used.

第一个问题相当令人困惑,因为每个单独的查询都在数据库中回滚。这也包括SELECT语句。什么可能导致每个查询在数据库中回滚?

The first problem is rather perplexing, as every individual query is being rolled back in the database. This includes SELECT statements as well. What could cause every query to be rolled back in the database?

至于第二个问题,我的交易管理配置概述如下:

As for the second problem, my configuration of the transaction management is outlined below:

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/spring-context-3.0.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"
       default-autowire="byName">

<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) -->
<tx:advice id="txAdvice" transaction-manager="txManager">
  <!-- the transactional semantics... -->
  <tx:attributes>
    <!-- other methods use the default transaction settings (see below) -->
    <tx:method name="*" rollback-for="Exception" />
  </tx:attributes>
</tx:advice>

<!-- ensure that the above transactional advice runs for any execution
 of an operation defined by a service in the service package -->
<aop:config>
  <aop:pointcut id="serviceOperations" expression="execution(* foo.bar.service.*.*(..))"/>
  <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperations"/>
</aop:config>

<!-- similarly, don't forget the PlatformTransactionManager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>

<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="defaultAutoCommit" value="false" />
</bean>

<bean id="fooService" class="foo.bar.service.FooService" />

<bean id="barService" class="foo.bar.service.BarService" />

<bean id="zapService" class="foo.bar.service.ZapService" />

</beans>

在我试图解决这个问题的所有教程和论坛中,我相信我的配置应该是正确的。但是我并不完全理解aop和spring交易,所以我可能会遗漏一些关键的东西。

From all of the tutorials and forums that I have visited in trying to solve this problem, I believe that my configuration should be correct. However I do not fully understand aop and spring transactions so I may be missing something crucial.

如上所述,我可以追踪我的日志并查看代理作为事务方法,为我的服务类创建。但是,当我实际运行应用程序并跟踪日志时,我没有看到任何处理DataSourceTransactionManager或正在创建,提交,回滚等事务的语句。

As alluded to above, I can trace through my logs and see proxies, as well as transactional methods, being created for my service classes. However when I actually run the application and trace through the logs I don't see any statements dealing with the DataSourceTransactionManager or transactions being created, committed, rolled back, etc.

在我看来,实际上没有任何东西在运行,我非常困惑,因为我已经遵循了许多不同的教程并尝试了很多不同的方法,但它总是以这种情况结束。

It would appear to me that nothing is actually being run, and I am terribly confused as I have followed many different tutorials and tried this many different ways, but it always ends up with this situation.

我也很确定我已正确设置log4j属性以接收来自DataSourceTransactionManager的消息,但我在下面提供它们以确保它不仅仅是我的记录错误。

I am also fairly certain that I have my log4j properties set up correctly to receive messages from the DataSourceTransactionManager, but I am supplying them below to make sure that it is not just a logging error on my part.

我的log4j设置了以下记录器以尝试跟踪交易:

My log4j is set up with the following loggers to try and trace through the transactions:

log4j.logger.org.springframework=INFO, file
log4j.logger.org.springframework.jdbc.datasource=DEBUG, file
log4j.logger.org.springframework.transaction=DEBUG, file

注意:我在DEBUG上运行了顶级记录器,这是我验证正在创建服务代理的地方。

Note: I ran the top logger on DEBUG at one point, and that is where I verified that the service proxies were being created.

有没有人对可能发生的事情有任何见解?我现在相当困难,因为我确实看到一些涉及交易的部分,但我没有看到任何交易被使用的任何迹象。

Does anyone have any insights into what might be happening? I am rather stuck at the moment, as I do see some parts involved with transactions being created but I don't see any signs of any transactions being used whatsoever.

编辑

JB Nizet要求的其他信息。

Additional information as requested by JB Nizet.

我的整个申请表是注释驱动,所以我的服务bean用@Service注释,并通过基于名称的自动装配注入我的控制器。

My entire application is annotation-driven and so my service beans are annotated with @Service and injected into my controllers via name-based autowiring.

以下是我的一个服务类的示例(名称已更改,但会反映我的applicationContext.xml)。

The below is an example of one of my service classes (names have been changed but will reflect my applicationContext.xml).

@Service("zapService")
public class ZapService
{

    /**
     * Data access object which performs the database look up
     */
    private ZapDAO zapDAO;

    /**
     * Add the given zap to the database
     *
     * @param zap a populated zap
     */
    public void processNewZap(Zap zap)
    {
        zapDAO.processNewZap(zap);
    }
}

如您所见,我的服务类只是代理控制器类和dao类之间。 DAO是我实际处理数据库连接的地方。

As you can see, my service classes are simply proxies between the controller classes and the dao classes. The DAOs are where I actually handle database connections.

我相信我读到某个地方,在处理交易时,使服务交易,而不是dao类是首选。如果我错了,请纠正我。

I believe I read somewhere that making the services transactional, rather then the dao classes, was a preferred practice when dealing with transactions. Please correct me if I am wrong.

ZapDAO课程概述如下。

The ZapDAO class is outlined below.

@Repository("zapDAO")
public class ZapDAO
{

    /**
     * Log4j logger for this class
     */
    Logger logger = Logger.getLogger(ZapDAO.class);

    /**
     * Spring jdbc object to handle interacting with the database
     */
    private JdbcTemplate jdbcTemplate;

    public void processNewZap(Zap zap) {

        ... query constructing logic ...

        this.jdbcTemplate.update(INSERT_ZAP_QUERY_SQL);

    }

    public void setDataSource(DataSource dataSource)
    {
        Assert.notNull(dataSource, "You must supply a valid data source");

        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
}

我使用jdbcTemplate来处理我的连接和查询。

I use a jdbcTemplate to handle my connections and queries.

推荐答案

因此,经过几个小时的搜索,调试和撕掉我的头发,我终于偶然发现这个小宝石提供了所有答案。

So after hours upon hours of searching, debugging, and ripping my hair out, I finally stumbled upon this little gem which provided all the answers.

我从来没有怀疑过这样的问题,但是按照上面链接中列出的步骤完美地工作了。

I never would have suspected something like that to be the issue but following the steps outlined in the above link worked perfectly.

在我的调度中 - servlet.xml我最初声明我的组件扫描如下:

Inside my dispatch-servlet.xml I had originally declared my component-scan as follows:

<context:component-scan base-package="foo.bar"/>

这是我所有应用程序bean的父包。因此,如上面的链接所述,Spring使用dispatcher-servlet.xml中的服务bean从applicationContext.xml覆盖我的事务服务bean,该服务bean不知道事务。

Which is a parent package to all of my application beans. So, as described in the link above, Spring was overwriting my transactional service beans from the applicationContext.xml with the service beans from the dispatcher-servlet.xml which did not know about the transactions.

我所做的就是打破上面的组件扫描,只扫描包含非事务bean的文件夹。

All I did was break up the above component-scan to scan only the folders which contained non-transactional beans.

<context:component-scan base-package="foo.bar.controller"/>
<context:component-scan base-package="foo.bar.model"/>
<context:component-scan base-package="foo.bar.service.display"/>
<context:component-scan base-package="foo.bar.service.security"/>

<!-- foo.bar.service gets scanned in applicationContext.xml and includes 
transactions so we must make sure to not include it here. The transactional beans
will be overridden in that case -->

在此之后我的交易完全符合预期,我终于看到了交易的足迹和DataSourceTransactionManager in我的日志文件。这也修复了我在数据库中自动回滚的第一个初始问题。我想它一定与缺乏交易密切相关。

After this my transactions worked exactly as expected and I was finally seeing footprints of the transactions and the DataSourceTransactionManager in my log files. This also fixed my first initial problem of the automatic rollbacks in the database. I guess it must have been closely tied with the lack of transactions.

这篇关于Spring Jdbc声明式事务已创建但未执行任何操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆