2

I would like to query ConcreteEntity where AUser user IS MEMBER of ConcreteEntity.createdBy with

@Entity
public class AUser implements Serializable {
    @Id
    @GeneratedValue
    private Long id;
    private String property;

and

@MappedSuperclass
public class AbstractEntity implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue
    private Long id;
    @ManyToMany
    private Set<AUser> createdBy = new HashSet<>();

and

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
ppublc class ConcreteEntity extends AbstractEntity {
    private String property1;

i.e.

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

I don't get the transition from SetAttribute to PluralAttribute. I know that I'm not supposed to post question with code which doesn't compile, but although I'd say I have a fair understanding of generics, I don't get it here.

I'm using Eclipselink 2.5.2 and JPA 2.1.

Kalle Richter
  • 8,008
  • 26
  • 77
  • 177

1 Answers1

2

look at the Path.get methods:

<Y> Path<Y> get(SingularAttribute<? super X, Y> attribute);

<E, C extends Collection<E>> Expression<C> get(PluralAttribute<X, C, E> collection);

the second should be instead:

<E, C extends Collection<E>> Expression<C> get(PluralAttribute<? super X, C, E> collection);

So, IMHO, it's not your fault, the API is bugged.

A workaround is needed. Just erase the compile-time type (it's erased on run-time, anyway).

You have to do:

Expression<Set<AUser>> createdByExpression = ((Root<AbstractEntity>) (Object) root).get(AbstractEntity_.createdBy);

or

Expression<Set<AUser>> createdByExpression = root.get((SetAttribute<ConcreteEntity, AUser>) (Object) AbstractEntity_.createdBy);

or else

Expression<Set<AUser>> createdByExpression = root.get("createdBy");
Michele Mariotti
  • 7,372
  • 5
  • 41
  • 73
  • I verified this change in the referenced SSCCE (on branch `proposed-api-change`). There's been a [hint about this issue on the jpa-spec list in 2012](http://download.oracle.com/javaee-archive/jpa-spec.java.net/users/2012/11/0523.html) which has simply been ignored - that's why you need issue trackers to track issues, kids. I asked the new list jpa-spec@javaee.groups.io what they think about this issue - but can't post a link here, yet, because - surprise email archives don't have immediate links, like - guess... - issue trackers. – Kalle Richter Jan 30 '18 at 14:15
  • 1
    The issue has been reported at the official issue tracker at https://github.com/javaee/jpa-spec/issues/108. – Kalle Richter Jan 30 '18 at 14:44
  • I'm the author of the bug report you linked :) As you can see I created it on 28 Apr 2015 (on the old JIRA) and it has been ignored too. It's useless to have an issue-tracker if you don't spend time working on reports... – Michele Mariotti Jan 30 '18 at 15:23