为什么我的JQL查询返回的结果与等效的CriteriaBuilder查询不同? [英] Why does my JQL query return a different result than the equivalent CriteriaBuilder query?

查看:99
本文介绍了为什么我的JQL查询返回的结果与等效的CriteriaBuilder查询不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Dropwizard Hibernate,但测试遇到问题。我已尽可能简化了此示例。我创建了一个 Foo ,对其进行更新,然后尝试获取它。使用原始查询可获得正确的结果,但等效的CriteriaBuilder查询无法捕获更新。我在做什么错?

I'm using Dropwizard Hibernate and am having issues with my tests. I've simplified this example as much as possible. I create a Foo, update it, and then try to fetch it. Using a raw query gets the correct result, but the equivalent CriteriaBuilder query doesn't catch the update. What am I doing wrong?

    @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 类,但这不是很有趣。

I can also show the Foo class, but it's not very interesting.

推荐答案

Foo 实例仍在L1高速缓存中,即update语句未触及的当前会话。由于Hibernate / JPA必须保留会话实体对象的身份,因此由于update语句,它无法清除会话。通常,必须在更新语句后清除会话或刷新实例,以再次反映当前状态。

The Foo instance is still in the L1 cache i.e. the current session which is not touched by the update statement. Since Hibernate/JPA has to retain identity for entity objects of a session, it can't clear the session due to the update statement. Usually, one has to clear the session or refresh instances after an update statement to reflect the current state again.

尝试执行 sessionFactory.getCurrentSession()。clear() ; 而是在您的读取交易开始时

Try doing sessionFactory.getCurrentSession().clear(); instead at the start of your read transaction

这篇关于为什么我的JQL查询返回的结果与等效的CriteriaBuilder查询不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆