多个持久性单元的persistence.xml

时间:2013-08-16 14:28:02

标签: jpa eclipselink jta persistence.xml

我正在尝试将同一个实体持久化到MySQL和Postgres数据库(这主要是为了识别任何不一致,并找出执行双写的任何问题的细节 - 我在这里遇到过) 。我发现的文章都描述了依赖于其他框架的解决方案。我正在尝试使用Glassfish 4.0开箱即用,JPA 2.1以及EclipseLink 2.5作为JPA提供程序来解决这个问题。我正在使用Eclipse,并意识到IDE不支持在persistence.xml文件中配置多个持久性单元,所以我正在为此直接编写XML。

我希望在代码中做同样的事情(用同样的方法):

@PersistenceContext(name = "MyAppMySQLPU")
EntityManager emMySQL;
@PersistenceContext(name = "MyAppPostgresPU")
EntityManager emPostgres;
//...etc...
MyThing thing = new MyThing();
//...etc...
emMySQL.persist(thing);
emPostgres.persist(thing);

并使用包含以下内容的persistence.xml文件:

  <persistence-unit name="MyAppPostgresPU">
    <jta-data-source>jdbc/PostgresPool_test</jta-data-source>
    <class>model.MyThing</class>
  </persistence-unit>

  <persistence-unit name="MyAppMySQLPU">
    <jta-data-source>jdbc/MySQLPool_test</jta-data-source>
    <class>model.MyThing</class>
  </persistence-unit>

当我这样做时,我收到以下错误:

SEVERE: Exception while invoking class org.glassfish.persistence.jpa.JPADeployer prepare method
SEVERE: Exception while preparing the app
SEVERE: Exception while preparing the app : Could not resolve a persistence unit corresponding to the persistence-context-ref-name [MyAppPostgresPU] in the scope of the module called [MyApp]. Please verify your application.

但是,如果我只包含一个<persistence-unit>短语(与哪一个无关),则该实体会持久保存到关联的数据库中 - 我无法弄清楚如何使其工作两者同时进行(不在其他框架中利用持久性功能)。

1 个答案:

答案 0 :(得分:16)

搞定了;有几件事要做。这似乎是一个关键部分,为了使用我正在采用的方法使用多个数据库,需要将连接池类型设置为使用分布式事务。由于这实际上是一个实验,因此数据库持久化并不是需要在同一个事务中,但它不是那样的问题。 (This文章有助于从错误消息中识别出来)。还需要按照here所述更改Postgres参数,以启用准备好的事务。


这让一切顺利:

(1)在Glassfish中:
在JDBC连接池中,将两个db的资源类型更改为javax.sql.XADataSource。将Postgres的数据源类名更改为org.postgresql.xa.PGXADataSource;将MySQL的数据源类名更改为com.mysql.jdbc.jdbc2.optional.MysqlXADataSource

(2)在Posgres配置中(postgresql.config):
启用max_prepared_transactions并将其设置为大于max_connections的1。 (我不得不使用这两个参数来找到没有炸掉所有可用共享内存的东西;但由于这只是一个实验,减少数据库连接数与增加共享内存相比是正常的)

(3)代码中:
@PersistenceContext(name="...")更改为@PersistenceContext(unitName="...")


对这个“答案”提出警告 - 这对我来说大部分都是新的,所以这可能不是处理这个问题的最优雅方式。如果有人能提供“最佳实践”来解决这个问题,我会非常有兴趣知道。