【问题标题】:spring LocalContainerEntityManagerFactoryBean does not work with persistentunitmanagerspring LocalContainerEntityManagerFactoryBean 不适用于persistentunitmanager
【发布时间】:2023-03-16 21:14:02
【问题描述】:

我想将 LocalContainerEntityManagerFactoryBean 与多个持久性单元一起使用。

applicationContext.xml:

<bean id="jpaEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitManager" ref="jpaPersistenceUnitManager"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true"/>
            <property name="generateDdl" value="false"/>
            <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
        </bean>
    </property>
</bean>

<bean id="jpaPersistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
    <property name="defaultPersistenceUnitName" value="pu-user”/>
    <property name="persistenceXmlLocations">
        <list>
            <value>classpath*:META-INF/persistence-user.xml</value>
            <value>classpath*:META-INF/persistence-customer.xml</value>
        </list>
    </property>
    <property name="dataSources">
        <map>
            <entry key=“userDataSource" value-ref=“userDataSource"/>
            <entry key="customerDataSource" value-ref=“customerDataSource"/>
        </map>
    </property>
    <property name="defaultDataSource" ref=“userDataSource"/>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" primary="true">
    <property name="entityManagerFactory" ref="jpaEntityManagerFactory"/>
</bean>

<tx:annotation-driven proxy-target-class="true"/>

<context:component-scan base-package="simple.user.persistence"/>
<context:component-scan base-package="simple.customer.persistence"/>

persistence xmls 定义如下:

<persistence-unit name="pu-user" transaction-type="RESOURCE_LOCAL">
    <jta-data-source>userDataSource</jta-data-source>
    <non-jta-data-source>userDataSource</non-jta-data-source>
</persistence-unit>

数据源定义如下:

<bean id="userDataSource" class="org.apache.commons.dbcp2.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/user"/>
    <property name="username" value="user"/>
    <property name="password" value="password"/>
    <property name="maxTotal" value="32"/>
    <property name="maxIdle" value="32"/>
    <property name="validationQuery" value="select 1"/>
</bean>

UserRepository 和 CustomerRepository 定义如下:

package simple.user.persistence;

@Repository
public class UserRepository {
   @PersistenceContext(unitName="pu-user”)
   EntityManager em;

   @Transactional
   User createUser(User user) {
       em.persist(user);
   }
}

当我运行单元测试时,我收到以下异常。

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'pu-customer' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:698)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1175)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.findEntityManagerFactory(EntityManagerFactoryUtils.java:139)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findNamedEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:556)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:538)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:707)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:680)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:354)
... 60 more

查看了EntityManagerFactoryUtils的源代码。第 132 行的 findEntityManagerFactory 方法清楚地只比较了 defaultPersistentUnitName 而忽略了在 DeafultPersistentUnitManager 中定义的其他持久单元名称。这在我看来就像一个错误。请让我知道你的想法。

https://github.com/spring-projects/spring-framework/blob/master/spring-orm/src/main/java/org/springframework/orm/jpa/EntityManagerFactoryUtils.java

【问题讨论】:

    标签: spring hibernate jpa orm spring-orm


    【解决方案1】:

    当我需要多个持久性单元时,我会创建多个 LocalContainerEntityManagerFactoryBean,然后每个 LocalContainerEntityManagerFactoryBean 都会有一个对应的 JpaTransactionManager。

    如果您有多个事务管理器,则需要在 @Transactional 注释中命名要使用的事务管理器。

    我想如果您需要在单个事务中访问两个持久性单元,您将需要一个 JTA 事务管理器来结合 2 个 JPA 事务管理器——虽然不确定您的要求是什么。

    【讨论】:

    • 谢谢约翰。感谢您的回复。我目前正在使用这种方法。我们的生产数据库有 10 个 SQL 模式。我为它们中的每一个声明了一个单独的 LocalContainerEntityManagerFactoryBean 和 JpaTransactionManager 。它在代码维护方面增加了一点开销。如果我的原始配置有效,那么我可以减少所需的配置量。
    • 拥有多个是我发现让这个工作的唯一方法。如果问题是单个数据库上的多个架构,那么另一种解决方案可能是将所需表的访问权限授予单个架构(可能是第 11 个应用程序架构)。
    • 谢谢约翰。我们正在使用版本控制框架。它为每个模式创建单独的全局历史表。这就是为什么我们需要创建单独的 EntityManager 来访问它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 2015-11-03
    • 1970-01-01
    • 2014-11-29
    相关资源
    最近更新 更多