JAVA Swing:JPA 控制器函数未 return 从数据库更新数据

JAVA Swing: JPA controller function not return updated data from database

我正在使用 JAVA 构建一个带有 JTable 的面板,显示来自 sql 服务器数据库的书籍信息。如果我单击图书按钮,此面板将显示数据。

我的问题是,第一次显示后,如果我更改数据库中的修改数据并重新单击书籍按钮(重新加载面板并显示更改),数据不会改变。

当我调查问题时,我发现负责从数据库中检索数据的函数 return 每次点击的结果相同,尽管数据库中的数据已更改。

这是函数(带断点的第 227 行)

及其作用(这是从 JPA Controller 自动生成的,我没有修改任何东西)

        try
        {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Books.class));
            Query q = em.createQuery(cq);
            if (!all)
            {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        }
        finally
        {
            em.close();
        }

我的想法是,每次单击按钮重新加载 JTable 时,都会调用此函数来连接数据库并在数据库中检索 当前数据 。事实上,虽然它被调用并且它仍然returns 旧数据,而不是在数据库中检索当前数据

谁能解释一下这种情况?

记住一些事情,这是一个经典案例,其中一个线程读取数据快照,另一个线程更新数据,这导致数据不一致。因此,任何此类共享都应该同步。 在您的情况下,事务已经在进行中并且有人修改了数据库中的数据,因此您必须再次刷新所有内容然后您将看到修改后的数据。

我在 spring-boot 中的一个实施过程中遇到了同样的问题。 我已经使用 entityManager.refresh(entity).

解决了同样的问题

您需要使用EntityManager刷新加载的数据。

EntityManager.refresh() 操作用于从数据库中刷新对象的状态。这会将当前事务中对对象所做的任何未刷新更改还原,并将其状态刷新为数据库中当前定义的状态。如果发生刷新,它将刷新为刷新的内容。必须在托管对象上调用刷新,因此如果您有非托管实例,您可能首先需要找到具有活动 EntityManager 的对象。

另一个解决方案 是使用清除缓存 entityManager.getEntityManagerFactory().getCache().evictAll();

这将清空缓存,并获取在实体管理器之外更改的对象,它将执行实际的数据库查询,而不是使用过时的缓存值。

逐出和刷新的区别

evict: 在缓存中将实例标记为不再需要。
refresh: 从数据库中刷新实例的状态,覆盖对实体所做的更改