无论出于何种原因,我都有一个代码,它本质上就像下面这样:它在一个事务/会话中加载一个实例几次:
@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
实例是否总是非空?
答案 0 :(得分:3)
当然你不必调用flush,你应该很少执行flush。然而,证明某事的最佳方法是使用简单的演示,因此我编写了一个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/en-US/JBoss_Enterprise_Web_Platform/5/html/Hibernate_Core_Reference_Guide/objectstate-flushing.html
答案 1 :(得分:-1)
每次代码都在这里传递:
SomeClass someClass = (SomeClass) session()
.createCriteria(SomeClass.class)
.add(Restrictions.eq("name", someName))
.uniqueResult();
someClass
将为null或对数据库中的注册表有引用。
(我假设.add(Restrictions.eq("name", someName))
总是返回一个唯一的结果,否则会抛出异常)
如果要在@ids
创建不同process(someClass);
的对象,则无需担心。
我通常使用 flush ,当数据库动态生成 id 时,我需要对象立即反映它(例如,序列ID),所以我可以用它。
但在您的情况下,我认为您在ids
方法中向someClass
提供了不同的process
,因此您不必担心会出现冲动。
<强> EDITED 强>
... Opsss
我没看到这一行
//应该在后续的标准调用
中找到它
假设这样,你应该冲洗。因此,数据库将反映您的新注册表,否则,只有在整个事务结束时才能看到所有注册表。
另一件事:
如果这是真正的代码,你应该这样做:
SomeClass someClass = (SomeClass) session()
.createCriteria(SomeClass.class)
.add(Restrictions.eq("name", someName))
.uniqueResult();
for(int i=0; i<10; ++i) {
这样,假设您正在搜索同一个对象,则无需在每次迭代时转到数据库。 (第一级缓存可以在这里提供帮助,但是如果你知道它与你获得的对象相同,那就让它在循环之外)。