LocalContainerEntityManagerFactoryBean不会与@Transactional一起保留

时间:2014-07-28 16:12:01

标签: spring hibernate jpa spring-data-jpa transactional

我试图在Eclipse中使用Spring 4,Primefaces 5和Hibernate JPA创建一个项目,运行Wildfly 8.0。我的项目现在运行正常。唯一的问题是@Transactional注释不起作用。我试过这个(就像我在另一个SO问题中看到的那样)并且它有效(这在我的DAO中):

@Repository(value="empleadoDAO")
public class EmpleadoDAO {

    @Resource(name="myEmf")
    private EntityManagerFactory em;

    private EntityManager emf;

    public boolean insertarEmpleado(Empleado emp) {
        boolean res = true;
        emf = em.createEntityManager();
        emf.getTransaction().begin();
        emf.persist(emp);
        emf.getTransaction().commit();
        return res;
    }
}

如果我这样做,它可以工作,但是如果我在我的DAO或我的服务中使用@Transactional注释,要么使用javax.transaction中的注释或使用springframework注释它不起作用。它没有给我一个例外或者什么都没有,但如果我查看数据库它不会插入任何东西(我使用PostgreSQL 9.3)。

此外,目前我正在将EntityManagerFactory注入到我的DAO中而不只是注入EntityManager。我尝试使用@PersistenceContext注入EntityManager(unitName =" myPersistenceUnit")但它给了我这个错误:

JBAS016069: Error injecting persistence unit into CDI managed bean. Can't find a persistence unit named myPersistenceUnit in deployment sprisf2.war

这是我的beans.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

    <context:spring-configured />
    <context:annotation-config />
    <task:annotation-driven />
    <context:component-scan base-package="com.saplic.sprisf.daos" />
    <context:component-scan base-package="com.saplic.sprisf.managedbeans" />
    <context:component-scan base-package="com.saplic.sprisf.services" />
    <context:component-scan base-package="com.saplic.sprisf.entities" />
    <mvc:annotation-driven />

    <bean id="myEmf"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dbDs"></property>

        <property name="persistenceUnitName" value="myPersistenceUnit" />
        <property name="packagesToScan" value="com.saplic.sprisf.entities" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.format_sql">false</prop>
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>


            </props>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="myEmf" />
        <property name="dataSource" ref="dbDs" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />

    <jee:jndi-lookup id="dbDs" jndi-name="java:jboss/datasources/postgreDS"></jee:jndi-lookup>

    <mvc:resources location="/resources/" mapping="/static/**" />
</beans>

以前它在没有persistence.xml文件的情况下启动并在代码中提交事务,但之后我决定创建一个尝试使用@PersistenceContext注入EntityManager,这里是我的persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    version="1.0">
    <persistence-unit name="myPersistenceUnit">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.format_sql" value="true" />
            <!-- property name="hibernate.max_fetch_depth" value="3" /-->
            <!-- property name="hibernate.order_updates" value="true" /-->

            <property name="hibernate.default_schema" value="public" />
            <property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />

            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
            <property name="jboss.entity.manager.factory.jndi.name" value="java:jboss/datasources/postgreDS" />
        </properties>
    </persistence-unit>
</persistence>

我在LocalContainerEntityManagerFactoryBean中使用此属性引用了此persistence.xml:

<property name="persistenceXmlLocation" value="/META-INF/persistence.xml" />

至少我想在我的服务中使用@Transactional来保存我的数据,而不必通过代码启动和提交事务,如果我可以注入EntityManager而不是EntityManagerFactory,那将会很棒。

[编辑]这是我的文件EmpleadoManagedBean和EmpleadoService,我从中调用DAO方法进行插入:

@Component(value="empleadoMB")
@ManagedBean(name="empleadoMB")
@ConversationScoped
public class EmpleadoManagedBean implements Serializable {

    @Resource(name="empleadoService")
    private EmpleadoService empleadoService;

    private Empleado instance = new Empleado();

         public String addEmpleado() {
             empleadoService.insertarEmpleado(instance);
             return "SUCCESS";
         }
}

我确信实例对象具有调用insertarEmpleado之前的必要数据。这是我的服务类:

@Service("empleadoService")
@Transactional
public class EmpleadoService {

    @Resource(name="empleadoDAO")
    private EmpleadoDAO empleadoDAO;

    @Transactional
    public void insertarEmpleado(Empleado emp) {
        empleadoDAO.insertarEmpleado(emp);
    }
}

[编辑]通过查看一些示例,我看到有些人只是声明然后是一个名为transactionManager的bean,我将bean的名称更改为txManager并且它给我一个错误,表明没有bean id transactionManager,所以我认为它注入了Services,但由于某种原因,注释不起作用。

1 个答案:

答案 0 :(得分:0)

这不是一个真正的答案,但即使我觉得有点受限制,它对我也有用。我看到eclipse中生成的Wildfly日志,我看到了:

14:58:22,465 INFO  [org.jboss.as.jpa] (MSC service thread 1-4) JBAS011401: Read persistence.xml for sprisf2
14:58:22,665 INFO  [org.jboss.as.jpa] (ServerService Thread Pool -- 77) JBAS011409: Starting Persistence Unit (phase 1 of 2) Service 'sprisf2.war#sprisf2'
14:58:22,674 INFO  [org.hibernate.jpa.internal.util.LogHelper] (ServerService Thread Pool -- 77) HHH000204: Processing PersistenceUnitInfo [
    name: sprisf2
    ...]
14:58:22,739 INFO  [org.hibernate.Version] (ServerService Thread Pool -- 77) HHH000412: Hibernate Core {4.3.5.Final}
14:58:22,741 INFO  [org.hibernate.cfg.Environment] (ServerService Thread Pool -- 77) HHH000206: hibernate.properties not found
14:58:22,742 INFO  [org.hibernate.cfg.Environment] (ServerService Thread Pool -- 77) HHH000021: Bytecode provider name : javassist

14:58:23,410 INFO  [org.jboss.as.jpa] (ServerService Thread Pool -- 77) JBAS011409: Starting Persistence Unit (phase 2 of 2) Service 'sprisf2.war#sprisf2'

14:58:25,619 INFO  [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean] (MSC service thread 1-3) Building JPA container EntityManagerFactory for persistence unit 'sprisf2'
14:58:25,619 WARN  [org.hibernate.ejb.HibernatePersistence] (MSC service thread 1-3) HHH015016: Encountered a deprecated javax.persistence.spi.PersistenceProvider [org.hibernate.ejb.HibernatePersistence]; use [org.hibernate.jpa.HibernatePersistenceProvider] instead.
14:58:25,620 INFO  [org.hibernate.jpa.internal.util.LogHelper] (MSC service thread 1-3) HHH000204: Processing PersistenceUnitInfo [
    name: sprisf2
    ...]
14:58:26,029 INFO  [org.hibernate.dialect.Dialect] (MSC service thread 1-3) HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect

根据LocalContainerEntityManagerFactoryBean文档,它使用persistence.xml中的信息生成PersistenceInfoUnit,或者如果不使用jpaProperties值定义它,则可以使用此bean将EntityManagers注入DAO。正如您在日志中看到的,它生成一个名为sprisf2(我的项目名称)的PersistenceUnitInfo,当我将其用作持久性单元名称时:

@PersistenceContext(unitName="sprisf2")
private EntityManager entityManager;

创建一个空的persistence.xml后,它工作了!!不幸的是,即使我使用不同的名称指定persistenceUnitName,我似乎也无法更改PersistenceUnitInfo名称。

有人知道为什么我不能改名字?为什么我需要有一个空的persistence.xml才能工作?