This is my model:
@Entity
@Table(name="library_entities", schema="jamschema")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="entity_type", discriminatorType=DiscriminatorType.STRING)
@org.hibernate.annotations.DiscriminatorOptions(force=true)
public abstract class Entity {
private UUID id;
private String title;
private String tags;
...
}
@Entity
public abstract class Artwork extends Entity {
private String inheritedTags;
...
}
@Entity
@DiscriminatorValue("A")
public class Album extends Entity {
private Set<Track> tracks;
...
}
@Entity
@DiscriminatorValue("T")
public class Track extends Entity {
private Album album;
...
}
I need to search for entities using their base class attributes (e.g. title, tags, etc.) AND Artwork
's attributes (e.g. inheritedTags) if they exist.
In other words I need a query like this:
SELECT ... FROM Entity entities WHERE entities.title like '...' OR entities.tags like
'...'OR (entities.type in ('A', 'T') AND (entities.inheritedTags like '...' OR
entities.title like '...' OR entities.tags like '...'))
criteriaBuilder.treat()
is not the solution because it only queries the subclass (not the superclass).
And according to this solution the following must be a workaround:
final CriteriaBuilder builder = em.getCriteriaBuilder();
final CriteriaQuery<Entity> query =
builder.createQuery(Entity.class);
Root<Entity> root = query.from(Entity.class);
query.select(root);
query.where(
builder.or(
builder.like(root.get("title"), "%a"),
builder.like(root.get("tags"), "%a"),
builder.and(
builder.equal(root.type(), Artwork.class),
builder.like(
((Root<Artwork>) (Root<?>) root).get("inheritedTags"), "%a")
)
)
)
);
But it's not and I still get the following error:
java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [inheritedTags] on this ManagedType [com...Entity]
at org.hibernate.metamodel.model.domain.internal.AbstractManagedType.checkNotNull(AbstractManagedType.java:148)
at org.hibernate.metamodel.model.domain.internal.AbstractManagedType.getAttribute(AbstractManagedType.java:119)
at org.hibernate.metamodel.model.domain.internal.AbstractManagedType.getAttribute(AbstractManagedType.java:117)
at org.hibernate.metamodel.model.domain.internal.AbstractManagedType.getAttribute(AbstractManagedType.java:44)
at org.hibernate.query.criteria.internal.path.AbstractFromImpl.locateAttributeInternal(AbstractFromImpl.java:111)
at org.hibernate.query.criteria.internal.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:204)
at org.hibernate.query.criteria.internal.path.AbstractPathImpl.get(AbstractPathImpl.java:177)
at com.jamapplicationserver.AppMain.lambda$main$1(AppMain.java:99)
at spark.RouteImpl$1.handle(RouteImpl.java:72)
at spark.http.matching.Routes.execute(Routes.java:61)
at spark.http.matching.MatcherFilter.doFilter(MatcherFilter.java:134)
at spark.embeddedserver.jetty.JettyHandler.doHandle(JettyHandler.java:50)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1584)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.Server.handle(Server.java:501)
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:556)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
at java.base/java.lang.Thread.run(Thread.java:829)
It seems like Hibernate looks for the attribute in the super class and since the attribute (inheritedTags
) is not present on the super class, it throws the exception.
How can I resolve this without changing the model?