Spring 多个 PersistenceContext

cod*_*het 5 java spring spring-mvc jpa-2.0

spring 中多个持久性上下文的设置有很多变化,但没有一个可以解释我面临的问题。

我有一个像这样的应用程序上下文结构:

core AC
`-- web-root AC
Run Code Online (Sandbox Code Playgroud)

在我的核心应用程序上下文中,我定义了两个数据源和一个 transactionManager 以及一个 EntityManagerFactory bean:

<!-- core applicationContext.xml -->
<beans ...>
    <context:annotation-config/>
    ...
    <!-- Container managed datasources -->
    <jee:jndi-lookup id="module1DS" jndi-name="jdbc/module1DS" expected-type="javax.sql.DataSource"/>
    <jee:jndi-lookup id="securityDS" jndi-name="jdbc/securityDS" expected-type="javax.sql.DataSource"/>

    <bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>

    <bean id="securityEMF" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="securityPU"/>
        <property name="jtaDataSource" ref="securityDS"/>
        <property name="packagesToScan" value="com.example.security.model"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter"/>
        </property>
        <property name="loadTimeWeaver">
            <bean class="org.springframework.instrument.classloading.websphere.WebSphereLoadTimeWeaver"/>
        </property>
    </bean>
</beans>
Run Code Online (Sandbox Code Playgroud)

在 web-root 应用程序上下文中,我定义了一个额外的 EMF:

<!-- module1 applicationContext.xml -->
<beans...>
    ....
    <bean id="module1EMF" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="module1PU"/>
        <property name="jtaDataSource" ref="module1DS"/>
        <property name="packagesToScan" value="com.example.module1.model"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter"/>
        </property>
        <property name="loadTimeWeaver">
            <bean class="org.springframework.instrument.classloading.websphere.WebSphereLoadTimeWeaver"/>
        </property>
    </bean>
</beans>
Run Code Online (Sandbox Code Playgroud)

现在,我在核心模块的包下定义了几个实体com.example.core.model,并且在com.example.module1.modelmodule1 的包中定义了一个实体(这是一场耳边的战争)。

核心中定义了一个服务,它将 EntityManager 注入到 securityPU PersistenceContext 中,并对数据库中的实体执行命名查询:

@Service("coreThingService")
public class CoreEntityThingServiceImpl implements CoreEntityThingService {

    @PersistenceContext(unitName = "securityPU")
    @Qualifier("securityEMF")
    private EntityManager em;

    @Override
    public List<CoreEntityThing> getCoreEntityThingById(String id) {
        // select a from CoreEntityThing a where a.id = :id
        TypedQuery<CoreEntityThing> query = em.createNamedQuery("CoreEntityThing.findById", CoreEntityThing.class);
        query.setParameter("id", id);
        return query.getResultList();
    }
}
Run Code Online (Sandbox Code Playgroud)

不要介意我这里不寻常的逻辑,重点是当这个服务被注入到 a 内的 web 层@Controller并被调用时,我收到以下错误:

org.apache.openjpa.persistence.ArgumentException: An error occurred while parsing the 
>query filter "select a from CoreEntityThing a where a.id = :id". Error message: The 
>name "CoreEntityThing" is not a recognized entity or identifier. Perhaps you meant 
>Module1Entity, which is a close match. Known entity names: [Module1Entity]
Run Code Online (Sandbox Code Playgroud)

我已经检查了注入的em:

@PersistenceContext(unitName = "securityPU")
@Qualifier("securityEMF")
private EntityManager em;
Run Code Online (Sandbox Code Playgroud)

并发现它是预期的 securityPU,但我没想到的是当它说它找不到实体时(即使 的属性packagesToScan正确securityEMF地指向正确的包)。

更奇怪的是,它建议“子”PU 中存在一个实体Module1Entity——该实体不应该在 securityEMF 中被拾取。

我究竟做错了什么?

更新 1:我更新了我的应用程序上下文 xml 描述,以明确我如何创建 PU

更新 2:看来我的类正在被扫描,因为我可以在运行时在持久性单元中看到它们,真正有趣的是,直到调用createNamedQueryEntityManager 代理上的方法(使用method.invoke(targetPU, name)wheremethod是 createNamedQuery 函数和targetPUsecurityEMFPU),PU 仍然是 securityEMF。我无法更深入地研究代码来查看 createNamedQuery 实际上在做什么,但在此调用期间,会引发所描述的错误!到底发生了什么?

为了让事情更清楚,错误消息的查询字符串:

"select a from CoreEntityThing a where a.id = :id"
Run Code Online (Sandbox Code Playgroud)

位于我的 CoreEntityThing 类之上!

package com.example.core.model.security;
...

@Entity
@NamedQuery(name = "CoreEntityThing.findById", query = "select ...")
public class CoreEntityThing { ... }
Run Code Online (Sandbox Code Playgroud)

所以它正在寻找实体,然后声称它对此一无所知!

更新 3:我在这篇博文中读到了有关 JPA PersistenceUnits 模块化程度有限的假设限制。任何人都可以向我指出有关此限制的更多文档以及使用多个数据源的多模块企业解决方案的任何示例。这必须成为大量大型项目的共同关注点。