Java 能够在Seam 3中@InjectEntityManager的配置

Java 能够在Seam 3中@InjectEntityManager的配置,java,configuration,persistence,cdi,seam3,Java,Configuration,Persistence,Cdi,Seam3,在我的项目中,我使用了Seam 3,在使用@Inject注释注入EntityManager时遇到了问题。我确信有某种配置可以确保EnityManager知道要使用哪个PersistenceUnit。例如,使用EJB可以键入: @PersistenceContext(unitName="MY_PERSISTENCE_UNIT_NAME") private EntityManager eManager; 在persistence.xml文件中配置了哪个持久化单元。以下是我的伪配置: <?xm

在我的项目中,我使用了
Seam 3
,在使用
@Inject
注释注入
EntityManager
时遇到了问题。我确信有某种配置可以确保
EnityManager
知道要使用哪个
PersistenceUnit
。例如,使用
EJB
可以键入:

@PersistenceContext(unitName="MY_PERSISTENCE_UNIT_NAME")
private EntityManager eManager;
persistence.xml
文件中配置了哪个持久化单元。以下是我的伪配置:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
    xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="MY_PERSISTENCE_UNIT_NAME" transaction-type="JTA">

        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:jboss/TimeReportDS</jta-data-source>
        <mapping-file>META-INF/orm.xml</mapping-file> 

        <class>....</class>
        <class>....</class>
        <class>....</class>

        <properties>

            <property name="jboss.entity.manager.factory.jndi.name"
                value="java:/modelEntityManagerFactory" />

            <!-- PostgreSQL Configuration File -->
            <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
            <property name="hibernate.connection.password" value="password" />
            <property name="hibernate.connection.url" value="jdbc:postgresql://192.168.2.125:5432/t_report" />
            <property name="hibernate.connection.username" value="username" />

            <!-- Specifying DB Driver, providing hibernate cfg lookup
                 and providing transaction manager configuration -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
            <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/>
            <property name="hibernate.transaction.manager_lookup_class"
                value="org.hibernate.transaction.JBossTransactionManagerLookup" />
            <property name="hibernate.archive.autodetection" value="class" />

            <!-- Useful configuration during development - developer can see structured SQL queries -->
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="false" />

        </properties>
    </persistence-unit>
</persistence>  
标记内。Seam 2中的下一步是添加:

<property name="jboss.entity.manager.factory.jndi.name"
                value="java:/modelEntityManagerFactory" />
但是seam 3中没有文件
components.xml
。在
@Inject
注释中也没有属性
unitName
来指定持久化单元

因此,请帮助我配置我的项目,以便我可以将
@Inject
EntityManager
一起使用,如网上的许多示例所示

我使用
Postgres
数据库和
jbossas7

编辑:添加示例。我不在
实体
类中使用
实体管理器

@Named("validateReportAction")
@SessionScoped
public class ValidateReportAction extends ReportAction implements Serializable {

    private static final long serialVersionUID = -2456544897212149335L;

    @Inject
    private EntityManager em;
...
}  
在此
@Inject
中,我收到来自
Eclipse
的警告:“
没有bean符合注入点[JSR-299§5.2.1]


如果我在一些标记为
实体的bean上使用
@Inject
@Inject
工作正常。

您可以在CDIBean上使用@PersistenceContext。它不必是EJB

如果出于某种原因您想使用@Inject,那么您必须做更多的工作@Inject不知道EntityManager;它只能注入其他托管bean。令人高兴的是,有一个简单的解决方法-使用生产者方法,作为一个简单的蹦床

@ApplicationScoped
public class EntityManagerProducer {

    @PersistenceContext
    private EntityManager entityManager;

    @Produces
    @RequestScoped
    public EntityManager getEntityManager {
        return entityManager;
    }

    public void closeEntityManager(@Disposes EntityManager em) {
        if (em != null && em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
        if (em != null && em.isOpen()) {
            em.close();
        }
    }

}

现在可以使用@Inject注入EntityManager。注入的EntityManager将是RequestScope,而EntityManager生产者是ApplicationScope。此外,必须关闭entityManager。

您遇到了什么问题?如果同一persistence.xml中有多个持久性单元,则只需在注释中使用鉴别器。因为它是你只有一个将是默认的。请确保persistence.xml与DAO和Entity类位于同一个模块(JAR)中。@Perception请查看我编辑的帖子,并为discriminator.Maistora提供一些示例-您不需要discriminator注释,您的persistence.xml中只有一个PU。但是根据您添加的错误消息,我非常确定Eclipse没有找到您的JBoss JEE实现文件。如果您使用的是Maven,那么需要将jboss-javaee-web-6.0依赖项添加到POM中。如果您使用的是其他构建工具,那么您需要手动查找JAR并将其添加到您的项目类路径中。如果消息是困扰您的是,我必须说我成功地在一些bean上使用了[et]Inject。例如@Inject private UserBean UserBean;其中UserBean被标记为实体。这很好:)谢谢,但是当我想使用entityManager.persist(MyObject)并且出现此错误时:javax.persistence.TransactionRequiredException:执行此操作需要事务(使用事务或扩展持久性上下文),所以我添加了PersistenceContext(类型=PersistenceContextType.EXTENDED)但是什么也没发生。我读到这意味着我应该自己关心事务。有没有办法让容器来管理事务?恐怕没有。EJB获得事务;CDI bean没有。Seam可能对此有所帮助,但我对Seam不太了解。在普通EE中,您必须自己管理事务f、 您可以选择(a)通过bean中的UserTransaction显式管理事务,(b)添加过滤器并将整个请求周期包装在事务中,以及(c)编写一个管理事务的CDI拦截器(请参阅-这真是太酷了!).@TomAnderson既然
EntityManager
实例不是线程安全的,那么
EntityManager Producer
不应该是
@requestscope
而不是
@ApplicationScoped
?即使是会话或对话也似乎很危险,因为同一个会话可能有多个并行请求。@Brian:好问题。我没想到我知道CDI使用范围感知代理来安全地将bean注入到范围更广的其他bean中(请求进入会话等等)。这适用于这里吗?或者更确切地说,这适用于
@PersistenceContext
注入EntityManager的点吗?如果不适用,那么当然,我写的是错误的,EntityManager应该是请求作用域。
@Named("validateReportAction")
@SessionScoped
public class ValidateReportAction extends ReportAction implements Serializable {

    private static final long serialVersionUID = -2456544897212149335L;

    @Inject
    private EntityManager em;
...
}  
@ApplicationScoped
public class EntityManagerProducer {

    @PersistenceContext
    private EntityManager entityManager;

    @Produces
    @RequestScoped
    public EntityManager getEntityManager {
        return entityManager;
    }

    public void closeEntityManager(@Disposes EntityManager em) {
        if (em != null && em.getTransaction().isActive()) {
            em.getTransaction().rollback();
        }
        if (em != null && em.isOpen()) {
            em.close();
        }
    }

}