11

我正在尝试将同一实体持久保存到 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>短语(不管是哪个短语),实体就会被持久化到关联的数据库中——我只是不知道如何让它同时与这两个短语一起工作(没有在其他框架中利用持久性功能)。

4

1 回答 1

16

让它工作;必须做几件事。似乎其中的一个关键部分是,为了通过我采用的方法使用多个数据库,需要将连接池类型设置为使用分布式事务。因为这本质上是一个实验,所以两个 db persists不需要在同一个事务中,但那样做不是问题。(这篇文章有助于从错误消息中识别出来)。还需要按照此处所述更改 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="...")


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

于 2013-08-19T03:28:31.377 回答