简体   繁体   中英

Spring MVC 4 service @tTransactional doesn't work

1. Spring MVC application-context.xml

<tx:annotation-driven/>

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

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

2. Service impl class

@Override
@Transactional
public void deleteCommentAndFiles(int commentId) {
    int deletedCommentCount = commentDAO.deleteComment(commentId);
    int deletedFileCount = fileDAO.deleteFiles(commentId);

    if (deletedCommentCount != 1) {
        throw new IncorrectUpdateSemanticsDataAccessException("Deleted comment not 1 [deletedCount : " + deletedCommentCount);
    }

    if (deletedFileCount != 1) {
        throw new IncorrectUpdateSemanticsDataAccessException("Deleted file not 1 [deletedCount : " + deletedCommentCount);
    }

}

3. Test Case

@Test
public void rollbackT() {
    boolean hasException = false;
    int sizeBeforDelete = commentDAO.selectCountByArticle(1);

    try {
        commentService.deleteCommentAndFiles(1);
    } catch (RuntimeException e) {
        hasException = true;
    }

    Assert.assertTrue(hasException);
    Assert.assertEquals(sizeBeforDelete, commentDAO.selectCountByArticle(1));

}

in Test case

first Assert.assertTrue(hasException); is passed but

Assert.assertEquals(sizeBeforDelete, commentDAO.selectCountByArticle(1)) this case fail Expected : 1 but Actual : 0

this second TC fail mean Exception is occur but doesn't rollback delete comment

deleteCommentAndFiles method throw exception but doesn't rollback

Im trying to use @Transactional(propagation=Propagation.REQUIRED, rollbackFor={IncorrectUpdateSemanticsDataAccessException.class})

but same doesn't work

why @Transactional annotaion doesn't work?

I've also had the same issue. I moved the @transactional to the controller in order to works.

@EnableTransactionManagement and only looks for @Transactional on beans in the same application context they are defined in. This means that, if you put annotation driven configuration in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services. See Section 21.2, “The DispatcherServlet” for more information.

The database has to support transactions. In case of MySQL you need to create a table with type of InnoDB, BDB or Genini.

Per default myisam does not support transactions.

I didn't see your main test class, but i assume you use the default spring configuration for junit :

By default, a test is launched on his own implicit transaction. when you call your service, it start a "sub" logical transaction (which is a part of the test transaction, because you didn't use require_new for the propagation). when this transaction failed, the main transaction is marked for rollback, but the rollback is not done until the main transaction has finished, when the test end

If you want to test a rollback, you shouldn't use this implicit transaction, launched by the test framework, or you can use TestTransaction.end() before your assertions to force this transaction to be committed or rollback.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM