Ich brauche Hilfe beim Debuggen, warum die Transaktionsverwaltung meiner Spring-Boot-App nicht funktioniert.@Transactional Annotation nicht wie erwartet funktioniert
Die Grundidee ist, dass ich 2 Tabellen habe, in die ich etwas schreiben möchte. Wenn irgendetwas in einer der 2 Tabellen schief geht, sollte die Transaktion zurückgesetzt werden und nichts sollte in die Datenbank geschrieben werden.
Hier ist eine vereinfachte Version des Codes:
@Transactional
public void archiveTask(String taskId) {
OffloadedRun run = new OffloadedRun();
run.setStartDateTime(LocalDateTime.now());
calculationRunRepository.save(run);
List<SingleContractCalculationResults> activeResults = contractCalculationResultAccessService.get(taskId);
for (SingleContractCalculationResults result : example) {
for (Map.Entry<String, ContractResults> entry : result.getResultsPerScenario().entrySet()) {
String scenario = entry.getKey();
ContractResults results = entry.getValue();
OffloadedCalculationResult offloadedCalculationResult = new OffloadedCalculationResult();
// offloadedCalculationResult.setOffloadedRun(run);
offloadedCalculationResult.setContractId(result.getContractId());
calculationResultRepository.save(offloadedCalculationResult);
}
}
}
Die Klassen, die ich die auf Spring Data JPA Repositories sind speichern Methoden ausführen, die wie folgt definiert sind:
public interface CalculationRunRepository extends JpaRepository<OffloadedRun, String> {
}
der Linie I Auskommentiert ist eine obligatorische Spalte. Ich tue dies, um eine ConstraintViolationException zu erzwingen, um zu testen, was bei einer Ausnahme passiert, wenn etwas in der zweiten Tabelle gespeichert wird.
Was passiert ist, dass die erste Entität erfolgreich gespeichert wurde, was nicht passiert sein sollte. Ich versuche herauszufinden, warum das so ist.
Meine Spring Boot-Anwendung ist mit @EnableTransactionManagement
konfiguriert, um die @Transactional
Anmerkungen in meinen eigenen Diensten (wie diesem) zu aktivieren.
änderte ich die Protokollstufe für org.springframework.transaction.interceptor
zu sehen, zu verfolgen, was los ist:
o.s.t.i.TransactionInterceptor : Getting transaction for [be.sodemo.calculator.offloading.TaskArchiverImpl.archiveTask]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [be.sodemo.calculator.offloading.TaskArchiverImpl.archiveTask]
o.h.e.j.s.SqlExceptionHelper : SQL Error: 1048, SQLState: 23000
o.h.e.j.s.SqlExceptionHelper : Column 'run_id' cannot be null
o.h.e.j.b.i.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'run_id' cannot be null
at sun.reflect.GeneratedConstructorAccessor2599.newInstance(Unknown Source) ~[?:?]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java) ~[?:1.8.0_102]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_102]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.40.jar:5.1.40]
Nach diesen
Ich bin mir nicht sicher, was die Protokollierung aussehen würde, wenn das Transaktionsmanagement funktioniert, aber es sieht so aus, als würde es jede Transaktion abschließen.
Hat jemand eine Idee, was ich als nächstes versuchen kann, um zu sehen, was schief läuft?
Edit: Bis jetzt habe ich eine MySQL-Datenbank verwendet. Ich habe festgestellt, dass, als ich genau diesen Code in einer H2-Datenbank getestet habe, es so aussieht, als ob der Rollback wie vorgesehen funktioniert. Der einzige Unterschied, den ich sehe, ist, dass eine andere herstellerspezifische Ausnahme ausgelöst wird.
Ich habe versucht, explizit das rollbackFor Attribut auf der @Transactional Anmerkung Einstellung wie folgt:
@Transactional(rollbackFor = {Exception.class, MySQLIntegrityConstraintViolationException.class})
Aber auch das kein Rollback verursacht hat.
Edit:
Diese meine Feder Boot-Einstellungen beziehen sich auf JPA/Hibernate:
spring:
jpa:
hibernate:
ddl-auto: none
dialect: org.hibernate.dialect.MySQL5Dialect
database: mysql
properties:
hibernate:
order_inserts: true
jdbc:
batch_size: 50
datasource:
url: jdbc:mysql://localhost/local-test-db
driver-class-name: com.mysql.jdbc.Driver
Könnten Sie bitte den Import für die Annotation "@Transactional" überprüfen? Stellen Sie sicher, dass es nicht aus den Javax-Paketen importiert wird, sondern aus den Spring-Paketen. – galovics
Es ist die Frühlingsversion der Anmerkung: org.springframework.transaction.annotation.Transactional – geoffreydv
Könnten Sie bitte die Methode 'calculationRunRepository.save (run)' '? Möglicherweise haben Sie hier eine andere Transaktionsfortpflanzung. – galovics