将EJB应用迁移至Spring时访问EntityManager触发空指针异常求助
问题诊断与解决方案
核心原因:Spring未正确托管DAO Bean或未完成JPA配置,导致EntityManager未被注入
以下是具体的排查和修复步骤:
确保DAO被Spring容器托管并启用注解支持
Spring只有在管理Bean实例时,才会处理@PersistenceContext和@Transactional注解:- 在
ExampleDAOBean类上添加Spring的@Repository注解(DAO层专用注解,自带异常转换功能); - 在Spring的context.xml中配置组件扫描,确保能扫描到DAO所在包:
<context:component-scan base-package="com.your.dao.package"/> - 启用注解驱动的事务管理,同时确认
@Transactional导入的是org.springframework.transaction.annotation.Transactional(而非EJB的同名注解):<tx:annotation-driven transaction-manager="transactionManager"/>
- 在
添加Spring JPA核心配置,加载persistence.xml
仅靠persistence.xml无法让Spring识别JPA配置,必须在context.xml中配置LocalContainerEntityManagerFactoryBean来加载指定的持久化单元:<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="PersonInfo"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> </property> </bean>配置JTA事务管理器
由于你的persistence-unit使用transaction-type="JTA",需要配置对应的JTA事务管理器:<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="dataSource" ref="paymentsDS"/> </bean>同时确保
paymentsDS数据源在Spring中正确定义,如果是应用服务器托管的数据源,通过JNDI lookup获取:<jee:jndi-lookup id="paymentsDS" jndi-name="paymentsDS" resource-ref="true"/>清理persistence.xml中的冗余配置
移除tomee.jpa.cdi属性,这是TomEE的特定配置,在纯Spring环境中会干扰JPA处理:<!-- 移除这一行 --> <property name="tomee.jpa.cdi" value="false" />移除自定义EntityManager的getter/setter
自定义的setEntityManager和getEntityManager可能干扰Spring的注入逻辑,直接使用@PersistenceContext注入的字段即可,无需额外封装:@Repository @Transactional(propagation = Propagation.REQUIRES_NEW) public class ExampleDAOBean implements IExampleDAOBean { @PersistenceContext(unitName = "PersonInfo") private EntityManager entityManager; @Override public List<PersonPersist> findAll(String sourceType) { List<PersonPersist> persistList = new ArrayList<>(); try { Query query = entityManager.createNamedQuery(PersonPersist.FIND_ALL); persistList = (List<PersonPersist>) query.getResultList(); } catch (NoResultException noResultException) { } return persistList; } }
内容的提问来源于stack exchange,提问作者Mounika
相关产品推荐
相关产品推荐

