I'm trying to understand how transactions work with Spring. I have a repository interface extending CrudRepository:
@Transactional
public interface MessageRepository extends CrudRepository<Message, Long> {
}
And a PersistenceConfig that I use to create my EntityManagerFactory and TransactionManager:
@Configuration
@EnableTransactionManagement
public class PersistenceConfig {
final static Logger logger = LoggerFactory.getLogger(PersistenceConfig.class);
public static EntityManagerFactory emf = null;
@Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory());
}
@Bean
public EntityManagerFactory entityManagerFactory() {
if (emf == null) {
synchronized (EntityManagerFactory.class) {
if (emf == null) {
final StandardServiceRegistry sr = new StandardServiceRegistryBuilder()
.configure() // Configures setting from hibernate.cfg.xml
.build();
try {
emf = new MetadataSources(sr).buildMetadata().buildSessionFactory();
}
catch (Exception e) {
StandardServiceRegistryBuilder.destroy(sr);
throw e;
}
}
}
}
return emf;
}
}
Thing is, I use a logger to debug JpaTransactionManager, and no matter if I use the annotations @Transactional/@EnableTransactionManager, I can see transactions are used:
3576 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
3576 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Opened new EntityManager [SessionImpl(2090037997<open>)] for JPA transaction
[...]
3576 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Initiating transaction commit
3576 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Committing JPA transaction on EntityManager [SessionImpl(2090037997<open>)]
[...]
3576 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [SessionImpl(2090037997<open>)] after transaction
So, what's the point of using these?
The reason why transactional are invoked when the method is not explicitly declared with @Transactional
annotation is it:
According to documentation and Java docs
By default, methods inherited from CrudRepository inherit the transactional configuration from SimpleJpaRepository. For read operations, the transaction configuration readOnly flag is set to true. All others are configured with a plain @Transactional so that default transaction configuration applies. Repository methods that are backed by transactional repository fragments inherit the transactional attributes from the actual fragment method.
To have more details about it I suggest you to read documentation, mainly 5.1.7. Transactionality