Home > Back-end >  List in list. Criteria API
List in list. Criteria API

Time:11-12

I have two entities:

AEntity:

@Entity
@Data
public class AEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

}

BEntity:

@Entity
@Data
public class BEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @ManyToMany(fetch = FetchType.EAGER)
    private List<AEntity> aEntities = new LinkedList();
}

I wanna load all BEntities from database by aEntities containing List of AEntity's names using criteria API.

Example:

Database:
AEntities -> {1, "A1"}, {2, "A2"}, {3, "A3"}
BEntities -> {1, AEntities: {1, 2, 3}}, {2, AEntities: {1, 3}}, {3, AEntities: {3}}

If I call mySearchMethod(List.of("A1", "A3")) it should return: {1, AEntities: {1, 2, 3}}, {2, AEntities: {1, 3}} because only these BEntities contains AEntities with names "A1" and "A3"

Tried to implement this with in expression, but it cant find list in list :(

CodePudding user response:

I haven't tried this, but it might work this way:

public List<BEntity> mySearchMethod(List<String> keyList){
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<BEntity> cq = cb.createQuery(BEntity.class);
    Root<BEntity> r = cq.from(BEntity.class);
        
    cq.select(r);
    ArrayList<Predicate> predicates = new ArrayList<>();
    for(String key : keyList) {
        predicates.add(cb.isMember(key, r.get(BEntity_.aEntities)));
    }
    if(predicates.size() > 0) {
        if(predicates.size() == 1) {
            cq.where(predicates.get(0));
        }else {
            cq.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
        }
    }
    TypedQuery<BEntity> query = em.createQuery(cq);

    return query.getResultList();
}
  • Related