1
resposta

JPA: Join Fetch com Criteria - relacionamento ManyToMany

Olá, gostaria da ajudar de alguém pois já procurei por uma solução e não tive muito sucesso, mesmo olhando a documentação.

A idéia é fazer método abaixo com(JPQL) utilizando Criteria do JPA.

public List<Produto> filter(ProdutoRastreavelModelFilter p) {
        return entityManager.createQuery("select distinct(p) from Produto p join fetch p.rastreabilidade r where r.pedido = :pedido", Produto.class)
                .setParameter("pedido", p.getNumeroPedido())
                .getResultList();
}

Entity Produto

@Entity
@Table(name = "produto")
public class Produto implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String codigo;
    private String lote;
    private String origem;    
    private YearMonth validade;
    private String descricao;

    @ManyToMany(mappedBy = "produtos")
    private List<Rastreabilidade> rastreabilidade = new ArrayList<>();
}

Entity Rastreabilidade

@Entity
@Table(name = "rastreabilidade")
public class Rastreabilidade implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String pedido;
    private LocalDate dataSeparacao;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "rastreabilidade_produto", joinColumns = {
            @JoinColumn(name = "rastreabilidade_id") }, 
    inverseJoinColumns = { 
            @JoinColumn(name = "produto_id") })
    private List<Produto> produtos = new ArrayList<>();
}

Método com Criteria

    public List<Produto> filter(ProdutoRastreavelModelFilter p) {
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Produto> criteria = builder.createQuery(Produto.class);
        Root<Produto> root = criteria.from(Produto.class);

        root.fetch(Produto_.rastreabilidade);
        criteria.distinct(true);

        Predicate[] predicates = criaRestricoes(p, builder, root);
        criteria.where(predicates);

        TypedQuery<Produto> query = entityManager.createQuery(criteria);
        return query.getResultList();
    }

Método com os predicates

private Predicate[] criaRestricoes(ProdutoRastreavelModelFilter p, CriteriaBuilder builder, Root<Produto> root) {

        List<Predicate> predicates = new ArrayList<>();

        if (p.getNumeroPedido() != null) {
            predicates.add(builder.equal(root.get("rastreabilidade").get("pedido"), p.getNumeroPedido()));
        }

        return predicates.toArray(new Predicate[predicates.size()]);
}

Exceção

Caused by: java.lang.IllegalStateException: Illegal attempt to dereference path source [null.rastreabilidade] of basic type
    at org.hibernate@5.3.9.Final//org.hibernate.query.criteria.internal.path.AbstractPathImpl.illegalDereference(AbstractPathImpl.java:82)
    at org.hibernate@5.3.9.Final//org.hibernate.query.criteria.internal.path.AbstractPathImpl.get(AbstractPathImpl.java:174)
    at deployment.er7system.war//com.carloser7.er7system.dao.RastreabilidadeDAO.criaRestricoes(RastreabilidadeDAO.java:80)
    at deployment.er7system.war//com.carloser7.er7system.dao.RastreabilidadeDAO.filter(RastreabilidadeDAO.java:68)
    at deployment.er7system.war//com.carloser7.er7system.bean.RastreabilidadeBean.filter(RastreabilidadeBean.java:108)
    at deployment.er7system.war//com.carloser7.er7system.bean.RastreabilidadeBean$Proxy$_$$_WeldSubclass.filter(Unknown Source)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.glassfish.javax.el@3.0.1-b08-jbossorg-1//com.sun.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:181)
    at org.glassfish.javax.el@3.0.1-b08-jbossorg-1//com.sun.el.parser.AstValue.invoke(AstValue.java:289)
    at org.glassfish.javax.el@3.0.1-b08-jbossorg-1//com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
    at org.jboss.weld.core@3.1.0.Final//org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
    at org.jboss.weld.core@3.1.0.Final//org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at org.jboss.weld.core@3.1.0.Final//org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
    at org.jboss.weld.core@3.1.0.Final//org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:65)
    at com.sun.jsf-impl@2.3.9.SP01//com.sun.faces.application.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:66)
1 resposta