JPA实体 - 指定持久化单元?

12

我有一个JavaEE项目,它利用了多个持久化单元。 有没有办法指定特定的JPA实体属于哪个持久化单元? 一些实体在一个数据源中,而其他实体在我的第二个数据源中。 是否有一种方法可以使用注释区分这两者?

3个回答

11

要指定Entity属于哪个持久单元,使用persistence.xml文件:

<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="user" transaction-type="JTA">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/myApp</jta-data-source>
        <class>com.company.User</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <!-- properties -->
        </properties>
    </persistence-unit>

    <persistence-unit name="data" transaction-type="JTA">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <jta-data-source>jdbc/myApp_data</jta-data-source>
        <!--<mapping-file>META-INF/myApp_entities.xml</mapping-file> You can also use mapping files.-->
        <class>com.company.Data</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <!-- properties -->
        </properties>
    </persistence-unit>
</persistence>

注意使用了<exclude-unlisted-classes />标签。


2
所以这需要我将每个实体都添加到persistence.xml中,而不是使用注解进行发现,对吗? - Shadowman
2
是的。从根本上说,为了在持久性上下文之间进行选择,您需要在每个persistence.xml中列出所有类,或在每个实体中列出持久性上下文。两者看起来差不多需要同样的工作量。但是,对于第一种方法,所有元数据都在一个地方。 - Kevin
此外,我不知道第二种方法(在实体中列出持久上下文)是否可行。 - Kevin

2

您可以通过识别注册它的EntityManager来确定实体属于哪个持久化单元。

托管实体属于持久化上下文,而持久化上下文属于持久化单元。因此,在这个例子中:

@PersistenceContext(unitName="persistence-unit-1")
EntityManager em1;

@PersistenceContext(unitName="persistence-unit-2")
EntityManager em2;

em1.persist(entity1);
em2.persist(entity2);

entity1属于persistence-unit-1,而entity2属于persistence-unit-2。这不像在persistence.xml中指定<class>标签那样明确,但是你可以在两个持久单元中拥有相同的实体类,并且仍然可以区分每个实体实例属于哪个单元。


那么,如果您没有在persistence.xml中使用<class>标签指定entity1属于persistence-unit-1,您是如何指定的呢? - badera
当将应用程序部署到完整的JEE容器(如Weblogic、JBoss或WebSphere)时,应用服务器会自动扫描带有“Entity”注释的类,您无需像在使用servlet容器(如Tomcat)或独立Java应用程序时那样向persistence.xml添加<class>标签,除非您使用“exclude-unlisted-classes”标签。 - German
我知道。但是它怎么知道它属于哪个“persistence-unit”?请看上面的答案... - badera
JPA规范没有明确说明,但我相信如果您不指定“exclude-unlisted-classes=true”,则所有类都属于所有持久性单元。我理解您不想在persistence.xml中显式添加它们。如果所有类都在所有持久性单元中是否有问题?如果它们用于不同的数据库模式,则仍然可以在EntityManager或EntityManagerFactory上指定pu名称以连接到正确的数据库,就像我在这个答案中发布的那样。除非使用自动模式生成,否则在错误的持久性单元中可用类不应该是一个问题。 - German
你写道:“如果一个类在错误的持久化单元中可用,除非使用自动模式生成,否则不应该有问题” - 这对于方案验证也是正确的吗?好的,我可以检查一下。我之前没有想到它不会有影响...如果确实如此,那将是个好消息!谢谢! - badera

1

@PersistenceUnit应该也可以使用(尽管我还没有尝试过)

例如:

@PersistenceUnit(unitName="persistenceUnit2")
@Entity
class XPTO {
}

来自Javadoc(http://docs.oracle.com/javaee/6/api/javax/persistence/PersistenceUnit.html

“表示对EntityManagerFactory及其关联的持久性单元的依赖性。”

unitName (可选)在persistence.xml文件中定义的持久性单元的名称。


有人可以确认这是否有效吗?我有不同的实体,希望将它们分配给两个不同的PersistentUnits - 而不需要exclude-unlisted-classes=true - badera
@badera:我从未使用过它,我知道它的存在,但最终我从未需要过它。我想没有什么比一个快速测试更好了 :) - João Antunes
1
好的,我测试了一下,但是它没有起作用[抱歉,在评论中我没有提到这点 :) ]。所以我想知道是我做错了什么还是它真的不起作用。我仍然很高兴能够得到一个解决方案,在其中我可以注释每个实体,指定它们应该属于哪个PersistenceUnit(一个或多个),而不必在persistence.xml中列出所有实体类...这对于几百个实体来说非常烦人...甚至更少。 - badera
@badera:所以,你尝试在persistence.xml上定义另一个持久化单元,并使用@PersistenceUnit(unitName="newName")。但是出了什么问题呢?你可以尝试调试代码,看看哪里出错了。 - João Antunes
1
抱歉,但是调试这个很难,因为我发现这个注释没有效果。那么为什么没有效果呢?没有效果意味着它的行为就像我没有在@Entity上注释@PersistenceUnit()一样。如果exclude-unlisted-classes为false,则所有实体都属于所有持久性单元。我使用带有包含的Hibernate的Wildfly 8.2.1。我认为我必须对这个答案进行负面评价,因为这是一个不起作用的建议。或者请提供证明表明它是有效的。 - badera
@badera 看起来是这样工作的:https://github.com/wicketstuff/core/wiki/How-to-use-@PersistenceUnit-annotation还有一个更深入的解释:https://doanduyhai.wordpress.com/2011/11/21/spring-persistencecontext-explained/因此,显然需要注释实体管理器工厂而不是实体。我还没有仔细阅读第二篇文章,但它似乎是如何使用这个的关键。 - João Antunes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接