Hibernate错过现有领域

时间:2017-12-07 12:57:25

标签: java hibernate jpa

我有这样的实体结构

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

我做标准查询

    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()

并在where子句中获取错误:

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

经过一段时间的调试后,我发现实体管理器元模型中的父元类将属性子元素保存为AC列表。 AC显然不包含字段“值”。

知道如何修复此错误吗?

1 个答案:

答案 0 :(得分:0)

我认为没有简单的解决办法。除非您愿意将value移至AC并使CC延长AC<CP>。或类似的东西。

此行为是因为类型擦除。

children的实际泛型类型在运行时不可用,因为编译器根据上限List<AC>将列表转换为泛型类型AC

另见great answer这对我说的很好。

在查询之后,可以检查并将列表/项目转换为实际类型,但在CriteriaQuery内是否可以确定是否可行。