เหตุใดแบบสอบถาม JQL ของฉันจึงส่งคืนผลลัพธ์ที่แตกต่างจากแบบสอบถาม CriteriaBuilder ที่เทียบเท่า

Aug 17 2020

ฉันใช้ 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ชั้นเรียนได้ แต่ก็ไม่น่าสนใจเท่าไหร่

คำตอบ

1 ChristianBeikov Aug 18 2020 at 09:16

Fooอินสแตนซ์ยังคงอยู่ใน L1 แคชเช่นเซสชันปัจจุบันซึ่งไม่ได้รับการสัมผัสจากคำสั่งปรับปรุง เนื่องจาก Hibernate / JPA ต้องรักษาข้อมูลประจำตัวสำหรับเอนทิตีอ็อบเจ็กต์ของเซสชันจึงไม่สามารถล้างเซสชันได้เนื่องจากคำสั่งอัพเดต โดยปกติเราต้องล้างเซสชันหรือรีเฟรชอินสแตนซ์หลังจากคำสั่งอัพเดตเพื่อแสดงสถานะปัจจุบันอีกครั้ง

ลองทำsessionFactory.getCurrentSession().clear();แทนตอนเริ่มอ่านธุรกรรมของคุณ