Mengapa kueri JQL saya mengembalikan hasil yang berbeda dari kueri CriteriaBuilder yang setara?
Saya menggunakan Dropwizard Hibernate dan mengalami masalah dengan pengujian saya. Saya telah menyederhanakan contoh ini sebanyak mungkin. Saya membuat Foo
, memperbaruinya, dan kemudian mencoba untuk mengambilnya. Menggunakan kueri mentah mendapatkan hasil yang benar, tetapi kueri CriteriaBuilder yang setara tidak menangkap pembaruan. Apa yang saya lakukan salah?
@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"
});
}
Ini kode penyiapan saya:
@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();
}
...
}
Saya juga bisa menunjukkan Foo
kelasnya, tapi itu tidak terlalu menarik.
Jawaban
The Foo
contoh masih dalam cache L1 yaitu sesi saat ini yang tidak tersentuh oleh pernyataan update. Sejak Hibernate / JPA harus mempertahankan identitas untuk objek entitas sesi, itu tidak dapat menghapus sesi karena pernyataan pembaruan. Biasanya, seseorang harus menghapus sesi atau me-refresh instance setelah pernyataan pembaruan untuk mencerminkan keadaan saat ini lagi.
Coba lakukan sessionFactory.getCurrentSession().clear();
sebagai gantinya di awal transaksi baca Anda