Warum funktioniert das Transaktionsverhalten von Grails/Spring in diesem Fall nicht?
Ich habe eine Grals-(2.5.2)-App mit einer MySQL- und einer NoSQL-Interaktion. Es gibt eine Haupt-/Hauptdienstmethode, die 2 andere Methoden aufruft:
class mainService {
static transactional = false
NoSQLDataAccessService noSQLDataAccessService
// main/principal method
@Transactional
void save(json){
// (1) creating domain entities from json
addNewDomainEntities(entities)
// (2)
noSQLDataAccessService.set(json)
}
@Transactional
void addNewDomainEntities(entities){
// save the entities in a mysql schema and use save(flush:true)
// because i need the generated id's
}
}
Wie Sie sehen können, erstellt dieser mainService neue Domänenentitäten (1) und leert die Sitzung, um die IDs zu erhalten. Dann rufe ich eine andere Dienstmethode (2) auf, die das Json in einem NoSQL-Schema speichert:
class NoSQLDataAccessService(){
static transactional = false
void set(json){
try{
// save the json in a NoSQL schema
} catch(Exception ex){
// if fails, i log the exception and throws it again
throws ex
}
}
}
Aber manchmal schlägt noSQLDataAccessService.set() durch externe Ursachen fehl und die zuvor erstellten Entitäten verbleiben weiterhin in der MySQL-Datenbank. (Dies ist das Problem)
Die save-Methode, die alle diese Programmausführungen enthält, wird als @Transactional markiert. Wenn also noSQLDataAccessService.set() eine Ausnahme auslöst, sollten alle vorgenommenen Änderungen wegen des Rollbacks nicht übernommen werden. Ich habe recht?
Sie müssen wahrscheinlich eine RuntimeException, keine Exception, auslösen, um ein Rollback gemäß dieser StackOverflow-Konversation zu erzwingen . Anstatt von:
throws ex
du könntest versuchen:
throw new RuntimeException(ex)
Darüber hinaus würde ich Ihnen empfehlen, Ihre Transaktionsisolation explizit anzugeben. Vielleicht sowas wie:
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.SERIALIZABLE)