0

我有以下方法,在调用callBothMethodInvocation()方法后,我期待用户插入时执行insertUser()将回滚,因为 insertUserWithException() 发生异常。但是,当我检查数据库用户表时,表中存在实体。我错过了什么?我发现了类似的问题http://forum.springsource.org/showthread.php?108015-JDBC-Transaction-inner-methods-and-rollback但找不到确切的解决方案。

@Transactional(rollbackFor=Exception.class)    
private void callBothMethodInvocation() throws Exception {
    insertUser();
    insertUserWithException();      
}


public void insertUserWithException() throws Exception{
    throw new Exception("fake exception for rollback");
}

@Transactional(rollbackFor=Exception.class) 
public void insertUser(){
    int id = (int) (System.currentTimeMillis()%1000);
    System.out.println("Insert user id:"+id);
    User user = new User(id,"Test",22);
    testDao.insertUser(user);
}

弹簧配置:

<beans 
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"   
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
        http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.2.xsd"
    default-lazy-init="false">


    <context:component-scan base-package="com.mkyong" />

    <context:property-placeholder location="config.properties" />

    <bean id="helloBean" class="com.mkyong.common.HelloWorld">
        <property name="name" value="Ahmet" />
    </bean>

    <bean id="person" class="com.mkyong.common.Person">
        <constructor-arg type="java.lang.String" value="DefaultName"/>
        <constructor-arg type="int" value="30"/>
    </bean>

    <bean id="jmxAdapter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
        <property name="beans">
            <map>
                <entry key="SPRING:Name=TestRun">
                    <ref bean="jmxService" />
                </entry>
            </map>
        </property>
        <!-- managemethods property starts -->
        <property name="assembler">
            <bean
                class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
                <property name="managedInterfaces">
                    <value>com.mkyong.jmx.JmxCoreComands</value>
                </property>
            </bean>
        </property>
        <!-- managemethods property ends -->
    </bean>


    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${db.driver}"/>
        <property name="url" value="${db.url}"/>
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>      
    </bean>

    <!-- Cache Mekanizmasi -->  
    <ehcache:annotation-driven />
    <ehcache:config cache-manager="cacheManager">
        <ehcache:evict-expired-elements interval="60" />
    </ehcache:config>
    <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="configLocation"  value="classpath:ehcache.xml"/>
    </bean>

    <!-- Aspect Oriented Performance Log Mekanizmasi -->
    <aop:aspectj-autoproxy />
    <bean id="performanceLogger" class="com.mkyong.util.PerformanceLogger" />

</beans>

添加了以下配置:

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mkyong.common</groupId>
  <artifactId>SpringExample</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>SpringExample</name>
  <url>http://maven.apache.org</url>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

    <!-- Spring framework -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>3.2.2.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>3.2.2.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>3.2.3.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc14</artifactId>
        <version>10.2.0.3.0</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>3.2.3.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>com.googlecode.ehcache-spring-annotations</groupId>
      <artifactId>ehcache-spring-annotations</artifactId>
      <version>1.2.0</version>
    </dependency>



  </dependencies>
</project>
4

2 回答 2

0

您需要在 context.xml 中启用 Spring 事务

<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

这是一个工作测试

class X {
    @Autowired
    DataSource ds;

    @Transactional(rollbackFor = Exception.class)
    public void insert() throws Exception {
        new JdbcTemplate(ds).update("insert into t1 (c1) values ('1')");
        throw new Exception();
    }
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/transactions.xml")
public class Transactions {
    @Autowired
    X x;

    @Test
    public void test() throws Exception {
        x.insert();
    }
}

交易.xml

xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        ">
<context:annotation-config />

<bean class="X" />

<tx:annotation-driven />

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

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="url" value="jdbc:mysql://localhost/test" />
    <property name="username" value="root" />
    <property name="password" value="root" />
</bean>

于 2013-08-02T11:54:08.257 回答
0

看起来您没有配置 TransactionManager 或无法获取@Transactional.

尝试添加<tx:annotation-driven/>一个JpaTransactionManager名为transactionManager.

于 2013-08-02T11:34:16.960 回答