2

Using the following code:

EntityManager manager = factory.createEntityManager();
manager.setFlushMode(FlushModeType.AUTO);
PhysicalCard card = new PhysicalCard();
card.setIdentifier("012345ABCDEF");
card.setStatus(CardStatusEnum.Assigned);

manager.persist(card);
manager.close();

when code runs to this line, the "card" record does not appear in the database. However, if using the FlushModeType.COMMIT, and using transaction like this:

EntityManager manager = factory.createEntityManager();
manager.setFlushMode(FlushModeType.COMMIT);

manager.getTransaction().begin();
PhysicalCard card = new PhysicalCard();
card.setIdentifier("012345ABCDEF");
card.setStatus(CardStatusEnum.Assigned);

manager.persist(card);
manager.getTransaction().commit();

manager.close();

it works fine. From the eclipselink's log i can see the previous code doesn't issue an INSERT statement while the second code does.

Do I miss something here? I'm using EclipseLink 2.3 and mysql connection/J 5.1

Wudong
  • 2,320
  • 2
  • 32
  • 46

1 Answers1

3

I am assuming that you are using EclipseLink in a Java SE application, or in a Java EE application but with an application managed EntityManager instead of a container managed EntityManager.

In both scenarios, all updates made to the persistence context are flushed only when the transaction associated with the EntityManager commits (using EntityTransaction.commit), or when the EntityManager's persistence context is flushed (using EntityManager.flush). This is the reason why the second code snippet issues the INSERT as it invokes the EntityTransaction's begin and commit methods, while the first doesn't; an invocation of em.persist does not issue an INSERT.

As far as FlushModeType values are concerned, the API documentation states the following:

COMMIT

public static final FlushModeType COMMIT

Flushing to occur at transaction commit. The provider may flush at other times, but is not required to.


AUTO

public static final FlushModeType AUTO

(Default) Flushing to occur at query execution.

Since, queries haven't been executed in the first case case, no flushing i.e. no INSERT statements corresponding to the persistence of the PhysicalCard entity will be issued. It is the explicit commit of the EntityTransaction in the second, that is resulting in the INSERT statement being issued.

Vineet Reynolds
  • 76,006
  • 17
  • 150
  • 174
  • thanks for the answer. but still something i don't quite understand. When I use the default FlushModelType.Auto, and issues a flush() after the persist(), an Exception occurs when flush, complaining No transaction is currently active. – Wudong Jul 24 '11 at 14:38
  • I think you've confused `FlushModeType` with something else. It is meant to define the flushing behavior of the JPA provider when a query has to be executed, so that the results of the query are consistent with any changes made to the persistence context. – Vineet Reynolds Jul 24 '11 at 14:43
  • As far as the exception thrown is concerned, well I'm not surprised. `EntityManager.persist` will do nothing if there is no transaction and `EntityManager.flush` requires a transaction to flush changes in the persistence context. If you do not start a transaction using `EntityManager.getTransaction.begin()`, then there is no transaction associated with the persistence context, which results in the error on `EntityManager.flush`. – Vineet Reynolds Jul 24 '11 at 14:46
  • If I have to state anything further, it would be that transactions are usually associated with container managed EntityManager instances in a Java EE container. In a Java SE application, you have to start a transaction. Also, `EntityManager.persist` is only useful for marking a entity as a managed entity that is to be persisted later. It is `EntityManager.flush` or `EntityTransaction.commit` that actually issues the `INSERT` statement to the database (see my answer). – Vineet Reynolds Jul 24 '11 at 15:00