Спящий | Почему сделка "наполовину совершена"
Я работаю с Hibernate в проекте Spring Boot.
У меня есть следующий кусок кода:
public class SomeService {
private Dependency dependency;
@Transactional(readOnly=false)
public void doSomething() {
//some BL code...
dependency.doSomeDbManipualation();
someOperation();
}
public void someOperation() {
//some code that eventually fails
}
}
public class Dependency {
public void doSomeDbManipulation() {
Entity entity = ...; //get the entity from current session by its key
if (entity != null) {
session.delete(entity);
}
OtherEntity oEntity = new OtherEntity();
//set its fields
Long oEntityId = session.save(oEntity);
entity = new Entity();
entity.setForeignKey(oEntityId);
//set other fields
session.persist(entity);
}
}
Теперь в базе данных есть сущность с соответствующим ключом. Поэтому я ожидаю, что при вызове сервиса код, который ищет сущность, действительно найдет ее. Но с тех пор someOperation()
не удается, я ожидаю увидеть никаких изменений в БД.
На самом деле после звонка someService.doSomething()
(и не удается), я смотрю в БД и вижу, что существующий объект был удален! Но новая сущность не была создана (что нормально).
Почему эта сделка "наполовину совершена"?
РЕДАКТИРОВАТЬ: очевидно, delete() и save() фиксируются немедленно. Когда я отлаживаю, я вижу, что сущность немедленно удаляется после завершения этой строки в коде. Также OtherEntity
добавляется сразу в БД.
persist() не совершается немедленно.
Я использую AspectJ для управления транзакциями. Вот соответствующая часть из моего pom.xml:
<project>
...
<dependencies>
...
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
...
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.8.3</version>
</dependency>
</dependencies>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<outxml>true</outxml>
<forceAjcCompile>true</forceAjcCompile>
<source>1.8</source>
<target>1.8</target>
<Xlint>ignore</Xlint>
<complianceLevel>1.8</complianceLevel>
<encoding>UTF-8</encoding>
<verbose>true</verbose>
<preserveAllLocals>true</preserveAllLocals>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<id>AspectJ-Compile</id>
<phase>process-classes</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
</project>
2 ответа
Я нашел решение проблемы. У меня было несколько аннотаций @ComponentScan в нескольких классах. Когда я удалил их все и оставил только один, все работало как положено.
Я не понимаю причину этого странного поведения, поэтому я разместил отдельный вопрос по этому поводу, здесь
Я не знаю, почему аспект j явно добавлен как зависимость в pom file.if, если вы используете весеннюю загрузку, вы получите аспекты из коробки. Я видел непредсказуемое поведение, когда в пути к классам присутствуют повторяющиеся jar-файлы.
Также я не смог понять, почему метод манипуляции с БД вызывается из метода, который сам помечен для транзакции только для чтения.
Я чувствую, что дизайн здесь не правильный.