4

我正在尝试将我们的 DAO maven 模块集成到 spring,我们不想更改 dao 的任何代码。以前,所有的 dao 类都使用以下方式获取实体管理器。

Persistence.getEntityManager()

在春天,我看到很多使用注释注入实体管理器的示例,但需要更改 dao 代码。有没有办法可以修改下面的类以使其在春季工作?

 public class PersistenceManager
    {

        /**
         * Key that stores the entity manager.
         */
        private static final String ENTITY_MANAGER_INSTANCE = "ENTITY_MANAGER_INSTANCE";
        /**
         * Persistence unit for eMyEd
         */
        private static final String PERSISTENCE_UNIT_EMYED = "application_openjpa";
        /**
         * The static factory used across the JVM
         */
        private static final EntityManagerFactory ENTITY_MANAGER_FACTORY = Persistence
                .createEntityManagerFactory(PERSISTENCE_UNIT_EMYED);

        /**
         * Cleanup any entity managers created in the thread context.
         */
        public static void close()
        {
            EntityManager emInstance = getEntityManager();
            try
            {
                if (emInstance.isOpen())
                {
                    emInstance.close();
                }
            }
            catch (Throwable t)
            {
                // ignore
            }
            finally
            {
                ThreadContext.instance.clear();
            }
        }

        /**
         * Returns the Entity manager associated with the given thread context. If
         * none available, one is created and set on the thread context and the same
         * is returned.
         *
         * @return
         */
        public static EntityManager getEntityManager()
        {
            EntityManager emInstance = (EntityManager) ThreadContext.instance
                    .get(ENTITY_MANAGER_INSTANCE);
            if (emInstance == null)
            {
                emInstance = createEntityManager();
                emInstance.setFlushMode(FlushModeType.COMMIT);
                ThreadContext.instance.put(ENTITY_MANAGER_INSTANCE, emInstance);
            }
            try
            {
                // try to join the current active transaction
                emInstance.joinTransaction();
            }
            catch (TransactionRequiredException notSupportedEx)
            {
                // If there was no transaction to join. Ignore
            }
            catch (Throwable unknownEx)
            {
                // If there was no transaction to join. Ignore
            }
            return emInstance;

        }

        /**
         * Create a new entity manager.
         *
         * @return
         */
        private static EntityManager createEntityManager()
        {
            return ENTITY_MANAGER_FACTORY.createEntityManager();
        }
    }

弹簧配置

<description>Example configuration to get you started.</description>
    <context:component-scan base-package="com.veera" />
 <!-- tell Spring that it should act on any @PersistenceContext and @Transactional annotations found in bean classes -->
    <tx:annotation-driven transaction-manager="transactionManager" />
    <!-- ******************************************************************** -->
    <!-- Setup the transaction manager -->
    <!-- ******************************************************************** -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>


    <!-- ******************************************************************** -->
    <!-- Setup each data source -->
    <!-- ******************************************************************** -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/test" />
        <property name="username" value="root" />
        <property name="password" value="root" />
    </bean>

    <!-- ******************************************************************** -->
    <!-- Setup each persistence unit -->
    <!-- ******************************************************************** -->
    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter">
                <property name="databasePlatform"
                    value="org.apache.openjpa.jdbc.sql.MySQLDictionary" />
            </bean>
        </property>
        <property name="persistenceUnitName" value="application_openjpa" />
        <!--  property name="loadTimeWeaver">
            <bean
                class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
        </property -->
        <!-- property name="jpaProperties"> <props> <prop key="hibernate.hbm2ddl.auto">create-drop</prop> 
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> 
            </props> </property -->
    </bean>
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

持久性.xml

    <persistence-unit name="application_openjpa"
        transaction-type="RESOURCE_LOCAL">
        <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
        <class>com.veera.jpa.Item</class>
        <class>com.veera.jpa.Order</class>
        <class>com.zreflect.emyed.entity.user.User</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <!--  property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema" /
            <property name="openjpa.InitializeEagerly" value="true"/-->
            <property name="openjpa.Log" value="File=stdout, DefaultLevel=INFO, Runtime=INFO, SQL=TRACE"/>
        </properties>
    </persistence-unit>

</persistence>
4

2 回答 2

1

由于EntityManager定义不是线程安全的,唯一的 - 仍然丑陋的 - 解决方案是静态保存并根据请求从工厂EntityManagerFactory创建实例。EntityManager

我什至建议通过这种方法更改 DAO 以使用依赖注入,因为您的 DAO 本质上变得不可单元测试,而无需引导整个 JPA 基础设施。

于 2013-09-11T03:43:25.193 回答
1

我找到了解决方案,见下文

更新

    @Repository
public class PersistenceManager
{
    /**
     * Key that stores the entity manager.
     */
    private static final String ENTITY_MANAGER_INSTANCE = "ENTITY_MANAGER_INSTANCE";
    /**
     * Persistence unit for eMyEd
     */
    private static final String PERSISTENCE_UNIT_EMYED = "application_openjpa";

    private static EntityManagerFactory emf;

    @PersistenceUnit(unitName=PERSISTENCE_UNIT_EMYED)
    public void setEntityManagerFactory(EntityManagerFactory emf) {
        PersistenceManager.emf = emf;
    }
    /**
     * Cleanup any entity managers created in the thread context.
     */
    public static void close()
    {
        EntityManager emInstance = getEntityManager();
        try
        {
            if (emInstance.isOpen())
            {
                emInstance.close();
            }
        }
        catch (Throwable t)
        {
            // ignore
        }
        finally
        {
            ThreadContext.instance.clear();
        }
    }

    /**
     * Returns the Entity manager associated with the given thread context. If
     * none available, one is created and set on the thread context and the same
     * is returned.
     *
     * @return
     */
    public static EntityManager getEntityManager()
    {
        EntityManager emInstance = (EntityManager) ThreadContext.instance
                .get(ENTITY_MANAGER_INSTANCE);
        if (emInstance == null)
        {
            emInstance = createEntityManager();
            emInstance.setFlushMode(FlushModeType.COMMIT);
            ThreadContext.instance.put(ENTITY_MANAGER_INSTANCE, emInstance);
        }
        try
        {
            // try to join the current active transaction
            emInstance.joinTransaction();
        }
        catch (TransactionRequiredException notSupportedEx)
        {
            // If there was no transaction to join. Ignore
        }
        catch (Throwable unknownEx)
        {
            // If there was no transaction to join. Ignore
        }
        return emInstance;
    }

    /**
     * Create a new entity manager.
     *
     * @return
     */
    private static EntityManager createEntityManager()
    {
        return emf.createEntityManager();
    }
}
于 2013-09-09T18:45:08.787 回答