Spring 6(非Boot)如何编程配置DataSource与事务管理器
解决方案:非Spring Boot环境下配置Spring 6事务管理器
你推测的问题根源完全正确——仅添加@EnableTransactionManagement只是启用了事务注解的支持,但Spring需要一个PlatformTransactionManager类型的Bean来处理实际的事务逻辑,非Spring Boot环境下不会自动创建这个Bean,导致@Transactional注解无法生效。
以下是两种适配你场景的配置方案,任选其一即可:
方案1:基于JPA EntityManager的配置(推荐)
这种方式贴合你当前使用EntityManager的代码习惯,通过LocalContainerEntityManagerFactoryBean管理JPA实体管理器,搭配JpaTransactionManager实现事务管理:
@Configuration @EnableTransactionManagement @ComponentScan(basePackages = "com.cypherf") // 确保Spring能扫描到你的Repository public class PersistenceConfig { // 配置JPA实体管理器工厂 @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); // 指定Hibernate作为JPA实现 HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); vendorAdapter.setShowSql(true); vendorAdapter.setFormatSql(true); emf.setJpaVendorAdapter(vendorAdapter); emf.setPackagesToScan("com.cypherf.model"); // 实体类所在包 emf.setJpaProperties(hibernateProperties()); // 加载Hibernate配置属性 emf.setDataSource(dataSource()); // 配置数据源 return emf; } // 配置数据库数据源 @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.h2.Driver"); dataSource.setUrl("jdbc:h2:./spring"); dataSource.setUsername("sa"); dataSource.setPassword(""); return dataSource; } // 封装Hibernate核心配置 private Properties hibernateProperties() { Properties props = new Properties(); props.put("hibernate.dialect", "org.hibernate.community.dialect.H2LegacyDialect"); props.put("hibernate.hbm2ddl.auto", "create-drop"); props.put("hibernate.show_sql", "true"); props.put("hibernate.format_sql", "true"); return props; } // 关键:配置事务管理器 @Bean public PlatformTransactionManager transactionManager(EntityManagerFactory emf) { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(emf); return transactionManager; } }
方案2:基于Hibernate SessionFactory的配置
如果你更倾向于保留原生Hibernate的SessionFactory配置,可以用这种方式,搭配HibernateTransactionManager:
@Configuration @EnableTransactionManagement @ComponentScan(basePackages = "com.cypherf") public class PersistenceConfig { // 配置Hibernate SessionFactory @Bean public LocalSessionFactoryBean sessionFactory() { LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); sessionFactory.setPackagesToScan("com.cypherf.model"); sessionFactory.setHibernateProperties(hibernateProperties()); return sessionFactory; } // 配置数据源(同方案1) @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.h2.Driver"); dataSource.setUrl("jdbc:h2:./spring"); dataSource.setUsername("sa"); dataSource.setPassword(""); return dataSource; } // Hibernate配置属性(同方案1) private Properties hibernateProperties() { Properties props = new Properties(); props.put("hibernate.dialect", "org.hibernate.community.dialect.H2LegacyDialect"); props.put("hibernate.hbm2ddl.auto", "create-drop"); props.put("hibernate.show_sql", "true"); props.put("hibernate.format_sql", "true"); return props; } // 配置Hibernate事务管理器 @Bean public PlatformTransactionManager transactionManager(SessionFactory sessionFactory) { HibernateTransactionManager transactionManager = new HibernateTransactionManager(); transactionManager.setSessionFactory(sessionFactory); return transactionManager; } // 可选:如果仍需使用EntityManager,从SessionFactory转换 @Bean public EntityManagerFactory entityManagerFactory(SessionFactory sessionFactory) { return sessionFactory.unwrap(EntityManagerFactory.class); } }
配置后的注意事项
- 确保你的
MessageRepository是通过Spring容器获取的实例(比如用@Autowired注入到服务类),而非手动new创建,否则Spring的AOP代理无法生效,@Transactional注解不会起作用。 @Transactional注解可以放在类上(所有方法生效),也可以单独标注在save方法上,按需调整即可。
内容的提问来源于stack exchange,提问作者Gaetan L.
相关产品推荐
相关产品推荐

