2010-03-15 3 views
1

J'utilise JPA et permet de dire que je fais quelque chose comme çaJPA, scope et autosave?

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(...) 
    } 
... 
} 

Donc, pour ces objets qui passent « someTest » et les valeurs sont mises à jour sont ces changements persistaient automatiquement à la DB, même si il n'y a pas de transaction et je ne pas explicitement "manager.save (state)" l'objet? Je demande parce que cela semble être le cas et je me demandais si le flush le fait?

+0

Comment/où exécutez-vous ce code? Quel type de transaction utilisez-vous (RESOURCE_LOCAL ou TRANSACTION)? –

Répondre

0

Comment savez-vous qu'il n'y a pas de transaction? L'utilisez-vous chez EJB? Dans ce cas, je parie qu'il y a une transaction.

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

Si FlushModeType.COMMIT est réglé, l'effet des mises à jour apportées à des entités dans le contexte de persistance sur les requêtes est non spécifiée. Si aucune transaction n'est active, le fournisseur de persistance ne doit pas vider la base de données à .

Si vous êtes en transaction, les entités attachées (c'est-à-dire celles chargées dans la même transaction) sont automatiquement enregistrées dans la base de données.

+0

Je crée l'entitymanager (juste avant que j'appelle la méthode ci-dessus je fais EntityManager manager = emFactory.createEntityManager();) moi-même, donc je sais qu'il n'y a pas d'autres transactions. – arinte

1

Selon le javadoc de FlushMode (je suppose que c'est une JPA 1.0 question), et comme l'a souligné @Konrad:

S'il n'y a pas de transaction active, le fournisseur de persistance ne doit pas rincer à la base de données.

Puisque vous êtes très probablement à l'aide d'un transaction-type="RESOURCE_LOCAL" pour votre unité de persistance, puisque je ne vois pas begin/commit entourant vos appels à votre EntityManager (ce qui est bon, plus sur ce juste après), pour moi il n'y a pas de transaction active donc je ne m'attendrais pas à ce que quoi que ce soit soit vidé.

Quoi qu'il en soit, comme l'a rappelé dans la page JPA Concepts belle:

  • Avec <persistence-unit transaction-type="RESOURCE_LOCAL"> vous êtes responsable deEntityManager (PersistenceContext/Cache) la création et le suivi ...
    • Vous doit utiliser le EntityManagerFactory pour obtenir un EntityManager
    • Le EntityManager résultant par exemple est un PersistenceContext/Cache
    • Un EntityManagerFactory peut être injecté via le @PersistenceUnit annotation seulement (pas @PersistenceContext)
    • Vous êtes pas autorisés à utiliser @PersistenceContext de se référer à une unité de type RESOURCE_LOCAL
    • Vous doit utiliser l'API EntityTransaction pour commencer/commit autour de chaque appel à votre EntityManger
    • L'appel entityManagerFactory.createEntityManager() deux fois les résultats dans deux séparé instances EntityManager et à cet effet deux séparer PersistenceContexts/Caches.
    • Il est presque jamais une bonne idée d'avoir plus d'un exemple d'un EntityManager en cours d'utilisation (ne pas créer une seconde à moins que vous avez détruit la première )

donc, à mon avis, vous devriez fixer votre code ici, il n'y a pas de véritable point à se demander sur le comportement inattendu si votre code est incorrect . Il suffit d'effectuer des appels à votre EntityManager dans une transaction.