API Criteria: Filter by Class Type

I am new to relational databases and I have some problems with building queries. First, I want to briefly explain the situation. I have multiple entity classes. They all expand AbstractEntity

or EntityProperty

. Thus, objects can have properties and properties that have their own objects, so there is a bi-directional relationship.
Now let's say ConcreteEntity

extends AbstractEntity

and I want to create queries like this: Get all entities of a type ConcreteEntity

that have at least a property named in the given list propertyNames

. So far, I have the following performance criteria query:

CriteriaQuery<AbstractEntity> cq = cb.createQuery(AbstractEntity.class);
Root<EntityProperty> property = cq.from(EntityProperty.class);
Join<EntityProperty, AbstractEntity> entity = property.join(EntityProperty_.owningEntities);
cq.where(property.get(EntityProperty_.name).in((Object[]) propertyNames));
cq.select(entity);

      

But now I only want those type objects ConcreteEntity

. How could I achieve this? In JPQL I wrote "SELECT entity FROM EntityProperty property JOIN property.owningEntities entity" and here I also don't know how to write it in such a way that only the specific type is returned ...

Thanks for the answers in advance!

EDIT: Moved second question to criteria query: fuzzy result lists and removed in code the code (which didn't work)

+3


source to share


2 answers


I know this is an old question, but just in case someone comes across the same problem, here's how to solve it. You can easily filter by object type like this:

Predicate p = cb.equal(entity.type(), cb.literal(ConcreteEntity.class));

      



where entity can be Path (Root and Join included), cb is a CriteriaBuilder object. So in your case it would be something like this:

CriteriaQuery<AbstractEntity> cq = cb.createQuery(AbstractEntity.class);
Root<EntityProperty> property = cq.from(EntityProperty.class);
Join<EntityProperty, AbstractEntity> entity = property.join(EntityProperty_.owningEntities);
cq.where(cb.and(
    property.get(EntityProperty_.name).in((Object[]) propertyNames),
    cb.equal(entity.type(), cb.literal.ConcreteEntity.class)
));
cq.select(entity);

      

+2


source


The only way I've found so far is to create an enum with a value for each class. As a result of a criteria query

CriteriaQuery<AbstractEntity> cq = cb.createQuery(AbstractEntity.class);
Root<EntityProperty> property = cq.from(EntityProperty.class);
SetJoin<EntityProperty, AbstractEntity> entity =
                property.join(EntityProperty_.owningEntities);
cq.where(property.get(EntityProperty_.name).in((Object[]) propertyNames),
                entity.get(AbstractEntity_.entityType).in(suitableSubTypes));
cq.select(entity);
List<AbstractEntity> resultList = em.createQuery(cq).getResultList();

      

As you can see, each entity now has an entityType attribute. I also have to create a collection of suitable SubTypes every time. Another problem is that the return type List<AbstractEntity>

. What I wanted was a method signature like

public static <T extends AbstractEntity> List<T>
                getEntities(Class<T> entityClass, String... propertyNames)

      



but at the moment i

public static List<AbstractEntity>
                getEntities(Collection<AbstractEntityType> suitableSubTypes,
                String... propertyNames)

      

So, I still hope there is a better solution ...

+1


source







All Articles