tags:

views:

27

answers:

2

I am using JPA and lets say I do something like this

public class MoRun extends Thread {...
public void run() {
    final EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("pu");
    EntityManager manager = emFactory.createEntityManager();
    manager.setFlushMode(FlushModeType.COMMIT);
    someMethod(manager);
    ...
}


public void someMethod(EntityManager manager){
    Query query = manager.createNamedQuery("byStates");
    List<State> list = query.getResultList(); 
    for (State state : list) {
        if(someTest)
            state.setValue(...)
    }
...
}

So for those objects that pass "someTest" and values are updated are those changes automatically persisted to the db even though there is no transaction and I don't explicitly "manager.save(state)" the object? I ask because it seems like it is and I was wondering if the flush is doing it?

A: 

How do you know there is no transaction? Are you using it from EJB? In that case I bet there is a transaction.

From docs (http://java.sun.com/javaee/6/docs/api/javax/persistence/FlushModeType.html):

If FlushModeType.COMMIT is set, the effect of updates made to entities in the persistence context upon queries is unspecified.

If there is no transaction active, the persistence provider must not flush to the database.

If you are in transaction, attached entities (i.e. those loaded in the same transaction) are automatically recorded to database.

Konrad Garus
I am creating the entitymanager (right before I call the method above I do this EntityManager manager = emFactory.createEntityManager();) myself, so I know there are no other transactions.
arinte
+1  A: 

According to the javadoc of FlushMode (I'm assuming this is a JPA 1.0 question), and as pointed out by @Konrad:

If there is no transaction active, the persistence provider must not flush to the database.

Since you're very likely using a transaction-type="RESOURCE_LOCAL" for your persistence unit, since I don't see any begin/commit surrounding your calls to your EntityManager (which is not good, more on this just after), for me there is no transaction active so I wouldn't expect anything to be flushed.

Anyway, as reminded in the nice JPA Concepts page:

  • With <persistence-unit transaction-type="RESOURCE_LOCAL"> you are responsible for EntityManager (PersistenceContext/Cache) creating and tracking...
    • You must use the EntityManagerFactory to get an EntityManager
    • The resulting EntityManager instance is a PersistenceContext/Cache
    • An EntityManagerFactory can be injected via the @PersistenceUnit annotation only (not @PersistenceContext)
    • You are not allowed to use @PersistenceContext to refer to a unit of type RESOURCE_LOCAL
    • You must use the EntityTransaction API to begin/commit around every call to your EntityManger
    • Calling entityManagerFactory.createEntityManager() twice results in two separate EntityManager instances and therefor two separate PersistenceContexts/Caches.
    • It is almost never a good idea to have more than one instance of an EntityManager in use (don't create a second one unless you've destroyed the first)

So, in my opinion, you should fix your code here, there is no real point at wondering about unexpected behavior if your code is not correct. Just performs calls to your EntityManager inside a transaction.

Pascal Thivent