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?
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 forEntityManager
(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.
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.
精彩评论