javahibernatejboss7.xejb-3.2

How do I select list of generic objects in abstract service using CriteriaQuery


Trying to take this method and optimize performance:

public T getByPrimaryKey(PK id) {
    T entity = getEntityManager().find(getEntityClass(), id);
    if(entity != null) {
        preProcessEntity(entity);
    }
    fireEvent(entity, IEntityEventService.Event.READ, null);
    return entity;
}

The reason is that we have many areas where we get a list of Ids based on native queries, and they are getting processed individually, leading to single queries created by Hibernate. I want to have Hibernate fetch these all at once.

public List<T> getEntitiesByPrimaryKey(List<PK> pks) {
    CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
    CriteriaQuery<T> cq = cb.createQuery(getEntityClass());
    Root<T> root = cq.from(getEntityClass());

    Metamodel m = getEntityManager().getMetamodel();
    EntityType<T> T_ = m.entity(getEntityClass());

    Path<T> keyPath = root.get(T_.getDeclaredId(getEntityClass()));
    cq.select(root);
    cq.where(keyPath.in(pks));

    List<T> entities = getEntityManager().createQuery(cq).getResultList();
    if(entities != null) {
        for (T entity : entities) {
            preProcessEntity(entity);
            fireEvent(entity, IEntityEventService.Event.READ, null);
        }
    }
    return entities;
}

I don't know where to go from here. Primary keys are not guaranteed to be Integer but almost certainly will be.


Solution

  • Here's what fixed it:

        //grabs the primaryKeyClass from generic type argument list (this was AbstractService<PK, T>)
        @SuppressWarnings("unchecked")
        protected Class<PK> primaryKeyClass = (Class<PK>) GenericTypeResolver.resolveTypeArguments(getClass(), AbstractService.class)[0];
    
        protected Class<PK> getPrimaryKeyClass() {
            return primaryKeyClass;
        }
    
        //code to retrieve generic list based on primary key
        public List<T> getEntitiesByPrimaryKey(List<PK> pks) {
            if(pks == null || pks.size() == 0)
                return new ArrayList<T>();
    
            CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
            CriteriaQuery<T> cq = cb.createQuery(getEntityClass());
            Root<T> root = cq.from(getEntityClass());
    
            Metamodel m = getEntityManager().getMetamodel();
            EntityType<T> T_ = m.entity(getEntityClass());
            Path<PK> keyPath = root.get(T_.getId(getPrimaryKeyClass()));
    
            cq.select(root);
            cq.where(keyPath.in(pks));
    
            List<T> entities = getEntityManager().createQuery(cq).getResultList();
            if(entities != null) {
                for (T entity : entities) {
                    preProcessEntity(entity);
                    fireEvent(entity, IEntityEventService.Event.READ, null);
                }
            }
            return entities;
        }