Question

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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top