1

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

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

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

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

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

谢谢。

4

2 回答 2

6

您可以通过提供属性在运行时创建 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 等)是特定于供应商的,它们应该被相应地替换。

于 2012-02-18T10:24:20.717 回答
3

纳扬,

I need to expand on your answer because it's not complete.

The confusing thing about using properties to dynamically create EntityManagers is that there are three createEntityManagerFactory() methods in JPA and all 3 take a persistenceunit name. I didn't realize that the properties override the persistenceunit name until I checked the JPA 2.0 spec. Section 9.4.3 says that the properties override the values given in the persistence.xml. It also shows what the standard property names are.

(The JavaDocs don't tell you what can go into the properties and they don't say that the properties override what is in persistence.xml. Another example where JavaDocs suck.)

Your example uses property names like "JDBC_URL" that aren't in the Java EE 6 API Javadocs. The JPA spec explains that vendor specific property names can be used in addition to the standard properties. The EclipseLink docs show what property names that implementation supports via the non-standard PersistenceUnitProperties class:

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

So in order to have dynamic EntityManagers it is necessary to use vendor specific properties, so dynamic entity managers aren't portable. I guess you can't have everything.

One case where dynamic EntityManagers would be portable is through the use of the standard javax.persistence.jtaDataSource property. You would have to add the data source to your Java EE container, but that is as dynamic as you can be when running in a container. In Java SE it doesn't look like there are any portable, dynamic options.

The JavaDocs need to do a much better job of explaining how properties work with the createEntityManagerFactory() methods.

于 2012-02-22T17:30:59.857 回答