我将Seam与JPA一起使用(实现为SEAM管理的持久上下文),在我的后台bean中,我将一个实体集合(ArrayList)加载到后台bean中。
如果不同的用户在不同的会话中修改实体之一,我希望这些更改传播到我的会话中的集合,我有一个方法< code>refreshList()并尝试了以下方法...
@Override
public List<ItemStatus> refreshList(){
itemList = itemStatusDAO.getCurrentStatus();
}
使用以下查询
@SuppressWarnings("unchecked")
@Override
public List<ItemStatus> getCurrentStatus(){
String s = "SELECT DISTINCT iS FROM ItemStatus iS ";
s+="ORDER BY iS.dateCreated ASC";
Query q = this.getEntityManager().createQuery(s);
return q.getResultList();
}
重新html" target="_blank">执行查询,只返回我已经拥有的相同数据(我假设它使用的是一级缓存,而不是数据库)
@Override
public List<ItemStatus> refreshList(){
itemStatusDAO.refresh(itemList)
}
调用< code > entitymanager . refresh()时,这应该会从数据库刷新,但是我在使用它时得到了< code > javax . EJB . ejbtransactionrolledbackexception:Entity not managed 异常,通常我会在调用之前使用< code > entitymanager . find byid(Entity . getid)。refresh()以确保它连接到PC,但是当我刷新实体集合时,我不能这样做。
这似乎是一个非常简单的问题,我不相信没有办法强迫JPA/hibernate绕过缓存并访问数据库?!
更新测试用例:
我使用两个不同的浏览器(1和2)加载相同的网页,我在1中进行了修改,更新了其中一个ItemStatus实体中的布尔属性,视图刷新为1以显示更新的属性,我通过PGAdmin检查数据库,行已更新。然后我在浏览器2中按刷新,属性尚未更新
在调用.refresh之前,我尝试使用以下方法合并所有实体,但实体仍未从数据库中更新。
@Override
public void mergeCollectionIntoEntityManager(List<T> entityCollection){
for(T entity: entityCollection){
if(!this.getEntityManager().contains(entity)){
this.getEntityManager().refresh(this.getEntityManager().merge(entity));
}
}
}
尝试将其标记为< code>@Transactional
@Override
@org.jboss.seam.annotations.Transactional
public void refreshList(){
itemList = em.createQuery("...").getResultList();
}
您必须引用由< code > entitymanager . merge()方法返回的实体,类似于:
@Override
public void refreshCollection(List<T> entityCollection){
for(T entity: entityCollection){
if(!this.getEntityManager().contains(entity)){
this.getEntityManager().refresh(this.getEntityManager().merge(entity));
}
}
}
通过这种方式,您应该去掉javax.ejb。EJBTransactionRolledbackException:实体未托管
异常。
更新
也许退回新收藏更安全:
public List<T> refreshCollection(List<T> entityCollection)
{
List<T> result = new ArrayList<T>();
if (entityCollection != null && !entityCollection.isEmpty()) {
getEntityManager().getEntityManagerFactory().getCache().evict(entityCollection.get(0).getClass());
T mergedEntity;
for (T entity : entityCollection) {
mergedEntity = entityManager.merge(entity);
getEntityManager().refresh(mergedEntity);
result.add(mergedEntity);
}
}
return result;
}
或者,如果您可以像这样访问实体ID,您可以更有效:
public List<T> refreshCollection(List<T> entityCollection)
{
List<T> result = new ArrayList<T>();
T mergedEntity;
for (T entity : entityCollection) {
getEntityManager().getEntityManagerFactory().getCache().evict(entity.getClass(), entity.getId());
result.add(getEntityManager().find(entity.getClass(), entity.getId()));
}
return result;
}
你有两个不同的问题。让我们先解决简单的问题。
javax.ejb。EJBTransactionRolledbackException:未管理实体
该查询返回的对象的< code >列表本身不是< code >实体,因此您不能< code >。刷新它。事实上,这就是异常所抱怨的。您要求< code>EntityManager对一个不是已知< code >实体的对象做一些事情。
如果你想<代码>。刷新一堆东西,遍历它们并< code >。单独刷新它们。
刷新项目状态列表
你正在与Hibernate的< code >会话级缓存进行交互,从你的问题来看,你并不期望这样。从Hibernate文档中:
对于附加到特定会话的对象(即会话范围内的对象)…数据库标识的JVM标识由Hibernate保证。
这对查询.getResultList()
的影响是,您不一定能恢复数据库的最新状态。
您运行的< code >查询实际上是获取与该查询匹配的实体id列表。任何已经存在于< code>Session缓存中的id都与已知的实体匹配,而任何没有匹配的id都是基于数据库状态填充的。以前已知的实体根本不会从数据库中刷新。
这意味着,如果在同一事务中的两次Query
执行之间,数据库中某个特定已知实体的某些数据发生了变化,那么第二次查询将不会检测到这种变化。然而,它会拾取一个全新的ItemStatus
实例(除非您使用的是查询缓存,我认为您没有)。
长话短说:使用Hibernate,无论何时您想在单个事务中加载一个实体,然后从数据库中获取对该实体的其他更改,您都必须显式。刷新(实体)
。
您想如何处理这个问题在一定程度上取决于您的用例。我可以立即想到两个选项:
List
一些附加说明
有关于使用查询提示的讨论。以下是它们不起作用的原因:
org.hibernate.cacheable=false这只有在使用查询缓存时才有意义,只有在非常特殊的情况下才推荐使用查询缓存。即使您正在使用它,它也不会影响您的情况,因为查询缓存包含对象id,而不是数据。
这是对Hibernate的第二级缓存的指令。如果启用了第二级缓存,并且您从不同的事务发出两个查询,那么您将在第二个查询中获得过时的数据,并且此指令将解决问题。但是,如果您在两个查询中的同一会话中,则第二级缓存只会发挥作用,以避免此
会话
的新实体加载数据库。
问题内容: 我将SEAM与JPA(实现为Seam托管持久性上下文)一起使用,在后备bean中,我将一组实体(ArrayList)加载到后备bean中。 如果不同的用户修改了另一个会话中的实体之一,而我希望将这些更改传播到会话中的集合中,则我有一种方法并尝试了以下方法… 用以下查询 重新执行查询,这只会返回我已经拥有的相同数据(我假设它正在使用一级缓存而不是访问数据库) 调用,这应该从数据库刷新,但
问题内容: 我在程序开始时,根据数据库中的某些内容,以编程方式在JScrollPane中添加了许多组件(JPanels,JLabels等)。 似乎对于GUI(?)而言,此过程太快了,因此JScrollPane并不总是正确更新,即,即使内部JPanel大于可见区域,滚动条也不可见。 调整窗口大小(JFrame)可以解决此问题,因为我认为Java在调整组件大小时会重新打印它们。 作为测试,我添加了一个
问题内容: 在我的React应用程序中,我有两种不同类型的组件: 演示文稿 和 容器 。大约是Dan Abromov的“ Presentational and Container Components”之后 ,除了我不使用Flux或Redux。 现在,我具有以下结构: 该负责从一些REST API加载数据,如果成功的话,代表们提交的数据的。 该负责添加新用户,再通过调用一个REST API。现在,
问题内容: 是否有可能迫使浏览器刷新缓存的CSS? 这并不是每个请求都那么简单。我们有一个站点已有一段时间稳定的CSS。 现在,我们需要对CSS进行一些重大更新;但是,已缓存CSS的浏览器将在两天内不会收到新CSS,从而导致呈现问题。 有没有一种方法可以强制刷新CSS,还是最好选择特定于版本的CSS URL? 问题答案: 有几件事情需要考虑,有多种方法可以解决。首先,规格 我们要完成什么? 理想情
问题内容: 我正在通过XAMPP开发基于Wordpress源代码的网站。有时,我更改了CSS代码,脚本或其他内容,但我注意到我的浏览器需要花费一些时间来应用修改。这导致我使用多个浏览器刷新一个浏览器,如果不应用新样式,则尝试第二个浏览器,而且总是这样。 有什么办法可以避免这个问题?有时我在更改代码时没有注意到先前的修改。 问题答案: 一般解决方案按Ctrl+ F5(或Ctrl+ Shift+ R)
本文向大家介绍angular4强制刷新视图的方法,包括了angular4强制刷新视图的方法的使用技巧和注意事项,需要的朋友参考一下 使用angular的过程中有时会出现数据已经更新了,但是对于的视图没有更新,针对这一情况,可以是用angular提供的方法强制更新视图。 这里使用NGZone来更新视图 以上这篇angular4强制刷新视图的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也