配置JpaTransactionManager后执行删除查询仍抛TransactionRequiredException
问题原因及修复方案
核心问题1:手动创建EntityManager,脱离Spring事务管控
你在test方法里通过dbConfig.getEntityManagerFactory().createEntityManager()手动创建了新的EntityManager,这个实例不在Spring@Transactional注解开启的事务范围内。Spring的事务管理只对它自身注入的EntityManager实例生效,手动创建的EntityManager完全不受其管控,因此执行更新/删除操作时会抛出事务缺失异常。
核心问题2:DBConfig存在重复创建EntityManagerFactory的错误
在myTransactionManager()方法中,你调用getLocalContainerEntityManagerFactoryBean()重新创建了一个LocalContainerEntityManagerFactoryBean实例,这会导致事务管理器使用的EntityManagerFactory,和getEntityManagerFactory()返回的实例不是同一个,进一步造成事务上下文不匹配。
另外代码里还有个低级错误:LocalContainerEntityManagerFactoryBean.setPersistenceUnitName("PERSISTENCE_UNIT");是静态调用,但setPersistenceUnitName是实例方法,应该改为localContainerEntityManagerFactoryBean.setPersistenceUnitName("PERSISTENCE_UNIT");
具体修复步骤
1. 修正DBConfig配置,确保EntityManagerFactory单例
@Configuration @EnableTransactionManagement class DBConfig{ @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); Properties properties = new Properties(); properties.put("hibernate.dialect", "org.hibernate.dialect.DB2Dialect"); properties.put("hibernate.show_sql", true); properties.put("hibernate.jdbc.batch_size", 5000); properties.put("hibernate.hbm2ddl.auto", ""); properties.put("hibernate.id.new_generator_mappings", false); // 修正拼写错误:nappings → mappings em.setJpaProperties(properties); em.setPackagesToScan("**"); // 建议替换为具体实体包路径,比如com.yourproject.entity em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); em.setDataSource(getDB2DataSource("<DB_SERVER_NAME>")); em.setPersistenceUnitName("PERSISTENCE_UNIT"); // 修正为实例方法调用 em.afterPropertiesSet(); return em; } @Bean("myTransactionManager") public JpaTransactionManager myTransactionManager(EntityManagerFactory entityManagerFactory) { // 直接注入Spring管理的EntityManagerFactory,避免重复创建 return new JpaTransactionManager(entityManagerFactory); } // 保留你的数据源实现方法 private DataSource getMSSQLDataSource(String DBServerName) { // 你的MSSQL数据源逻辑 } private DataSource getDB2DataSource(String DBServerName) { // 你的DB2数据源逻辑 } }
2. 修改Test类,使用Spring注入的EntityManager
@Component public class Test { @PersistenceContext(unitName = "PERSISTENCE_UNIT") // 和配置中的持久化单元名一致 private EntityManager entityManager; @Transactional("myTransactionManager") public void test() { Query query = entityManager.createNativeQuery("<Some Delete Query>"); query.executeUpdate(); // 现在会在Spring事务上下文内执行 } }
额外注意事项
- 永远不要手动创建EntityManager/EntityManagerFactory,依赖Spring的依赖注入获取受事务管理的实例。
setPackagesToScan("**")会扫描所有包,可能拖慢启动速度,建议指定具体的实体类包路径。
内容的提问来源于stack exchange,提问作者Foos
相关产品推荐
相关产品推荐

