由Spring注入的EntityManager在首次使用时为null

时间:2011-10-06 14:23:25

标签: spring jpa

我正在开发一个实现spring + hibernate entitymanager

的基本webapp

我完全按照这篇文章的描述设置我的dao和上下文: http://blog.springsource.com/2006/08/07/using-jpa-in-spring-without-referencing-spring/

并为其创建了一个测试,如下所示: http://lstierneyltd.com/blog/development/examples/unit-testing-spring-apps-with-runwithspringjunit4classrunner-class/

出于某种原因,当我尝试访问entitymanager来创建查询时,它的null。

但是,通过在entitymanager的setter方法中设置断点,我可以看到Spring正确地注入它,并且字段正在初始化。

有关为什么在setter返回后实体管理器可能会被取消的任何线索?

编辑: 我设置断点的dao代码:

public class ProductDaoImpl implements ProductDao {

private EntityManager entityManager;

@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
    this. entityManager = entityManager;
}

public Collection loadProductsByCategory(String category) {
    return entityManager.createQuery("from Product p where p.category = :category")
        .setParameter("category", category).getResultList();
}
}

1 个答案:

答案 0 :(得分:0)

我认为你拥有的<tx:annotation-driven/>告诉Spring将事务建议放在任何有@Transactional注释的类或方法上。

应在服务/业务层定义交易,因此通常在服务中调用ProductDaoImpl拥有@Transactional。 e.g。

pubic class ProductService {

    @Resource(...)   // inject it the way you like e.g. @Autowired / Setter / Constructor injection, etc..
    ProductDao yourProductDao;

    @Transactional
    public List<Product> findCarProducts {
        yourProductDao.loadProductsByCategory( "car" );
    }
}

(或者,您可以使用基于XML的事务配置)

现在,您对DAO的实际调用将是within一次交易=&gt;这对于entityManager / Hibernate Session非常重要。否则,您会看到所有常见错误:例如entityManager为null,entityManager关闭等。

如果您想单独测试DAO,则必须确保您的测试用例通过@TransactionConfiguration包含在事务中。例如,如果您的事务管理器bean定义为:

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

您的DAO测试将包含此bean名称:

@ContextConfiguration
@TransactionConfiguration(transactionManager="txManager", defaultRollback=false)
public class ProductDaoTransactionalTests {
    // your use cases here..
}

您可以在Spring Documentation

中详细了解交易测试