我试图将同一个实体持有到
MySQL和Postgres数据库(这主要是为了识别任何不一致之处,并阐述了双重写入的任何问题的细节 – 我已经在这里讨论过).我发现的文章都描述了依赖于其他框架的解决方案.我试图用Glassfish 4.0开箱即用,JPA 2.1与EclipseLink 2.5作为JPA提供程序来解决这个问题.我正在使用Eclipse,并且意识到IDE不支持在persistence.xml文件中配置多个持久性单元,所以我正在直接编写XML.
@H_403_4@@PersistenceContext(name = "MyAppMysqLPU")
EntityManager emMysqL;
@PersistenceContext(name = "MyAppPostgresPU")
EntityManager emPostgres;
//...etc...
MyThing thing = new MyThing();
//...etc...
emMysqL.persist(thing);
emPostgres.persist(thing);
@H_403_4@<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>
当我这样做,我得到以下错误:
@H_403_4@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>短语(不重要哪一个),实体被持久化到关联的数据库 – 我只是无法弄清楚如何使它同时处理两者(不需要在额外的框架中利用持久性功能).
解决方法
得到它的工作;必须做几件事情.这似乎是一个关键部分,为了使用我所采用的方法使用多个数据库,连接池类型需要设置为使用分布式事务.由于这基本上是一个实验,因此数据库持续存在不需要在同一个事务中,但它并不是一个问题. (
This文章有助于从错误消息中识别出来).还需要根据
here所述更改Postgres参数,以使准备的事务成为可能.
所有这一切:
(1)在Glassfish:
在JDBC连接池中,将db的资源类型更改为javax.sql.XADataSource.将Postgres的Datasource类名更改为org.postgresql.xa.PGXADataSource;将MysqL的Datasource Classname更改为com.MysqL.jdbc.jdbc2.optional.MysqLXADataSource.
(2)在Posgres配置(postgresql.config)中:
启用max_prepared_transactions并将其设置为大于max_connections 1. (我不得不使用两个参数来找到一些没有吹出所有可用的共享内存的东西;但是由于这只是一个实验,减少数据库连接数量,而是增加共享内存可以)
(3)代码中:
将@PersistenceContext(name =“…”)更改为@PersistenceContext(unitName =“…”)
关于这个“答案”的警告 – 大多数对我来说都是新的,所以这可能不是处理这个问题的最优雅的方式.如果有人可以提供“最佳实践”来解决这个问题,我会很有兴趣知道.