开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜