2016-07-27 6 views
1

Ich bin mir nicht sicher, wo ich mein Transaction Objekt öffnen soll. In der Serviceschicht? Oder die Controller-Schicht?Java: Wie werden mehrere Hibernate-Transaktionen in einer Anfrage behandelt?

Meine Controller hat grundsätzlich zwei Dienste, nennen wir sie AService und BService. Dann geht mein Code so etwas wie:

public class Controller { 
    public AService aService = new AService(); 
    public BService bService = new BService(); 

    public void doSomething(SomeData data) { 
     //Transaction transaction = HibernateUtil.getSession().openTransaction(); 
     if (data.getSomeCondition()) { 
      aService.save(data.getSomeVar1()); 
      bService.save(data.getSomeVar2()); 
     } 
     else { 
      bService.save(data.getSomeVar2()); 
     } 


     //transaction.commit(); or optional try-catch with rollback 
    } 
} 

Das Verhalten I will, dass, wenn bService#save fehlschlägt, dann könnte ich rufe ein transaction#rollback so dass alles, was in aService gerettet hätte, würde auch zurück gerollt werden. Dies scheint nur möglich zu sein, wenn ich für beide Saves eine einzige Transaktion erstelle.

Aber in einer anderen Perspektive sieht es wirklich hässlich aus, dass meine Controller von der Transaction abhängig ist. Es wäre besser, wenn ich die Transaction innerhalb der jeweiligen Dienste erstellen würde, (etwas wie, wie Spring @Transactional funktioniert), aber wenn ich es so mache, dann weiß ich nicht, wie ich erreichen kann, was ich will ...

EDIT: Fester Code, eine andere Bedingung hinzugefügt. Ich verwende keine Spring-Abhängigkeiten, so dass die Verwendung von @Transactional nicht in Frage kommt.

Antwort

3

Sie können erreichen, was Sie fragen, mit einer anderen Abstraktionsebene und mit Komposition.

public class CompositeABService { 
    @Autowired 
    private AService aservice; 
    @Autowired 
    private BService bservice; 

    @Transactional 
    public void save(Object value1, Object value2) { 
    aservice.save(value1); 
    bservice.save(value2); 
    } 
} 

public class AService { 
    @Transactional 
    public void save(Object value) { 
    // joins an existing transaction if one exists, creates a new one otherwise. 
    } 
} 

public class BService { 
    @Transactional 
    public void save(Object value) { 
    // joins an existing transaction if one exists, creates a new one otherwise. 
    } 
} 

Dieses gleiche Muster typischerweise verwendet, wenn Sie müssen mit mehreren Repositories als Teil einer einzigen Arbeitseinheit (z Transaktion) zu interagieren.

Jetzt ist alles, was Sie brauchen, von Ihrem Controller abhängig: CompositeABService oder wie auch immer Sie es nennen möchten.

+0

Okay - könnte etwas vom Thema abweichen, aber ich verwende keine Spring Abhängigkeiten, so dass ich nur manuell neue Transaktionen erstellen. Wenn ich eine Transaktion in CompositeABService.save() öffne - bedeutet dies, dass das Öffnen einer anderen Transaktion innerhalb von AService.save() und BService.save() einen Fehler verursachen würde. Bitte sehen Sie sich meine Bearbeitung an – mpmp