Spring Data JPA部署JBoss 5.2数据未写入数据库问题排查
刚帮几个团队排查过类似的EJB转Spring Data JPA的适配问题,结合你的症状(PrePersist触发但PostPersist无响应、Hibernate标记实体为托管却从不提交),核心问题肯定是Spring的EntityManager和JBoss容器的JTA事务没绑定到位——单元测试用的是Spring本地事务(适配H2),但JBoss 5.2是Java EE容器,默认走JTA事务,两者的上下文脱节了。下面是针对性的修复步骤:
1. 修正EntityManagerFactory的JTA事务配置
你的LocalContainerEntityManagerFactoryBean需要明确告诉Hibernate使用JBoss的JTA事务平台,添加以下JPA属性:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="springbatch.repositoryDataSource" /> <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" /> <property name="jpaProperties"> <props> <!-- 原有dialect配置 --> <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> <!-- 新增JTA相关配置 --> <prop key="hibernate.transaction.jta.platform">org.hibernate.transaction.JBossTransactionManagerLookup</prop> <prop key="javax.persistence.transactionType">JTA</prop> <prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop> </props> </property> </bean>
这一步是让Hibernate适配JBoss的JTA事务环境,避免用本地事务模式运行。
2. 切换到JtaTransactionManager
把原来的DataSourceTransactionManager替换成Spring的JTA事务管理器,绑定到JBoss的容器事务:
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManagerName" value="java:/TransactionManager"/> <property name="userTransactionName" value="java:comp/UserTransaction"/> </bean>
同时确保事务驱动注解指定这个管理器:
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
proxy-target-class="true"是关键——JBoss 5.2的类加载器机制特殊,CGLIB代理比JDK动态代理更可靠,能确保@Transactional注解被正确拦截。
3. 检查PersistenceUnit和数据源配置
- 你的
persistence.xml里的持久化单元必须明确是JTA类型:<persistence-unit name="yourPersistenceUnit" transaction-type="JTA"> <jta-data-source>springbatch.repositoryDataSource</jta-data-source> <!-- 实体类配置 --> </persistence-unit> - 确认
springbatch.repositoryDataSource是JBoss中配置的JTA数据源(在*-ds.xml里用<jta-data-source>定义,而非<local-tx-datasource>),非JTA数据源无法参与容器事务。
4. 验证EntityManager注入方式
不要用@Autowired注入EntityManager,改用@PersistenceContext:
@PersistenceContext private EntityManager entityManager;
这会注入容器托管的EntityManager,自动关联到JTA事务上下文;而@Autowired拿到的是本地EntityManager,无法参与容器事务。
最后验证逻辑
调整后,你可以在业务方法里手动打印事务状态,或者开启Hibernate的show_sql和hibernate.transaction.flush_before_completion=true,观察日志里是否有COMMIT语句。如果PostPersist触发了,说明事务已经正常提交。
内容的提问来源于stack exchange,提问作者Mike Rother

