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

Сработало; нужно было сделать несколько вещей. Похоже, что ключевая часть этого заключается в том, что для использования нескольких баз данных с подходом, который я принимал, для пула соединений необходимо настроить использование распределенных транзакций. Поскольку это по существу эксперимент, обе db-стойки не должны быть в одной транзакции, но это не проблема для этого. (Эта статья была полезной для определения этого из сообщений об ошибках). Также необходимо было изменить параметры Postgres, как описано здесь, чтобы включить подготовленные транзакции.


Это все получилось:

(1) В Glassfish:
В пулах соединений JDBC измените тип ресурса для обоих db на javax.sql.XADataSource. Измените имя класса данных для Postgres на org.postgresql.xa.PGXADataSource; измените Datasource Classname для MySQL на com.mysql.jdbc.jdbc2.optional.MysqlXADataSource.

(2) В конфигурации Posgres (postgresql.config):
Включите max_prepared_transactions и установите его на 1 больше, чем max_connections. (Мне пришлось поиграть с обоими параметрами, чтобы найти что-то, что не выдуло всю доступную общую память, но поскольку это всего лишь эксперимент, уменьшение количества подключений db и увеличения общей памяти в порядке)

(3) В коде:
Измените @PersistenceContext(name="...") на @PersistenceContext(unitName="...")


Предостережение в этом "ответе". Большинство из них для меня новы, поэтому это может быть не самый элегантный способ справиться с этим. Если кто-то может предоставить "наилучшую практику" для решения этой проблемы, мне было бы очень интересно узнать.