我在tomcat 7上使用Hibernate和Weld CDI运行一个项目。我已经编写了一个ServletContextListener来在应用程序启动期间创建EntityManagerFactory和EntityManager。
public class PersistenceListener implements ServletContextListener {
private static EntityManagerFactory entityManagerFactory;
public void contextInitialized(ServletContextEvent sce){
ServletContext context = sce.getServletContext();
entityManagerFactory = Persistence.createEntityManagerFactory("hibernate-test");
}
public void contextDestroyed(ServletContextEvent sce) {
entityManagerFactory.close();
}
public static EntityManager createEntityManager() {
if (entityManagerFactory == null) {
throw new IllegalStateException("Context is not initialized yet.");
}
return entityManagerFactory.createEntityManager();
}
}
我可以在我的测试类中使用我的entityManager(它是一个arquillian测试类),只需通过以下代码创建它
EntityManager em = PersistenceListener.createEntityManager();
em.getTransaction().begin();
em.createQuery("delete from Game").executeUpdate();
em.getTransaction().commit();
这是我的测试类的完整代码
@RunWith(Arquillian.class)
public class HibernateTestSample {
@Deployment
public static WebArchive createTestArchive()
{
MavenDependencyResolver resolver = DependencyResolvers.use(
MavenDependencyResolver.class).loadMetadataFromPom("pom.xml");
WebArchive webArchive= ShrinkWrap
.create(WebArchive.class, "ROOT.war")
.addClasses(CdiTestBean.class,HibernateListener.class,PersistenceListener.class)
.addAsLibraries(
resolver.artifact("org.jboss.weld.servlet:weld-servlet")
// .artifact("org.hibernate.javax.persistence:hibernate-jpa-2.0-api")
.artifact("org.apache.tomcat:tomcat-dbcp")
.artifact("org.hibernate:hibernate-entitymanager")
.artifact("org.hibernate:hibernate-validator")
.artifact("org.hibernate:hibernate-core")
.artifact("com.h2database:h2")
.artifact("mysql:mysql-connector-java")
.resolveAs(GenericArchive.class))
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
.addAsWebInfResource("test-persistence.xml", "classes/META-INF/persistence.xml")
.addAsWebInfResource("hibernate.cfg.xml", "classes/hibernate.cfg.xml")
// .addAsWebInfResource("context.xml", "classes/META-INF/context.xml")
.addAsManifestResource("context.xml", "context.xml")
.setWebXML("hibernate-web.xml");
System.out.println(webArchive.toString(true));
return webArchive;
}
@Test
public void myTest()
throws Exception {
EntityManager em = PersistenceListener.createEntityManager();
em.getTransaction().begin();
em.createQuery("delete from Game").executeUpdate();
em.getTransaction().commit();
...............
.......
...
}
}
但我想将我的entityManager注入我的班级。我读in an other post我不能在课堂上使用@PersistenceContext,因此我决定使用生产者来注入我的实体经理。但它对我不起作用,请告诉我这里我做错了什么(我是CDI的新手)
这是我新的ServletContextListener
public class PersistenceListener implements ServletContextListener {
private static EntityManagerFactory entityManagerFactory;
@Produces
private EntityManager entityManager;
public void contextInitialized(ServletContextEvent sce){
ServletContext context = sce.getServletContext();
entityManagerFactory = Persistence.createEntityManagerFactory("hibernate-test");
createEntityManager();
}
public void contextDestroyed(ServletContextEvent sce) {
entityManagerFactory.close();
}
public void createEntityManager() {
if (entityManagerFactory == null) {
throw new IllegalStateException("Context is not initialized yet.");
}
this.entityManager = entityManagerFactory.createEntityManager();
}
我正在注入我的测试类
@Inject
private EntityManager em;
它为空
答案 0 :(得分:3)
通过实现ServletContextListener通过Servlet规范创建的实例与CDI稍后将创建的用于解析@Produces
字段的实例不同。
此外,我推荐这篇关于EntityManager的信息性博文:http://struberg.wordpress.com/2012/04/25/is-there-a-way-to-fix-the-jpa-entitymanager/
它可能会略显过时,因为如果我没记错的话,我在deltaspike的作品中看到了@TransactionScoped。
最后,你可能已经想到了一个单独的EntityManager并不是你想要的,但为了完整起见,使用Deltaspike的CdiCtrl和Deltspike Core的BeanProvider可以在一定程度上修复ContextListener和CDI之间的协同作用。
如何将CDI ApplicationScope附加到当前线程http://struberg.wordpress.com/2012/03/17/controlling-cdi-containers-in-se-and-ee/
然后你可以拾取一个用@ApplicationScoped
注释的bean并进行设置。取件由MyBean myBean = BeanProvider.getContextualReference(MyBean.class, false);
http://deltaspike.apache.org/deltaspike/core.html
希望CDI 1.1能让它更流畅
更新:关于Deltaspike列表的讨论是在大约一个月内将0.5发布为较小版本。希望新的Servlet模块能很好地解决这个问题。
https://issues.apache.org/jira/browse/DELTASPIKE-376 https://issues.apache.org/jira/browse/DELTASPIKE-377
答案 1 :(得分:1)
您的@Produces
方法需要createEntityManager
,而不是字段。