簡體   English   中英

Spring聲明事務不起作用(事務未提交)

[英]Spring Declarative Transaction is not working (transaction not committed)

Spring Declarative Transaction無效(未提交)。

彈簧配置

  <!-- DATASOURCE -->

   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      <property name="driverClassName" value="${jdbc.driver}"/>
      <property name="url" value="${jdbc.url}"/>
      <property name="username" value="${jdbc.user}"/>
      <property name="password" value="${jdbc.password}"/>
      <property name="initialSize" value="${dbcp.initialSize}"/>
      <property name="maxActive" value="${dbcp.maxActive}"/>
      <property name="maxIdle" value="${dbcp.maxIdle}"/>
      <property name="maxWait" value="${dbcp.maxWait}"/>
      <property name="poolPreparedStatements" value="${dbcp.poolPreparedStatements}"/>
      <property name="validationQuery" value="select 1 from dual"/>
      <property name="testOnBorrow" value="${dbcp.testOnBorrow}"/>
      <property name="maxOpenPreparedStatements" value="${dbcp.maxOpenPreparedStatements}"/>
      <property name="logAbandoned" value="${dbcp.logAbandoned}"/>
      <property name="removeAbandoned" value="${dbcp.removeAbandoned}"/>
      <property name="removeAbandonedTimeout" value="${dbcp.removeAbandonedTimeout}"/>
      **<property name="defaultAutoCommit" value="false"/>**
   </bean>

  <!-- IBATIS -->

    <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocations" value="classpath:/config/ibatis/sqlMapConfig.xml"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
      <property name="sqlMapClient" ref="sqlMapClient"/>
    </bean>

  <!-- TRANSACTION -->

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

   <tx:advice id="txAdvice" transaction-manager="transactionManager">
      <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" isolation="READ_COMMITTED" timeout="10" read-only="false"/>
      </tx:attributes>
   </tx:advice>

    <aop:config>
        <aop:pointcut id="serviceMethods" expression="execution(public * com.store.web.front.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
    </aop:config>

控制器Bean

package com.store.web.front.controller;

    public interface TestTxControllerIF {
       public ModelAndView transaction();
    }

package com.store.web.front.controller;

    @Controller
    public class TestTxControllerImpl implements TestTxControllerIF {

        @Autowired
        protected TestTxServiceIF testService;

        Logger                    logger = Logger.getLogger(TestTxControllerIF.class);

        @Override
        @RequestMapping(value = "/test/tx.html")
        public ModelAndView transaction() {

            logger.info("# TestTxController.transaction() - " + testService);

            testService.transaction();
            return new ModelAndView("main");
        }
}

服務Bean

    package com.store.web.front.service;

        public interface TestTxServiceIF {
            public void transaction();
        }

    package com.store.web.front.service;

        @Service
        public class TestTxServiceImpl implements TestTxServiceIF {

            Logger logger = Logger.getLogger(TestTxServiceImpl.class);

            @Autowired
            protected TestDaoIF testDao;

            @Override
            public void transaction() {

                logger.info("# TestTxService.transaction()");

                Test test1 = new Test("111", "First");
                Test test2 = new Test("222", "Second");
                Test test3 = new Test("333", "Third");

                testDao.insertTest(test1);        
                logger.info("# Successfully inserted!!! - " + test1);

                testDao.insertTest(test2);        
                testDao.insertTest(test3);
            }
        }

道豆

package com.store.web.front.dao;

    public interface TestDaoIF {
        public void insertTest(Test test);
    }

package com.store.web.front.dao;

    @Repository
    public class TestDaoImpl extends AbstractIBatisDao implements TestDaoIF {    

        Logger logger = Logger.getLogger(TestTxServiceImpl.class);

        @Override
        public void insertTest(Test test) {

            logger.info("# TestDao.insertTest()");

            template.insert("test.insertTest", test);
        }
    }

結果與問題

部署並發送請求“/test/tx.html”后,事務執行沒有問題,但數據庫記錄不會保留。 我想,交易沒有提交。 問題是什么?

日志

DEBUG> 11:02:10 - DispatcherServlet with name 'spring-dispatcher' processing request for [/test/tx.html] ☜ DispatcherServlet.java:781
DEBUG> 11:02:10 - Invoking request handler method: public org.springframework.web.servlet.ModelAndView com.store.web.front.controller.TestTxControllerImpl.transaction() ☜ HandlerMethodInvoker.java:134
INFO > 11:02:10 - # TestTxController.transaction() - com.store.web.front.service.TestTxServiceImpl@126cb1a ☜ TestTxControllerImpl.java:23
INFO > 11:02:10 - # TestTxService.transaction() ☜ TestTxServiceImpl.java:25
INFO > 11:02:10 - # TestDao.insertTest() ☜ TestDaoImpl.java:20
DEBUG> 11:02:10 - Opened SqlMapSession [com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl@1bc345a] for iBATIS operation ☜ SqlMapClientTemplate.java:177
DEBUG> 11:02:10 - Fetching JDBC Connection from DataSource ☜ DataSourceUtils.java:112
DEBUG> 11:02:10 - Obtained JDBC Connection [jdbc:oracle:thin:@localhost:1521:XE, UserName=STORE, Oracle JDBC driver] for iBATIS operation ☜ SqlMapClientTemplate.java:194
DEBUG> 11:02:10 - Returning JDBC Connection to DataSource ☜ DataSourceUtils.java:312
INFO > 11:02:10 - # Successfully inserted!!! - Test [id=111, name=First] ☜ TestTxServiceImpl.java:33

我發現了這個問題的原因。 當DispatcherServlet加載事務聲明文件時,事務控制成功。 但是文件是由ContextLoaderListener加載的,事務控制並不好。 我不知道為什么會出現這種差異。 你能跟我解釋一下嗎?

豆子由BeanPostProcessor的“AOP東西”裝飾(在你的情況下可能由AspectJAwareAdvisorAutoProxyCreator )。 這些后處理器bean是特定於上下文實例的

如果在servlet上下文中配置AOP並且在根上下文中有目標bean(反之亦然),那么這就是未應用切入點的原因。

通常的做法是在根上下文中使用較低級別的bean(服務和DAO)以及AOP配置,並在servlet上下文中僅保留UI bean(MVC內容)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM