@RunWith(SpringRunner.class)
@CustomTestContext
public class TransactionalTest {
@Autowired
private UserRepository userRepository;
private Log logger = LogFactory.getLog(getClass());
public void doSomething() {
try {
User user = new User();
user.setUsername("test"); // username has unique constraint
userRepository.save(user);
} catch (DataIntegrityViolationException e) {
logger.info("Wrong");
}
}
@Test
@Transactional
public void doTest() {
doSomething();
doSomething();
}
@Test
@Transactional
public void doTest2() {
doSomething();
doSomething();
}
}
当
doTest
在第二个DataIntegrityViolationException
调用中遇到doSomething
时,第一个doSomething
调用没有回滚,这导致用户名“ test”的用户仍然存在,并导致doTest2
的两个调用抛出doSomethong
。我期望的是,当事务方法遇到异常时,它将回滚到第一个带有
DataIntegrityViolationException
批注的方法运行之前的状态,在上述情况下,由于默认传播值,根本没有向数据库插入任何新用户。是@Transactional
。我将
REQUIRE
日志记录级别更改为JpaTransactionManager
,并得到如下所示的控制台:DEBUG o.s.o.jpa.JpaTransactionManager - Creating new transaction with name [com.ray.spring.test.TransactionalTest.doTest]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG o.s.o.jpa.JpaTransactionManager - Opened new EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
DEBUG o.s.o.jpa.JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@2ceca2ef]
INFO o.s.t.c.t.TransactionContext - Began transaction (1) for test context [DefaultTestContext@3b42121d testClass = TransactionalTest, testInstance = com.ray.spring.test.TransactionalTest@7a2ab862, testMethod = doTest@TransactionalTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41fa769c testClass = TransactionalTest, locations = '{file:src/main/resources/applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{file:src/main/resources/application.properties}', propertySourceProperties = '{mysql.Url = jdbc:mysql://localhost:3306/springtest?characterEncoding=UTF-8&serverTimezone=UTC}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@343e225a]; rollback [true]
DEBUG o.s.o.jpa.JpaTransactionManager - Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
DEBUG o.s.o.jpa.JpaTransactionManager - Participating in existing transaction
DEBUG org.hibernate.SQL - insert into User (password, username) values (?, ?)
DEBUG o.s.o.jpa.JpaTransactionManager - Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.ray.spring.model.User#1]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
DEBUG o.s.o.jpa.JpaTransactionManager - Participating in existing transaction
DEBUG org.hibernate.SQL - insert into User (password, username) values (?, ?)
WARN o.h.e.j.spi.SqlExceptionHelper - SQL Error: 1062, SQLState: 23000
ERROR o.h.e.j.spi.SqlExceptionHelper - Duplicate entry 'test' for key 'UK_jreodf78a7pl5qidfh43axdfb'
DEBUG o.s.o.jpa.JpaTransactionManager - Participating transaction failed - marking existing transaction as rollback-only
DEBUG o.s.o.jpa.JpaTransactionManager - Setting JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.ray.spring.model.User#1]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] rollback-only
INFO c.r.s.test.TransactionalTest - Wrong
DEBUG o.s.o.jpa.JpaTransactionManager - Initiating transaction rollback
DEBUG o.s.o.jpa.JpaTransactionManager - Rolling back JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.ray.spring.model.User#1]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
DEBUG o.s.o.jpa.JpaTransactionManager - Closing JPA EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] after transaction
INFO o.s.t.c.t.TransactionContext - Rolled back transaction for test context [DefaultTestContext@3b42121d testClass = TransactionalTest, testInstance = com.ray.spring.test.TransactionalTest@7a2ab862, testMethod = doTest@TransactionalTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41fa769c testClass = TransactionalTest, locations = '{file:src/main/resources/applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{file:src/main/resources/application.properties}', propertySourceProperties = '{mysql.Url = jdbc:mysql://localhost:3306/springtest?characterEncoding=UTF-8&serverTimezone=UTC}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]].
// doTest2() below
DEBUG o.s.o.jpa.JpaTransactionManager - Creating new transaction with name [com.ray.spring.test.TransactionalTest.doTest2]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG o.s.o.jpa.JpaTransactionManager - Opened new EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
DEBUG o.s.o.jpa.JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@17229821]
INFO o.s.t.c.t.TransactionContext - Began transaction (1) for test context [DefaultTestContext@3b42121d testClass = TransactionalTest, testInstance = com.ray.spring.test.TransactionalTest@e829999, testMethod = doTest2@TransactionalTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41fa769c testClass = TransactionalTest, locations = '{file:src/main/resources/applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{file:src/main/resources/application.properties}', propertySourceProperties = '{mysql.Url = jdbc:mysql://localhost:3306/springtest?characterEncoding=UTF-8&serverTimezone=UTC}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@343e225a]; rollback [true]
DEBUG o.s.o.jpa.JpaTransactionManager - Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
DEBUG o.s.o.jpa.JpaTransactionManager - Participating in existing transaction
DEBUG org.hibernate.SQL - insert into User (password, username) values (?, ?)
WARN o.h.e.j.spi.SqlExceptionHelper - SQL Error: 1062, SQLState: 23000
ERROR o.h.e.j.spi.SqlExceptionHelper - Duplicate entry 'test' for key 'UK_jreodf78a7pl5qidfh43axdfb'
DEBUG o.s.o.jpa.JpaTransactionManager - Participating transaction failed - marking existing transaction as rollback-only
DEBUG o.s.o.jpa.JpaTransactionManager - Setting JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] rollback-only
INFO c.r.s.test.TransactionalTest - Wrong
DEBUG o.s.o.jpa.JpaTransactionManager - Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
DEBUG o.s.o.jpa.JpaTransactionManager - Participating in existing transaction
DEBUG org.hibernate.SQL - insert into User (password, username) values (?, ?)
WARN o.h.e.j.spi.SqlExceptionHelper - SQL Error: 1062, SQLState: 23000
ERROR o.h.e.j.spi.SqlExceptionHelper - Duplicate entry 'test' for key 'UK_jreodf78a7pl5qidfh43axdfb'
DEBUG o.s.o.jpa.JpaTransactionManager - Participating transaction failed - marking existing transaction as rollback-only
DEBUG o.s.o.jpa.JpaTransactionManager - Setting JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] rollback-only
INFO c.r.s.test.TransactionalTest - Wrong
DEBUG o.s.o.jpa.JpaTransactionManager - Initiating transaction rollback
DEBUG o.s.o.jpa.JpaTransactionManager - Rolling back JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
DEBUG o.s.o.jpa.JpaTransactionManager - Closing JPA EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] after transaction
INFO o.s.t.c.t.TransactionContext - Rolled back transaction for test context [DefaultTestContext@3b42121d testClass = TransactionalTest, testInstance = com.ray.spring.test.TransactionalTest@e829999, testMethod = doTest2@TransactionalTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@41fa769c testClass = TransactionalTest, locations = '{file:src/main/resources/applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{file:src/main/resources/application.properties}', propertySourceProperties = '{mysql.Url = jdbc:mysql://localhost:3306/springtest?characterEncoding=UTF-8&serverTimezone=UTC}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]].
似乎它回滚了,但不影响第一个
DEBUG
调用。更新:
我按如下方式编辑代码:
@Transactional
public void doSomething() {
logger.info("First save");
userRepository.save(new User("test", "test"));
logger.info("Second save");
userRepository.save(new User("test", "test"));
}
@Test
@Transactional
public void doTest() {
doSomething();
}
@Test
@Transactional
public void doTest2() {
doSomething();
}
我已经将
doSomething
添加到@transactional
并从doSomething()
抛出异常,但是得到了相同的结果:DEBUG o.s.o.jpa.JpaTransactionManager - Creating new transaction with name [com.ray.spring.test.TransactionalTest.doTest]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG o.s.o.jpa.JpaTransactionManager - Opened new EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
DEBUG o.s.o.jpa.JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@42d6c12d]
INFO o.s.t.c.t.TransactionContext - Began transaction (1) for test context [DefaultTestContext@7a2ab862 testClass = TransactionalTest, testInstance = com.ray.spring.test.TransactionalTest@33188612, testMethod = doTest@TransactionalTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@40113163 testClass = TransactionalTest, locations = '{file:src/main/resources/applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{file:src/main/resources/application.properties}', propertySourceProperties = '{mysql.Url = jdbc:mysql://localhost:3306/springtest?characterEncoding=UTF-8&serverTimezone=UTC}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@1a07bf6]; rollback [true]
INFO c.r.s.test.TransactionalTest - First save
DEBUG o.s.o.jpa.JpaTransactionManager - Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
DEBUG o.s.o.jpa.JpaTransactionManager - Participating in existing transaction
DEBUG org.hibernate.SQL - insert into User (password, username) values (?, ?)
INFO c.r.s.test.TransactionalTest - Second save
DEBUG o.s.o.jpa.JpaTransactionManager - Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.ray.spring.model.User#1]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
DEBUG o.s.o.jpa.JpaTransactionManager - Participating in existing transaction
DEBUG org.hibernate.SQL - insert into User (password, username) values (?, ?)
WARN o.h.e.j.spi.SqlExceptionHelper - SQL Error: 1062, SQLState: 23000
ERROR o.h.e.j.spi.SqlExceptionHelper - Duplicate entry 'test' for key 'UK_jreodf78a7pl5qidfh43axdfb'
DEBUG o.s.o.jpa.JpaTransactionManager - Participating transaction failed - marking existing transaction as rollback-only
DEBUG o.s.o.jpa.JpaTransactionManager - Setting JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.ray.spring.model.User#1]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] rollback-only
DEBUG o.s.o.jpa.JpaTransactionManager - Initiating transaction rollback
DEBUG o.s.o.jpa.JpaTransactionManager - Rolling back JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.ray.spring.model.User#1]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
DEBUG o.s.o.jpa.JpaTransactionManager - Closing JPA EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] after transaction
INFO o.s.t.c.t.TransactionContext - Rolled back transaction for test context [DefaultTestContext@7a2ab862 testClass = TransactionalTest, testInstance = com.ray.spring.test.TransactionalTest@33188612, testMethod = doTest@TransactionalTest, testException = org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [UK_jreodf78a7pl5qidfh43axdfb]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement, mergedContextConfiguration = [MergedContextConfiguration@40113163 testClass = TransactionalTest, locations = '{file:src/main/resources/applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{file:src/main/resources/application.properties}', propertySourceProperties = '{mysql.Url = jdbc:mysql://localhost:3306/springtest?characterEncoding=UTF-8&serverTimezone=UTC}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]].
\\ doTest2() below
DEBUG o.s.o.jpa.JpaTransactionManager - Creating new transaction with name [com.ray.spring.test.TransactionalTest.doTest2]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG o.s.o.jpa.JpaTransactionManager - Opened new EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
DEBUG o.s.o.jpa.JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@22d9ca63]
INFO o.s.t.c.t.TransactionContext - Began transaction (1) for test context [DefaultTestContext@7a2ab862 testClass = TransactionalTest, testInstance = com.ray.spring.test.TransactionalTest@484149eb, testMethod = doTest2@TransactionalTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@40113163 testClass = TransactionalTest, locations = '{file:src/main/resources/applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{file:src/main/resources/application.properties}', propertySourceProperties = '{mysql.Url = jdbc:mysql://localhost:3306/springtest?characterEncoding=UTF-8&serverTimezone=UTC}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@1a07bf6]; rollback [true]
INFO c.r.s.test.TransactionalTest - First save
DEBUG o.s.o.jpa.JpaTransactionManager - Found thread-bound EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
DEBUG o.s.o.jpa.JpaTransactionManager - Participating in existing transaction
DEBUG org.hibernate.SQL - insert into User (password, username) values (?, ?)
WARN o.h.e.j.spi.SqlExceptionHelper - SQL Error: 1062, SQLState: 23000
ERROR o.h.e.j.spi.SqlExceptionHelper - Duplicate entry 'test' for key 'UK_jreodf78a7pl5qidfh43axdfb'
DEBUG o.s.o.jpa.JpaTransactionManager - Participating transaction failed - marking existing transaction as rollback-only
DEBUG o.s.o.jpa.JpaTransactionManager - Setting JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] rollback-only
DEBUG o.s.o.jpa.JpaTransactionManager - Initiating transaction rollback
DEBUG o.s.o.jpa.JpaTransactionManager - Rolling back JPA transaction on EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
DEBUG o.s.o.jpa.JpaTransactionManager - Closing JPA EntityManager [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] after transaction
INFO o.s.t.c.t.TransactionContext - Rolled back transaction for test context [DefaultTestContext@7a2ab862 testClass = TransactionalTest, testInstance = com.ray.spring.test.TransactionalTest@484149eb, testMethod = doTest2@TransactionalTest, testException = org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [UK_jreodf78a7pl5qidfh43axdfb]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement, mergedContextConfiguration = [MergedContextConfiguration@40113163 testClass = TransactionalTest, locations = '{file:src/main/resources/applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{file:src/main/resources/application.properties}', propertySourceProperties = '{mysql.Url = jdbc:mysql://localhost:3306/springtest?characterEncoding=UTF-8&serverTimezone=UTC}', contextCustomizers = set[[empty]], contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]].
它具有行
doSomething
,但是Participating transaction failed - marking existing transaction as rollback-only
在第一次尝试时仍然失败,这意味着具有“测试”名称的用户已经存在。这是否意味着当同一事务中发生某些异常时,第一个
doTest2
无法回滚?CustomTestContxt.java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ContextConfiguration("file:src/main/resources/applicationContext.xml")
@TestPropertySource(
locations = {"file:src/main/resources/application.properties"},
properties = {"mysql.Url = jdbc:mysql://localhost:3306/springtest?characterEncoding=UTF-8&serverTimezone=UTC"})
public @interface CustomTestContext {
}
更新2:
@Test
@Transactional
@Rollback
public void doTest() {
entityManager.persist(new User("test", "test"));
}
@Test
@Tranactional
public void doTest2() {
logger.info(entityManager.find(User.class, 1L));
}
并记录:
INFO c.r.s.test.TransactionalTest - User{id=1, username='test', password='test', roles=[]}
最佳答案
doSomething()正在捕获异常。
仅当在@Transactional注释的方法中抛出RuntimeException时,才会回滚事务。
如果要保留原样的代码,则必须在doSomething()中手动回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
第二个选项是将doSomething()标记为事务性的,然后不捕获事务。然后,必须在测试方法中完成事务处理。
关于java - Spring 交易未正确回滚,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48151514/