多个持久性单元的persistence.xml

Cra*_*ver 11 jpa jta persistence.xml eclipselink

我正在尝试将同一个实体持久化到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);
Run Code Online (Sandbox Code Playgroud)

并使用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>
Run Code Online (Sandbox Code Playgroud)

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

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.
Run Code Online (Sandbox Code Playgroud)

但是,如果我只包含其中一个<persistence-unit>短语(无关紧要),那么该实体会持久保存到相关的数据库中 - 我无法弄清楚如何同时使用它们(没有利用其他框架中的持久性功能).

Cra*_*ver 16

搞定了; 有几件事要做.这似乎是一个关键部分,为了使用我正在采用的方法使用多个数据库,需要将连接池类型设置为使用分布式事务.由于这实际上是一个实验,因此数据库持久化并不需要在同一个事务中,但它不是那样的问题.(文章是在识别从所述错误消息有用).还必须按照此处所述更改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并将其设置为大于1 max_connections.(我不得不使用这两个参数找到一些没有炸掉所有可用共享内存的东西;但由于这只是一个实验,减少数据库连接数与增加共享内存相比是可以的)

(3)在代码:
改变@PersistenceContext(name="...")@PersistenceContext(unitName="...")


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