Urb*_*leg 4 java spring jpa spring-data
我有以下服务:
@Service
public class CamelService {
@Transactional
public aCamelThing() {
Camel camel = this.camelRepository.findOne(1);
System.out.println(camel.getCamelName()); // prints "normalCamel"
// simple hql set field 'camelName'
int res = this.camelRepository.updateCamelName(1,"superCamel!");
Camel camelWithNewName = this.camelRepository.findOne(1);
System.out.println(camelWithNewName .getCamelName()); // prints "normalCamel" ?!?!?
}
}
Run Code Online (Sandbox Code Playgroud)
我知道如何实现第二张println打印的目标:"superCamel!" ?(将第二次调用与新事务分开并不理想).
Oli*_*ohm 16
你看到它工作的原因很简单:JPA被定义为以这种方式工作.
我假设您触发更新查询updateCamelName(…).JPA规范声明了以下更新和删除操作:
持久性上下文与批量更新或删除的结果不同步.
执行批量更新或删除操作时应谨慎使用,因为它们可能导致数据库与活动持久性上下文中的实体之间出现不一致.通常,批量更新和删除操作应仅在新持久性上下文中的事务中执行,或者在获取或访问其状态可能受此类操作影响的实体之前执行.
这意味着,如果您需要查看此类操作的更改,则需要执行以下操作:
EntityManager此操作后.Spring Data JPA的@Modifying注释有一个clearAutomatically默认的标志false.如果将其设置为true,则调用查询方法将EntityManager自动清除(顾名思义.请谨慎使用,因为它会有效地删除尚未刷新到数据库的所有待处理更改!EntityManager.调用findOne(…)存储库似乎是一种合理的方式,因为这大致转化为EntityManager.find(…).请注意,这可能仍会遇到在持久性提供程序上配置的二级缓存.解决这个问题最安全的方法是 - 正如规范建议的那样 - 仅对批量操作使用更新查询,并在默认情况下回退到"加载实体,更改,合并"方法.