为什么我的 JQL 查询 return 与等效的 CriteriaBuilder 查询的结果不同?
Why does my JQL query return a different result than the equivalent CriteriaBuilder query?
我正在使用 Dropwizard Hibernate,我的测试遇到了问题。我已经尽可能地简化了这个例子。我创建了一个 Foo
,更新它,然后尝试获取它。使用原始查询可以获得正确的结果,但等效的 CriteriaBuilder 查询不会捕获更新。我做错了什么?
@Test
public void testFoo() {
String id = "12345";
// Create
Foo foo = Foo.builder()
.id(id)
.name("old-name")
.build();
sessionFactory.getCurrentSession().replicate(foo, ReplicationMode.EXCEPTION);
// Update
database.inTransaction(() -> {
CriteriaBuilder cb = sessionFactory.getCurrentSession().getCriteriaBuilder();
CriteriaUpdate<Foo> update = cb.createCriteriaUpdate(Foo.class);
Root<Foo> root = update.from(Foo.class);
update.set(Foo_.name, "new-name");
update.where(cb.equal(root.get(Foo_.id), id));
int updated = sessionFactory.getCurrentSession().createQuery(update).executeUpdate();
});
// Select
database.inTransaction(() -> {
sessionFactory.getCurrentSession().flush(); // Not sure if this matters
String newName = (String) sessionFactory.getCurrentSession()
.createQuery("select name from Foo where id=:id")
.setParameter("id", id)
.getSingleResult();
assertEquals("new-name", newName);
log.error("New name is " + newName);
CriteriaBuilder cb = sessionFactory.getCurrentSession().getCriteriaBuilder();
CriteriaQuery<Foo> cq = cb.createQuery(Foo.class);
Root<Foo> root = cq.from(Foo.class);
cq.where(cb.equal(root.get(Foo_.id), id));
Query query = sessionFactory.getCurrentSession().createQuery(cq);
Foo foo2 = (Foo) query.getSingleResult();
log.error("New name is " + foo2.getName()); // Prints "old-name"
});
}
这是我的设置代码:
@ExtendWith(DropwizardExtensionsSupport.class)
public class UpdateTest {
private SessionFactory sessionFactory;
public DAOTestExtension database = DAOTestExtension.newBuilder()
.addEntityClass(Foo.class)
.build();
@BeforeEach
public void setup() {
sessionFactory = database.getSessionFactory();
}
...
}
我也可以展示Foo
class,但是不是很有趣
Foo
实例仍在 L1 缓存中,即未被更新语句触及的当前会话。由于 Hibernate/JPA 必须保留会话实体对象的标识,因此由于更新语句,它无法清除会话。通常,必须在更新语句后清除会话或刷新实例以再次反映当前状态。
尝试在读取事务开始时执行 sessionFactory.getCurrentSession().clear();
我正在使用 Dropwizard Hibernate,我的测试遇到了问题。我已经尽可能地简化了这个例子。我创建了一个 Foo
,更新它,然后尝试获取它。使用原始查询可以获得正确的结果,但等效的 CriteriaBuilder 查询不会捕获更新。我做错了什么?
@Test
public void testFoo() {
String id = "12345";
// Create
Foo foo = Foo.builder()
.id(id)
.name("old-name")
.build();
sessionFactory.getCurrentSession().replicate(foo, ReplicationMode.EXCEPTION);
// Update
database.inTransaction(() -> {
CriteriaBuilder cb = sessionFactory.getCurrentSession().getCriteriaBuilder();
CriteriaUpdate<Foo> update = cb.createCriteriaUpdate(Foo.class);
Root<Foo> root = update.from(Foo.class);
update.set(Foo_.name, "new-name");
update.where(cb.equal(root.get(Foo_.id), id));
int updated = sessionFactory.getCurrentSession().createQuery(update).executeUpdate();
});
// Select
database.inTransaction(() -> {
sessionFactory.getCurrentSession().flush(); // Not sure if this matters
String newName = (String) sessionFactory.getCurrentSession()
.createQuery("select name from Foo where id=:id")
.setParameter("id", id)
.getSingleResult();
assertEquals("new-name", newName);
log.error("New name is " + newName);
CriteriaBuilder cb = sessionFactory.getCurrentSession().getCriteriaBuilder();
CriteriaQuery<Foo> cq = cb.createQuery(Foo.class);
Root<Foo> root = cq.from(Foo.class);
cq.where(cb.equal(root.get(Foo_.id), id));
Query query = sessionFactory.getCurrentSession().createQuery(cq);
Foo foo2 = (Foo) query.getSingleResult();
log.error("New name is " + foo2.getName()); // Prints "old-name"
});
}
这是我的设置代码:
@ExtendWith(DropwizardExtensionsSupport.class)
public class UpdateTest {
private SessionFactory sessionFactory;
public DAOTestExtension database = DAOTestExtension.newBuilder()
.addEntityClass(Foo.class)
.build();
@BeforeEach
public void setup() {
sessionFactory = database.getSessionFactory();
}
...
}
我也可以展示Foo
class,但是不是很有趣
Foo
实例仍在 L1 缓存中,即未被更新语句触及的当前会话。由于 Hibernate/JPA 必须保留会话实体对象的标识,因此由于更新语句,它无法清除会话。通常,必须在更新语句后清除会话或刷新实例以再次反映当前状态。
尝试在读取事务开始时执行 sessionFactory.getCurrentSession().clear();