【发布时间】:2018-10-25 08:05:59
【问题描述】:
我在 Spring Boot 项目中使用 Hibernate。
我有以下代码:
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>
【问题讨论】:
-
如果您在
doSomeDbManipulation()的末尾加上session.flush();,有什么变化吗?事务回滚可能仅针对某些特定类型的异常发生。 -
可能
session.delete(entity);刷新(并自动提交?)会话,而save()和persist()不会flush()。 -
但是,之前打开的事务在 doSomething 函数中已经提交是没有意义的。对吗?如果是这样的话......事务性注释背后的想法是什么?
-
这里好像和flush()没有关系,因为问题是我看到变化太早了,而不是预期的时候没看到。不过谢谢。