Entity is saved in DB, but never gets fetched
We're using JBoss Seam with JPA and Hibernate as persistence provider. We have encountered a very strange problem.
In our UI we have a tree. When we add a node to the tree, the node gets to postgres DB (the row is there, checked with pgadmin). But the tree is not changed. It appeared that named query (OrganizationEntity.FIND_BY_ISDELETED_MAIN
below) that fetches nodes with their children, doesn't work correctly. The newly created object should appear under OrganizationEntity.childOrganizations
- but it doesn't. FetchType.EAGER
doesn't help, neither session flushing does.
What is the most ridiculous thing is that after about half an hour the query starts to return correct result! How come it happens? Is there any cache in hibernate that needs to be cleared or tweaked?
Thanks in advance!
UI tree:
<rich:tree id="OrgTrees" switchType="ajax" ignoreDupResponses="true">
<rich:recursiveTreeNodesAdaptor
roots="#{organizationServiceBean.getOrgTree()}" var="item"
nodes="#{item.childOrganizations}">
<rich:treeNode>
<a4j:commandLink value="#{item.fname}" ajaxSingle="true"
reRender="organizationViewForm,OrgTree"
onclick="this.disabled=true; if(g_flagChanges){if(confirm('Save changes?')){ updateCheck()} else{this.disabled=false;}}"
oncomplete="this.disabled=false; g_flagChanges=false;">
<f:setPropertyActionListener
target="#{organizationBean4.selectedOrganization}"
value="#{item}" />
<a4j:support event="onclick" />
</a4j:commandLink>
</rich:treeNode>
</rich:recursiveTreeNodesAdaptor>
</rich:tree>
OrganizationServiceBean looks like this:
@Stateless
@Scope(ScopeType.EVENT)
@Name("organizationServiceBean")
public class OrganizationServiceBeanImpl implements OrganizationServiceBean, Serializable {
...
public List<OrganizationEntity> getOrgTree() {
return organizationService.findByIsDeletedMain(0);
}
}
organizationService is the following:
@Stateless
@AutoCreate
@Scope(ScopeType.STATELESS)
@Name("organizationService")
public class OrganizationServiceImpl extends
GenericServiceImpl<OrganizationEntity> implements OrganizationService {
……
public List<OrganizationEntity> findByIsDeletedMain(int isDeleted) {
//entityManager.flush();
List<OrganizationEntity> lOrg = findByCriteria(isDeleted, OrganizationEntity.FIND_BY_ISDELETED_MAIN);
log.info("search finished...");
return lOrg;
}
….
@SuppressWarnings("unchecked")
private List<OrganizationEntity> findByCriteria(Object searchKey,
String namedQuery) {
final Query query = entityManager.createNamedQuery(namedQuery);
query.setParameter("searchKey", searchKey);
List<OrganizationEntity> organizations = null;
try {
organizations = (List<OrganizationEntity>) query.getResultList();
} catch (Exception e) {
LOGGER.error(e.getMessage());
}
return organizations;
}
…..
}
And OrganizationEntity:
@Entity
@Table(name = "organization", uniqueConstraints = { @UniqueConstraint(columnNames = "fname") })
@NamedQueries( {
….
开发者_开发问答 @NamedQuery(name = OrganizationEntity.FIND_BY_ISDELETED_MAIN, query = "select org from OrganizationEntity org where org.isdeleted = :searchKey and org.parentOrganization is null order by org.id", hints={@QueryHint(name="org.hibernate.cacheable",value="false")}),
….})
@Name("organizationEntity")
public class OrganizationEntity extends AbstractEntity {
private static final long serialVersionUID = -9085028098941577562L;
….
public static final String FIND_BY_ISDELETED_MAIN = "OrganizationEntity.findByIsDeleted";
….
// bi-directional many-to-one association to Organization
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "parent_id")
private OrganizationEntity parentOrganization;
// bi-directional many-to-one association to Organization
@OneToMany(mappedBy = "parentOrganization", cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
@Where(clause="isdeleted = 0")
private List<OrganizationEntity> childOrganizations;
}
Edit
The functionality works just fine if we cut conversation id from url - which means that
http://localhost:8080/h2p2/admin/admin.seam?cid=7
doesn't work no matter how many times we refresh it, but
http://localhost:8080/h2p2/admin/admin.seam
works fine.
It's possible that you have a 2nd level cache that's caching the objects retrieved from the query (the query itself is marked as cacheable=false but hibernate could still consult the cache when realizing the objects). You can either evict the parent object from the 2nd level cache after the update (on every server that may have that entity cached) or have the entity manager used in the query ignore the cache.
To do the latter, do the following before you issue the query:
entityManager.setProperty("javax.persistence.cache.retrieveMode", CacheRetreiveMode.BYPASS);
That effectively disables consulting the cache for that query and could be performance concern.
精彩评论