I want to persist the same entity to a MySQL database and Postgres database (essentially one is a real-time clone of the other). Conceptually, I want to do this in a single method:
EntityManager mysql = ...;
EntityManager postgres = ...;
MyEntity e = new MyEntity();
e.setStuff();
mysql.persist(e);
postgres.persist(e);
The MyEntity
class specifies a @GeneratedValue
strategy of IDENTITY
for its @Id
field, and the two data sources are non-XA data sources.
JPA/JTA seems to want to do this in a distributed transaction, which I believe is due to how the transaction boundaries are determined for container-managed transactions, and I get an error because the data sources are non-XA. I can define the data sources as XA sources so the above works as a distributed transaction, but for the immediate need, that's really unnecessary. I don't really care that the two persists are in the same transaction -- In fact, if one fails and the other succeeds, that's fine too (at least for now).
Is there a way to persist the same object to multiple databases with non-XA data sources and still use container-managed transactions? Related, if I want to do a series of persists with multiple objects and multiple data sources in a single method, is there a way to do that with non-XA data sources? I'm using EclipseLink with GlassFish 4.0.
Well, didn't discover how to do it with container-managed transactions, but did it with bean-managed transactions. Injected a UserTransaction resource, and wrapped each persist between a begin/commit pair:
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class MyClass
{
@Resource private UserTransaction utx;
public void doStuff()
{
EntityManager mysql = ...;
EntityManager postgres = ...;
MyEntity e = new MyEntity();
e.setStuff();
try {
utx.begin();
mysql.persist(e);
utx.commit();
utx.begin();
postgres.persist(e);
utx.end();
} catch (...) {
...
}
}
}
I've never tried using bean-managed transactions before, and even though this isn't for production use and isn't especially elegant, if there's something fundamentally wrong with this, I'd appreciate somebody pointing out the proper way.