如何指定 JPA 标准 API 和 "MEMBER IN" 以及映射超类中的多对多关系?
How specify a JPA criteria API with "MEMBER IN" and a many-to-many relationship in a mapped superclass?
我想查询 ConcreteEntity
where AUser user
IS MEMBER
of ConcreteEntity.createdBy
with
@Entity
public class AUser implements Serializable {
@Id
@GeneratedValue
private Long id;
private String property;
和
@MappedSuperclass
public class AbstractEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
@ManyToMany
private Set<AUser> createdBy = new HashSet<>();
和
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
ppublc class ConcreteEntity extends AbstractEntity {
private String property1;
即
EntityManager em = ...; //set to null or else
AUser user = ...; //set to null or else
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<ConcreteEntity> criteria = cb.createQuery(ConcreteEntity.class);
Root<ConcreteEntity> concreteRoot = criteria.from(ConcreteEntity.class);
criteria.select(concreteRoot);
SetAttribute<AbstractEntity, AUser> setAttribute = ConcreteEntity_.createdBy;
PluralAttribute<ConcreteEntity, Set<AUser>, AUser> pluralAttribute = setAttribute;
//richtercloud/jpa/criteria/api/metamodel/member/of/NewMain.java:[40,77] error: incompatible types: SetAttribute<AbstractEntity,AUser> cannot be converted to PluralAttribute<ConcreteEntity,Set<AUser>,AUser>
Expression<Set<AUser>> createdByExpression = concreteRoot.get(pluralAttribute);
criteria.where(cb.isNotMember(user, createdByExpression));
TypedQuery<ConcreteEntity> query = em.createQuery(criteria);
List<ConcreteEntity> result = query.getResultList();
我无法从 SetAttribute
过渡到 PluralAttribute
。我知道我不应该 post 质疑无法编译的代码,但尽管我会说我对泛型有一定的了解,但我在这里不明白。
我正在使用 Eclipselink 2.5.2 和 JPA 2.1。
查看Path.get
方法:
<Y> Path<Y> get(SingularAttribute<? super X, Y> attribute);
<E, C extends Collection<E>> Expression<C> get(PluralAttribute<X, C, E> collection);
第二个应该是:
<E, C extends Collection<E>> Expression<C> get(PluralAttribute<? super X, C, E> collection);
所以,恕我直言,这不是你的错,API 有问题。
需要解决方法。只需 擦除 编译时类型(它在 运行 时被擦除,无论如何)。
你必须做的:
Expression<Set<AUser>> createdByExpression = ((Root<AbstractEntity>) (Object) root).get(AbstractEntity_.createdBy);
或
Expression<Set<AUser>> createdByExpression = root.get((SetAttribute<ConcreteEntity, AUser>) (Object) AbstractEntity_.createdBy);
否则
Expression<Set<AUser>> createdByExpression = root.get("createdBy");
我想查询 ConcreteEntity
where AUser user
IS MEMBER
of ConcreteEntity.createdBy
with
@Entity
public class AUser implements Serializable {
@Id
@GeneratedValue
private Long id;
private String property;
和
@MappedSuperclass
public class AbstractEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
@ManyToMany
private Set<AUser> createdBy = new HashSet<>();
和
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
ppublc class ConcreteEntity extends AbstractEntity {
private String property1;
即
EntityManager em = ...; //set to null or else
AUser user = ...; //set to null or else
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<ConcreteEntity> criteria = cb.createQuery(ConcreteEntity.class);
Root<ConcreteEntity> concreteRoot = criteria.from(ConcreteEntity.class);
criteria.select(concreteRoot);
SetAttribute<AbstractEntity, AUser> setAttribute = ConcreteEntity_.createdBy;
PluralAttribute<ConcreteEntity, Set<AUser>, AUser> pluralAttribute = setAttribute;
//richtercloud/jpa/criteria/api/metamodel/member/of/NewMain.java:[40,77] error: incompatible types: SetAttribute<AbstractEntity,AUser> cannot be converted to PluralAttribute<ConcreteEntity,Set<AUser>,AUser>
Expression<Set<AUser>> createdByExpression = concreteRoot.get(pluralAttribute);
criteria.where(cb.isNotMember(user, createdByExpression));
TypedQuery<ConcreteEntity> query = em.createQuery(criteria);
List<ConcreteEntity> result = query.getResultList();
我无法从 SetAttribute
过渡到 PluralAttribute
。我知道我不应该 post 质疑无法编译的代码,但尽管我会说我对泛型有一定的了解,但我在这里不明白。
我正在使用 Eclipselink 2.5.2 和 JPA 2.1。
查看Path.get
方法:
<Y> Path<Y> get(SingularAttribute<? super X, Y> attribute);
<E, C extends Collection<E>> Expression<C> get(PluralAttribute<X, C, E> collection);
第二个应该是:
<E, C extends Collection<E>> Expression<C> get(PluralAttribute<? super X, C, E> collection);
所以,恕我直言,这不是你的错,API 有问题。
需要解决方法。只需 擦除 编译时类型(它在 运行 时被擦除,无论如何)。
你必须做的:
Expression<Set<AUser>> createdByExpression = ((Root<AbstractEntity>) (Object) root).get(AbstractEntity_.createdBy);
或
Expression<Set<AUser>> createdByExpression = root.get((SetAttribute<ConcreteEntity, AUser>) (Object) AbstractEntity_.createdBy);
否则
Expression<Set<AUser>> createdByExpression = root.get("createdBy");