2017-03-10 4 views
0

Ich habe folgendes Service Layout verschachtelte Transaktionen:Transfer abbrechen Alle DB Commits in geschachtelte Transaktionen im Frühjahr

@Component 
public class Main implements RPCInterface { 

    @Autowired 
    private ServiceA serviceA; 

    @Autowired 
    private ServiceB serviceB; 

    @Autowired 
    private ServiceC serviceC; 

    @Override 
    @Transactional (value="txManager", propagation=Propagation.REQUIRED, rollbackFor={ExceptionOne.class, ExceptionTwo.class, ExceptionThree.class}) 
    public void outerMethod() throws ExceptionO { 

    try { 
     serviceA.methodA(); 
     serviceB.methodB(); 
     serviceC.methodC(); 

    } catch (ExceptionOne e) { 
     throw new ExceptionO(e.getMessage, e); 
    } catch (ExceptionTwo e) { 
     throw new ExceptionO(e.getMessage, e); 
    } catch (ExceptionThree e) { 
     throw new ExceptionO(e.getMessage, e); 
    } 
    } 
} 

@Service 
public class ServiceA implements SA { 

    @Autowired 
    private ServiceA1 serviceA1; 

    @Override 
    public void methodA() { 
    serviceA1.methodA1(); 
    } 
} 

@Service 
public class ServiceA1 implements SA1 { 
    @Autowired 
    private ServiceDBTable1 serviceDBTable1; 

    @Autowired 
    private ServiceA1A serviceA1A; 

    @Transactional 
    @Override 
    public void methodA1() { 
    serviceDBTable4.callToMapper4(); 
    serviceA1A.methodA1A(); 
    } 
} 

@Service 
@Transactional (value="txManager", propagation=Propagation.REQUIRED) 
public class ServiceA1A implements SA1A { 

    @Autowired 
    private ServiceDBTable2 serviceDBTable2; 

    @Override 
    public void methodA1A() { 
    serviceDBTable1.callToMapper1(); 
    } 
} 

@Service 
public class ServiceB implements SB { 

    @Autowired 
    private ServiceDBTable3 serviceDBTable3; 

    @Override 
    @Transactional (value="txManager", propagation=Propagation.REQUIRED) 
    public void methodB() { 
    serviceDBTable3.callToMapper3(); 
    } 
} 

@Service 
public class ServiceC implements SC { 

    @Override 
    public void methodC() throws ExceptionThree { 
    // code that throws ExceptionThree 
    } 
} 

Ich brauche alle machen die DB-Anrufe innerhalb ServiceA und ServiceB verschachtelte Aufrufe Rollback, wenn ServiceC#methodC() eine Ausnahme auslöst (oder irgendeine von denen, die eine Ausnahme auslöst - ServiceA oder ServiceB).

Ich habe versucht, Main#outerMethod transaktional mit REQUIRED Ausbreitung zu machen, aber es scheint, als ob die Datenbank-Commits nicht zurückgerollt werden. Ich habe sogar die spezifischen Klassen mit rollbackFor spezifiziert, aber die commits bestehen fort. Kann jemand dieses Problem beheben?

+0

Warum setzen Sie innerMethodThree nicht in dieselbe Transaktion wie innerMethod_1a und 2a? – Simon

+0

@Simon Wie erreiche ich das? 'innerMethodThree' muss nach 1) und 2) aufgerufen werden. – NuCradle

+0

setze @Transactional auf die äußere Methode und brauche keine neue für 1a und 2a – Simon

Antwort

1

Was ich getan habe, um es Arbeit zu machen war ServiceB.methodB() und ServiceC.methodC() Anrufe ServiceA.methodA() zu migrieren, und machen methodA()@Transactional während alle von methodA() und Rollbacks meine Ausnahmen werfen auf der Grundlage dieser drei Ausnahmen (meine Logik erlaubt mir tatsächlich, das zu tun):

@Component 
public class Main implements RPCInterface { 

    @Autowired 
    private ServiceA serviceA; 

    @Override 
    public void outerMethod() throws ExceptionO { 

    try { 
     serviceA.methodA(); 

    } catch (ExceptionOne e) { 
     throw new ExceptionO(e.getMessage, e); 
    } catch (ExceptionTwo e) { 
     throw new ExceptionO(e.getMessage, e); 
    } catch (ExceptionThree e) { 
     throw new ExceptionO(e.getMessage, e); 
    } 
    } 
} 

@Service 
public class ServiceA implements SA { 

    @Autowired 
    private ServiceA1 serviceA1; 

    @Autowired 
    private ServiceB serviceB; 

    @Autowired 
    private ServiceC serviceC; 

    @Override 
    @Transactional (value="txManager", propagation=Propagation.REQUIRED, rollbackFor={ExceptionOne.class, ExceptionTwo.class, ExceptionThree.class}) 
    public void methodA() throw ExceptionOne, ExceptionTwo, ExceptionThree { 
    serviceA1.methodA1(); 
    serviceB.methodB(); 
    serviceC.methodC(); 
    } 
} 

@Service 
public class ServiceA1 implements SA1 { 
    @Autowired 
    private ServiceDBTable1 serviceDBTable1; 

    @Autowired 
    private ServiceA1A serviceA1A; 

    @Transactional 
    @Override 
    public void methodA1() { 
    serviceDBTable4.callToMapper4(); 
    serviceA1A.methodA1A(); 
    } 
} 

@Service 
@Transactional (value="txManager", propagation=Propagation.REQUIRED) 
public class ServiceA1A implements SA1A { 

    @Autowired 
    private ServiceDBTable2 serviceDBTable2; 

    @Override 
    public void methodA1A() { 
    serviceDBTable1.callToMapper1(); 
    } 
} 

@Service 
public class ServiceB implements SB { 

    @Autowired 
    private ServiceDBTable3 serviceDBTable3; 

    @Override 
    @Transactional (value="txManager", propagation=Propagation.REQUIRED) 
    public void methodB() { 
    serviceDBTable3.callToMapper3(); 
    } 
} 

@Service 
public class ServiceC implements SC { 

    @Override 
    public void methodC() throws ExceptionThree { 
    // code that throws ExceptionThree 
    } 
} 
0

Da es keinen Code gibt, ist es schwer zu wissen. Transaktionen funktionieren jedoch nur, wenn Methoden öffentlich sind. Private Methoden werden nicht proxisiert und daher ist die Transaktionsunterstützung für sie nicht vorhanden.

Lesen Sie durch Declarative Transations - Spring Docs für weitere Details.

Bitte geben Sie den Code ein, wenn Sie immer noch darum kämpfen, bessere Hilfe zu bekommen.

+0

Die inneren Methoden sind alle Serviceaufrufe (ein Service/Objekt, Aufruf eines anderen Service/Objekts), also müssen sie öffentlich sein. Die Frage war, ob die obige Konfiguration funktionieren sollte oder nicht. Die Menge an verstreutem Code macht es schwierig, den tatsächlichen Code zu veröffentlichen, daher die obige gekürzte Version. – NuCradle

Verwandte Themen