I have two repositories:
Consider the following situation:
@Transactional
public Player createPlayer(String locationName, String name) {
Location location = new Location(locationName);
location = locationRepository.save(location);
Player player = new Player(name, location);
return playerRepository.save(player);
}
There is constraint violation on player entity. I get: org.springframework.dao.DataIntegrityViolationException
After that, I check the database:
This method is annotated with @Transaction. So why the location is not rolled back? I was expecting that neither of this two were saved to DB on exception. How to rollback also the location?
EDIT:
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(JpaVendorAdapter adapter) {
...
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource);
entityManagerFactory.setJpaVendorAdapter(adapter);
entityManagerFactory.setPackagesToScan(packagesToScan);
entityManagerFactory.setJpaProperties(properties);
return entityManagerFactory;
}
@Bean
PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory)
{
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
@Bean
PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor() {
return new PersistenceAnnotationBeanPostProcessor();
}
@Bean
JpaVendorAdapter createVendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.MYSQL);
adapter.setDatabasePlatform(MySQL5Dialect.class.getName());
return adapter;
}
EDIT:
Interesting thing is that the entry is persisted to database just after this call:
location = locationRepository.save(location);
I've set a breakpoint just after this call and checked the database. The entry was inserted immediately.
@Transactional should work in case of Spring based transaction management if your spring configuration is properly setup. If it is still not working then you can programmatically rollback a transaction in catch block by adding following line of code-
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
Also, what the import you are using for @Transactional, make sure it is -
import org.springframework.transaction.annotation.Transactional
The problem was with MySQL. I didn't know that MyISAM doesn't support transactions.
The MySQL5InnoDBDialect is needed in order for transactions to rollback the database. This changed the engine from engine=MyISAM
to engine=InnoDB
. InnoDB Table Schemas support transactions.
I modified my spring boot 2.0 application.properties file and added the following:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
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.