FIltrar elementos de um atributo Collection (@ManyToMany)

Bom dia,

Estou com uma dificuldade na construção de uma consulta. Eu tenho uma classe chamada Grupo que contém um atributo do tipo Collection de Contatos, mapeado com a anotação @ManyToMany.

@Entity
@Table(name = "grupo", schema="addressmobile")
               
public class Grupo implements Serializable {
                   
    private static final long serialVersionUID = 1L;
    
    @Id
    @SequenceGenerator(name="grupo_sequence", sequenceName="addressmobile.grupo_sequence", allocationSize=1)
    @GeneratedValue(generator="grupo_sequence", strategy=GenerationType.SEQUENCE)
    @Column(name = "id", nullable = false)
    private Integer id;
  
    @Column(name = "nome", nullable = false)    
    private String nome;
        
    @JoinTable(name = "addressmobile.grupo_possui_contatos", joinColumns = {@JoinColumn(name = "id_grupo", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "id_contato", referencedColumnName = "id")})
    @ManyToMany(cascade= {CascadeType.MERGE, CascadeType.PERSIST}, fetch=FetchType.EAGER)
    private Collection<Contato> contatos;

    @JoinColumn(name="id_usuario", referencedColumnName="id")
    @ManyToOne
    private Usuario usuario;

}


@Entity
@Table(name = "contato", schema="addressmobile")
@Inheritance(strategy=InheritanceType.JOINED)

public class Contato implements Serializable, Cloneable {
                   
    private static final long serialVersionUID = 1L;
    
    @Id
    @SequenceGenerator(name="contato_sequence", sequenceName="addressmobile.contato_sequence", allocationSize=1)
    @GeneratedValue(generator="contato_sequence", strategy=GenerationType.SEQUENCE)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name = "nome", nullable = false)
    private String nome;

    @Column(name = "sobrenome", nullable = false)
    private String sobrenome;

    @Column(name = "email")
    private String email;
            
    @OneToMany(mappedBy = "proprietario", fetch=FetchType.LAZY)
    private Collection<Telefone> telefones;
}

A consulta deve selecionar os objetos Contato que estão armazenados nos Grupos de determinado Usuario (o usuário é proprietário dos grupos de contato). Sendo assim, a consulta abaixo atende:

Query qry = em.createQuery("Select g.contatos " +
                                   "from Grupo g " +
                                   "where g.usuario= :usuario")
                                   .setParameter("usuario", usuario);
        Collection<Contato> contatos =  qry.getResultList();

Agora, o problema é o seguinte: Nesta consulta, eu preciso filtrar os contatos por nome. Se contatos é um atributo Collection de Grupo, eu não posso fazer algo do tipo where g.contatos.contato.nome = ‘maria’. Como eu faço essa filtragem?

Alguém poderia me ajudar a solucionar esta dúvida? Obrigado!

Você tem que fazer um join (inner, right ou left) para obter os dados.

Rafael, eu tinha pensado em fazer isso…porém vi outro problema: qual critério utilizar na junção?

Seria possível também através de um sub-select do tipo:

Query qry = em.createQuery("Select c from Contato c where c in ( Select g.contatos " + "from Grupo g " + "where g.usuario= :usuario) " + "where c.nome = 'maria' ") .setParameter("usuario", usuario); Collection<Contato> contatos = qry.getResultList();

???..bom, não sei se isso funciona pois não testei…to sem minha máquina aqui no momento. Chegando em casa vou testar.
Caso isso não funcione ou a estratégia de junção for melhor, de um toque ai…obrigado

A melhor forma pro seu caso é fazendo um join.