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

2.8k views Asked by At

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.

1

There are 1 answers

0
Chris Manning On BEST ANSWER

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;
    }