0

I have such entity structure

@MappedSuperclass
public abstract class Base {
    UUID id;
}

@MappedSuperclass
public abstract class Parent<C extends Child> extends Base {
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<C> children;
}

@MappedSuperclass
public abstract class Child<P extends Parent> extends Base {
    @JoinColumn(name = "parent_id", referencedColumnName = "id")
    @ManyToOne(optional = false)
    private P parent;
}

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name = "ap")
public class AP extends Parent<AC> {}

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name = "ac")
public class AC extends Child<AP> {}

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name = "bp")
public class BP extends Parent<BC> {}

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name = "bc")
public class BC extends Child<BP> {}

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name = "cp")
public class CP extends Parent<CC> {}

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name = "cc")
public class CC extends Child<CP> {
     String value;
}

I do criteria query

    CriteriaQuery<Long> cq = getEntityManager().getCriteriaBuilder().createQuery(Long.class);
    Root<CP> rt = cq.from(CP.class);
    Path child = rt.join("children");
    final CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
    cq.select(criteriaBuilder.count(rt));
    cq.where(criteriaBuilder.equal(child.get("value"), "exists"));
    TypedQuery<Long> q = getEntityManager().createQuery(cq);
    Long res = q.getSingleResult()

and get error on line with where clause:

java.lang.IllegalArgumentException: Unable to locate Attribute  with the the given name [value] on this ManagedType [Base]

After debugging a while I've found out that Parent meta class in entity manager's meta model keeps property children as List of AC. AC obviously doesn't contains field "value".

Any idea how to fix this error?

B. Pleshakov
  • 96
  • 10

1 Answers1

0

I think there is no easy fix. Unless you are willing to move value to AC and make CC to extend AC<CP>. Or something alike.

This behavior is because of type erasure.

The actual generic type of children is not available at runtime because compiler casts list to generic type List<AC> based on the upper bound AC.

See also this great answer that explained this thing to me quite well.

After query it is possible to check and cast the list / items to actual type but not at all sure if it is possible within CriteriaQuery.

pirho
  • 11,565
  • 12
  • 43
  • 70