2017-06-29 6 views
0

endet Ich versuche Container verwaltet Transaktion bestehen bleiben, bevor sein Anwendungsbereich istbenötigen Container verwaltet Transaktion mit Nachdruck beharren vor ihrem Umfang

Die Bean-Klasse zu Ende kommt

kommentierte mit entityManager.flush()
@TransactionAttribute(TransactionAttributeType.REQUIRED) 

Über diesen Link: how we can get JPA EntityManager Flush work habe ich erfahren, dass die Verwendung von entityManager.flush() die Transaktion nicht festschreibt. Dem DBMS werden diese Daten jetzt bekannt sein, andere DB-Sitzungen können es jedoch nicht sehen.

Außerdem habe ich versucht, ein neues Verfahren bean

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 

diesen Link how to commit a transaction in EJB? nennen entityManager.flush() in anderen Transaktion deren Umfang innerhalb der neuen Methode bean kommentierten zu erstellen. Dies funktioniert jedoch nicht.

Ich bin auf der Suche nach einem Ansatz, um eine Transaktion zwangsweise zu committen, um ihren bisherigen Status in DB zu erhalten.

Etwas wie:

entityManager.getTransaction().commit(); 

dies für BMT werden kann CMT aber nicht getan.

Antwort

1

Schließlich habe ich die Lösung für das Problem.

@Stateless 
@TransactionAttribute(TransactionAttributeType.REQUIRED) 
public class OuterBean { 

@EJB 
PersistingBean bean; 
@PersistenceContext 
EntityManager em; 

public void persistData() { 

    em.flush(); 

    procedureCall(); 

    Data data = loadExisitingData(); 
    update(data); 
    update(data); 

    bean.persistDataInOwnTransaction(data,em); 

    em.refresh(getUpdatedEntity()) 

    externalCall(); 
} 
} 

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
public class PersistingBean { 

public void persistDataInOwnTransaction(Data data, EntityManager em) { 
em.merge(data); 
    } 
} 

Hinweis: Hier hatten wir das Glück, dass wir wegen des em.flush() verpflichtet, die Transaktion in erster Linie mit der Version 1, die später beim Aufruf em overrided bekamen einen Prozeduraufruf an der DB hatten. Zusammenführen (Daten) mit inkrementiertem Hibernate Version 2.

em.merge (data) -> überträgt Daten in seperate Transaktion daher Entity wird in der Datenbank in seiner eigenen Transaktion mit dem gleichen EnityManager aktualisiert, der als Parameter in persistDataInOwnTransaction (Data Daten, EntityManager em), überschreibt somit die vorherige Entität in db mit derselben em ID.

em.refresh (getUpdatedEntity()) -> Aktualisiert den Status der Instanz aus der Datenbank, sodass weitere Commits für diese Entität mit Version 3 wie in unserem Fall gegen Ende des Bereichs der Bean-Klasse ausgeführt werden können.

Also am Ende werden mehrere Datensätze nicht in DB erstellt. Die gleiche Entität wird jedes Mal überschrieben, wenn wir versuchen, sie mit einer inkrementellen Hibernate-Version beizubehalten.

0

Sie können die Logik kapseln, die die Daten in einer anderen Bean speichert und mit @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) annotieren. Nach dem Aufruf dieser Methode sollten die persistenten Daten verfügbar sein.

NEUFASSUNG
Beispiel ContainerManagedTranaction (CMT)

@TransactionAttribute(TransactionAttributeType.REQUIRED)  
public class OuterBean { 
    @Inject 
    PersistingBean bean; 

    public void persistData() { 
     Data data = loadExisitingData(); 
     update(data); 
     update(data); 

     bean.persistDataInOwnTransaction(data); 

     externalCall(); 
    } 
} 

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)  
public class PersistingBean { 
    @PersistenceContext 
    EntityManager em; 

    public void persistDataInOwnTransaction(Data data) { 
     em.merge(data); 
     } 
} 

Beispiel BeanManagedTransaction (BMT)
siehe Oracles Java EE Tutorial

@Stateless 
@TransactionManagement(TransactionManagementType.BEAN) 
public class OuterBean { 
    @Resource 
    EJBContext context; 
    @PersistenceContext 
    EntityManager em; 

    public void persistData() { 
     UserTransaction ut = context.getUserTransaction(); 

     try { 
      ut.begin(); 
      Data data1 = loadData1(); 
      update(data1); 

      Data data2 = loadData2(); 
      update(data2); 

      ut.commit(); 
     } catch(Exception ex) { 
      ut.rollBack(); 
     } 

     externalCall(); 
    } 
} 
+0

Wir können die neuen Daten in persistDataInOwnTransaction() beibehalten, nicht die vorhandenen Daten.Mein Flow ist wie: Schritt 1: - Aktualisieren Sie die gleichen Daten Schritt 2: - Aktualisieren Sie die gleichen Daten step3: - Aktualisieren Sie die gleichen Daten // bis hier step4 gemacht, alle Änderungen in Daten bestehen: - einen externen Anruf tätigen Bevor ich den externen Anruf mache, muss ich diese Daten in der DB persistieren. –

+0

Siehe meine aktualisierte Version. Momentan kann ich das nicht testen, aber "merge" fügt die Daten wieder an den Entity Manager an und sollte die aktualisierten Daten beibehalten. –

+0

Danke! Diese Lösung funktioniert für diese Daten, aber ich muss mehrere unabhängige Entitäten innerhalb dieser Transaktion aktualisieren, so dass ich die gesamte Transaktion als Ganzes beibehalten muss. Gibt es eine Möglichkeit, die Transaktion innerhalb öffentlichen void persistData() { Data Data = loadExisitingData(); \t \t Daten2 data2 = loadExisitingData(); Aktualisierung (Daten1); Aktualisierung (Daten2); \t \t ... \t \t alles innerhalb der Transaktion externalCall (done save); } –

Verwandte Themen