spring 即使没有@ translation/@EnableTransactionManagement,JPA事务也是如此

kq0g1dla  于 2023-09-29  发布在  Spring
关注(0)|答案(2)|浏览(135)

我试图理解事务是如何与Spring一起工作的。我有一个扩展CrudRepository的repository接口:

@Transactional
public interface MessageRepository extends CrudRepository<Message, Long> {
}

还有一个PersistenceConfig,我用它来创建我的BulletyManagerFactory和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;
    }
}

问题是,我使用一个logger来调试JpaTransactionManager,无论我是否使用注解@Transactional/@EnableTransactionManager,我都可以看到使用了事务:

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

所以,用这些有什么用?

oogrdqng

oogrdqng1#

当方法没有用@Transactional注解显式声明时,transactional被调用的原因是:
根据文档和Java文档
默认情况下,从CrudRepository继承的方法从SimpleJpaRepository继承事务配置。对于读取操作,事务配置readOnly标志被设置为真。所有其他事务都使用普通的@Transactional进行配置,以便应用默认事务配置。由事务存储库片段支持的存储库方法从实际片段方法继承事务属性。
要了解更多细节,我建议您阅读文档,主要是5.1.7。事务性

vybvopom

vybvopom2#

Spring-data-jpa默认会在CrudRepository上的每个非查询方法上配置@Transactional。这意味着即使您没有配置@Transactional/@EnableTransactionManagement@Transactional的内容仍然存在,因此您将在日志中看到它们。
您可以通过以下方式关闭此类默认行为:

@EnableJpaRepositories(enableDefaultTransactions=false)

其中enableDefaultTransactions具有以下含义:
配置是否为Spring Data JPA存储库启用默认事务。默认为true。如果禁用,则必须在配置事务的facade后面使用存储库(例如使用Spring的注解驱动的事务工具)或存储库方法来划分事务。
自己定义@EnableTransactionManagement@Transactional的意义在于,它为您定义所需的事务边界提供了更大的灵活性。您可以跨业务服务方法扩展它,甚至更广泛,但不仅仅限于存储库级别的方法。

相关问题