【问题标题】:How can I make a JPA application access different databases?如何让 JPA 应用程序访问不同的数据库?
【发布时间】:2012-02-16 17:02:26
【问题描述】:

我正在编写一个 Java SE(桌面)应用程序,它必须访问不同的数据库,所有这些数据库都将具有相同的数据模型(相同的模式、表等)。我想重用已在每个数据库前面的 Java EE 应用程序中使用的 JPA 实体。

要重用现有的 entity.jar 文件,我必须使用具有 resource_local 数据源的不同 persistence.xml 重新打包它。这是构建时间上的不便,但不是大问题。

问题是我的桌面应用程序将被限制使用在 persistence.xml 文件中定义的数据源。我可以定义多个持久性单元并选择在运行时使用哪一个,但是当添加新数据库时,我必须更改 persistence.xml 并更新所有桌面二进制文件。

我希望能够在每个用户可以配置的 .properties 文件中定义新的数据源。有没有办法在运行时覆盖或添加到persistence.xml中声明的持久化单元?

我不想仅仅为了支持这个桌面应用程序而使用 Web 服务接口构建 Java EE 应用程序。 Java EE 应用程序有不同的用途,我想在桌面应用程序中保留桌面功能。

谢谢。

【问题讨论】:

    标签: jpa-2.0 persistence.xml


    【解决方案1】:

    您可以通过提供属性在运行时创建 EntityManagerFactory。

    Map<String, Object> properties = new HashMap<String, Object>();
    
    properties.put(TRANSACTION_TYPE, PersistenceUnitTransactionType.RESOURCE_LOCAL.name());
    properties.put(JDBC_DRIVER, driver);
    properties.put(JDBC_URL, db_url);
    properties.put(JDBC_USER, "userName");
    properties.put(JDBC_PASSWORD, "password");
    
    EntityManagerFactory factory = Persistence.createEntityManagerFactory("PERSISTENT_UNIT_NAME", properties);
    

    您也可以尝试使用属性文件,在运行时将属性文件加载到地图中。因此它将数据库配置与代码解耦。

    编辑:属性键(JDBC_URL 等)是特定于供应商的,应相应地替换它们。

    【讨论】:

    • 谢谢。我接受您的回答并在上面进行扩展。
    【解决方案2】:

    纳扬,

    我需要扩展你的答案,因为它不完整。

    使用属性动态创建 EntityManager 令人困惑的一点是,JPA 中有三个 createEntityManagerFactory() 方法,并且所有 3 个都采用了一个持久化单元名称。在我检查 JPA 2.0 规范之前,我没有意识到这些属性会覆盖persistenceunit 名称。第 9.4.3 节说这些属性会覆盖persistence.xml 中给定的值。它还显示了标准属性名称。

    (JavaDocs 没有告诉您可以进入属性的内容,也没有说属性会覆盖persistence.xml 中的内容。JavaDocs 的另一个例子。)

    您的示例使用了 Java EE 6 API Javadocs 中没有的属性名称,例如“JDBC_URL”。 JPA 规范解释说,除了标准属性之外,还可以使用供应商特定的属性名称。 EclipseLink 文档显示了实现通过非标准 PersistenceUnitProperties 类支持的属性名称:

    http://www.eclipse.org/eclipselink/api/2.3/index.html

    因此,为了拥有动态实体管理器,必须使用供应商特定的属性,因此动态实体管理器不可移植。我猜你不可能拥有一切。

    动态 EntityManager 可移植的一种情况是通过使用标准 javax.persistence.jtaDataSource 属性。您必须将数据源添加到您的 Java EE 容器中,但这是在容器中运行时尽可能动态的。在 Java SE 中,似乎没有任何可移植的动态选项。

    JavaDocs 需要更好地解释属性如何与 createEntityManagerFactory() 方法一起使用。

    【讨论】:

    • 是的,有些属性留待实现,在规范中找不到。 JDBC_URL 是通用的,仅用于显示目的,需要替换为供应商特定的属性。此外,只有 2 种方法可用于创建工厂,第一种方法使用 xml 中描述的单元名称,其他方法使用名称和属性。
    • 第三种方法在 javax.persistence.spi.PersistenceProvider 中,看起来它是由供应商实现使用的,通常不用于应用程序开发。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多