0

I have a query with Criteria which consists of multiple joins of same entity. The amount of joins is dynamic, the code as following:

@Entity 
public class Member {
    @Id
    Long id;
    String name;
    @OneToMany(...)
    private List<MemberSpec> specs = new ArrayList<>();
}

@Entity
public class MemberSpec {
    @Id
    private Long id
    private String specName;
}

// DTO
public class MemberDTO {
    Member member;
    MemberSpec[] memberSpecs;

    public MemberDTO(Member member, MemberSpec... memberSpecs) {
        this.member = member;
        this.memberSpecs = memberSpecs;
    }
}


// Repository
List<String> specs = List.of("Spec1", "Spec2"..."SpecN");
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<MemberDTO> root = builder.createQuery(MemberDTO.class);
  Root<Member> root = query.from(Member.class);
  List<Selection<?>> joins = new ArrayList<>();
  for (Spec specName : specs) {
        Join<Member, MemberSpec> specsJoin = root.join("specs");
        Predicate conditionName = builder.equal(specsJoin.get("specName").specName);
        joins.add(specsJoin);
    }
root.multiselect(joins);

List<MemberDTO> result = entityManager.createQuery(root).getResultList();

But is when this code executed then I receiving an exception:

org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [MemberDTO]. 
Expected arguments are: Member, MemberSpec, MemberSpec, MemberSpec [
    select new MemberDTO(( generatedAlias3, generatedAlias0, generatedAlias1, generatedAlias2) 
    from Member as generatedAlias3 
        inner join generatedAlias3.specs as generatedAlias0 
        inner join generatedAlias3.specs as generatedAlias1 
        inner join generatedAlias3.specs as generatedAlias2 
        where ( ( generatedAlias0.specName=:param0 ) and 
                ( generatedAlias1.specName=:param1 ) and 
                ( generatedAlias2.specName=:param2 ) ) 
    )
    ]

The exception reason is pretty clear - it's about Hibernate looks for DTO's constructor with exact number of arguments as the joins given. I thought since I used "..." operator I could have dynamic array of joins but obviously no. The problem is that number of joins is dynamic and I can't make different constructors with specific number of joined entity.

How can I achive it?

Nemo
  • 145
  • 1
  • 7

0 Answers0