[英]Does a Hibernate transaction rollback delete “session.flush()”ed entities?
[英]Will Hibernate criteria results update during a single transaction without session flush?
无论出于何种原因,我都有一个代码,其本质上执行以下操作:在单个事务/会话中多次加载一个实例:
@Transactional
public void fun(final String someName){
for(int i=0; i<10; ++i) {
SomeClass someClass = (SomeClass) session()
.createCriteria(SomeClass.class)
.add(Restrictions.eq("name", someName))
.uniqueResult();
// when not found
if(someClass == null){
someClass = new SomeClass();
someClass.setName(someName); // it SHOULD be found in subsequent criteria calls
}
process(someClass);
session().saveOrUpdate(someClass);
// session.flush(); // should it be here?
}
}
我不确定的是session().createCriteria...
调用的结果在循环期间是否更改。
它是在事务中,如果我找不到实体-我会创建它(但只能创建一次)。
因此,在第二遍过程中, someClass
实例将始终为非null吗?
当然,您不必调用冲洗,应该很少执行冲洗。 但是,证明某事的最佳方法是使用一个简单的演示,因此我编写了一个Spring Boot / Data示例并将其推到Github上 。 该代码与您的代码等效,并使用Hibernate 4.3.5:
@Transactional
public void createOrUpdateEmployee(String firstName, String lastName) {
for (int i = 0; i < 10; i++) {
Employee employee = repository.findByLastName(lastName);
if (employee == null) {
employee = new Employee(firstName, lastName);
if (i > 0) {
throw new IllegalStateException("This can never happen!");
}
}
log.info(employee);
repository.save(employee);
}
}
输出为:
....350 ...EmployeeService : Employee [id=0, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....396 ...EmployeeService : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....401 ...EmployeeService : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....403 ...EmployeeService : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....405 ...EmployeeService : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....407 ...EmployeeService : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....410 ...EmployeeService : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....412 ...EmployeeService : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....427 ...EmployeeService : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....429 ...EmployeeService : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
就像我期望的那样,该实体是从L1缓存中检索的(hashCode保持不变),并已自动刷新,因为已提到的文档链接指出: https : //access.redhat.com/documentation/zh-CN/JBoss_Enterprise_Web_Platform/5 /html/Hibernate_Core_Reference_Guide/objectstate-flushing.html
每次您的代码通过此处:
SomeClass someClass = (SomeClass) session()
.createCriteria(SomeClass.class)
.add(Restrictions.eq("name", someName))
.uniqueResult();
someClass
将为null或对数据库中注册表的引用。
(我假设.add(Restrictions.eq("name", someName))
始终返回唯一的结果,否则将引发异常)
如果要创建具有不同@ids
对象, @ids
在此处进行process(someClass);
那就不用担心了
我通常使用flush ,当数据库动态生成id时 ,我需要该对象立即反映它(例如,一个序列ID),因此可以使用它。
但是对于您而言,我认为您在process
方法中为someClass
提供了不同的ids
,因此您不必担心刷新。
EDITED
Opsss ...
我没看到这条线
//应该在随后的条件调用中找到
假设这样, 您应该冲洗一下 。 因此,数据库将反映您的新注册表,否则,只有在整个交易结束时才能看到所有注册表。
另一件事:
如果这是真实的代码,则应执行以下操作:
SomeClass someClass = (SomeClass) session()
.createCriteria(SomeClass.class)
.add(Restrictions.eq("name", someName))
.uniqueResult();
for(int i=0; i<10; ++i) {
这样,假设您正在搜索同一对象,则无需在每次迭代时都进入数据库。 (一级缓存可以在这里提供帮助,但是如果您知道它与所获取的对象是同一对象,请将其放在循环之外)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.