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:
从数据库中刷新实例的状态,覆盖对实体所做的更改
我正在使用 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:
从数据库中刷新实例的状态,覆盖对实体所做的更改