Query do jpa

Tenho esta consulta

@Query(value = "SELECT DISTINCT new Categoria(c.id, c.nome, c.metadadoAuditoria.statusDoRegistro, c.tipoCategoria, s, s.nome) FROM InsumoLoja e LEFT OUTER JOIN e.insumo i LEFT OUTER JOIN i.grupo g RIGHT OUTER JOIN g.categoria c LEFT OUTER JOIN c.setor s WHERE (UPPER(c.nome) LIKE :nome or :nome is null) AND (e.loja.id = :idLoja or :idLoja is null) ")
Page<Categoria> pesquisarRetornandoCategoria(@Param("nome") String nome, @Param("idLoja") Long idLoja, Pageable pageable);

Gerou esta consulta, o que traz o resultado correto
select distinct categoria3_.PK_CATEGORIA as col_0_0_, categoria3_.DS_NOME as col_1_0_, categoria3_.ST_REGISTRO as col_2_0_, categoria3_.ST_CATEGORIA_TIPO as col_3_0_, setor4_.PK_SETOR as col_4_0_, setor4_.DS_NOME as col_5_0_ from TAB_INSUMO_LOJA insumoloja0_ left outer join TAB_INSUMO insumo1_ on insumoloja0_.FK_INSUMO=insumo1_.PK_INSUMO left outer join TAB_GRUPO grupo2_ on insumo1_.FK_GRUPO=grupo2_.PK_GRUPO right outer join TAB_CATEGORIA categoria3_ on grupo2_.FK_CATEGORIA=categoria3_.PK_CATEGORIA left outer join TAB_SETOR setor4_ on categoria3_.FK_SETOR=setor4_.PK_SETOR where (upper(categoria3_.DS_NOME) like ? or ? is null) and (insumoloja0_.FK_LOJA=? or ? is null) order by categoria3_.DS_NOME asc offset 0 rows fetch next ? rows only

Só que o count, gera errado no meu ponto de vista aqui traz 413 e só tem 17

gera assim:
select count(distinct insumoloja0_.PK_INSUMO_LOJA) as col_0_0_ from TAB_INSUMO_LOJA insumoloja0_ left outer join TAB_INSUMO insumo1_ on insumoloja0_.FK_INSUMO=insumo1_.PK_INSUMO left outer join TAB_GRUPO grupo2_ on insumo1_.FK_GRUPO=grupo2_.PK_GRUPO right outer join TAB_CATEGORIA categoria3_ on grupo2_.FK_CATEGORIA=categoria3_.PK_CATEGORIA left outer join TAB_SETOR setor4_ on categoria3_.FK_SETOR=setor4_.PK_SETOR where (upper(categoria3_.DS_NOME) like ? or ? is null) and (insumoloja0_.FK_LOJA=? or ? is null)

devendo ser assim, porque traz 17 registros

select count(distinct categoria3_.PK_CATEGORIA) as col_0_0_ from TAB_INSUMO_LOJA insumoloja0_ left outer join TAB_INSUMO insumo1_ on insumoloja0_.FK_INSUMO=insumo1_.PK_INSUMO 
left outer join TAB_GRUPO grupo2_ on insumo1_.FK_GRUPO=grupo2_.PK_GRUPO 
right outer join TAB_CATEGORIA categoria3_ on grupo2_.FK_CATEGORIA=categoria3_.PK_CATEGORIA 
left outer join TAB_SETOR setor4_ on categoria3_.FK_SETOR=setor4_.PK_SETOR where (upper(categoria3_.DS_NOME) like ? or ? is null) 
and (insumoloja0_.FK_LOJA=? or ? is null)

O que pode ser ?

Poste o código completo da entidade?

1 curtida

Categoria

package br.com.ghnetsoft.comprasfood.model;

import static javax.persistence.EnumType.STRING;
import static javax.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;
import static lombok.AccessLevel.PUBLIC;
import static org.hibernate.annotations.CacheConcurrencyStrategy.NONSTRICT_READ_WRITE;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;

import br.com.ghnetsoft.comprasfood.model.enuns.ProdutoInsumoEnum;
import br.com.ghnetsoft.principal.auditoria.AuditableBase;
import br.com.ghnetsoft.principal.enuns.StatusDoRegistroEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@EqualsAndHashCode(of = "id", callSuper = false)
@Setter
@Getter
@Entity
@Builder
@Table(name = "TAB_CATEGORIA")
@NoArgsConstructor(access = PUBLIC)
@AllArgsConstructor(access = PROTECTED)
@Cache(usage = NONSTRICT_READ_WRITE)
public class Categoria extends AuditableBase {

    private static final long serialVersionUID = -1159628968264815235L;
    @Id
    @Column(name = "PK_CATEGORIA")
    @GeneratedValue(strategy = IDENTITY)
    private Long id;
    @ManyToOne(targetEntity = Setor.class)
    @JoinColumn(name = "FK_SETOR")
    private Setor setor;
    @Column(name = "DS_NOME")
    private String nome;
    @Enumerated(STRING)
    @Column(name = "ST_CATEGORIA_TIPO", length = 7)
    private ProdutoInsumoEnum tipoCategoria;

    public Categoria(Long id, String nome, StatusDoRegistroEnum statusDoRegistro, ProdutoInsumoEnum tipoCategoria, Setor setor, String nomeSetor) {
        this.id = id;
        this.nome = nome;
        this.getMetadadoAuditoria().setStatusDoRegistro(statusDoRegistro);
        this.tipoCategoria = tipoCategoria;
        this.setor = setor;
        this.setor.setNome(nomeSetor);
    }
}

InsumoLoja

package br.com.ghnetsoft.comprasfood.model;

import static javax.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;
import static org.hibernate.annotations.CacheConcurrencyStrategy.NONSTRICT_READ_WRITE;

import java.math.BigDecimal;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;

import br.com.ghnetsoft.principal.auditoria.AuditableBase;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@EqualsAndHashCode(of = "id", callSuper = false)
@Setter
@Getter
@Entity
@Builder
@Table(name = "TAB_INSUMO_LOJA")
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor(access = PROTECTED)
@Cache(usage = NONSTRICT_READ_WRITE)
public class InsumoLoja extends AuditableBase {

    private static final long serialVersionUID = -999094130427415229L;
    @Id
    @Column(name = "PK_INSUMO_LOJA")
    @GeneratedValue(strategy = IDENTITY)
    private Long id;
    @ManyToOne(targetEntity = Insumo.class)
    @JoinColumn(name = "FK_INSUMO")
    private Insumo insumo;
    @ManyToOne(targetEntity = Loja.class)
    @JoinColumn(name = "FK_LOJA")
    private Loja loja;
    @Column(name = "NR_QUANTIDADE_ATUAL")
    private BigDecimal quantidadeAtual;
    @Column(name = "NR_QUANTIDADE_MINIMO")
    private BigDecimal quantidadeMinima;
    @Column(name = "NR_QUANTIDADE_PEDIDO")
    private BigDecimal quantidadePedido;
    @Column(name = "NR_DIAS_INVENTARIO")
    private Long diasInventario;
    @Column(name = "VR_CUSTO_MEDIO")
    private BigDecimal custoMedio;
    @Column(name = "VR_ULTIMO_CUSTO")
    private BigDecimal ultimoCusto;
    @Column(name = "DT_ULTIMA_COMPRA")
    private Date ultimaCompra;
    @Column(name = "DS_PLANO_CONTA_CONTABILIDADE")
    private String planoContaContabilidade;
}

Insumo

package br.com.ghnetsoft.comprasfood.model;

import static javax.persistence.EnumType.STRING;
import static javax.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;
import static lombok.AccessLevel.PUBLIC;
import static org.hibernate.annotations.CacheConcurrencyStrategy.NONSTRICT_READ_WRITE;

import java.util.Collection;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.BatchSize;
import org.hibernate.annotations.Cache;

import br.com.ghnetsoft.comprasfood.model.enuns.InsumoFaseEnum;
import br.com.ghnetsoft.principal.auditoria.AuditableBase;
import br.com.ghnetsoft.principal.enuns.SimNaoEnum;
import br.com.ghnetsoft.principal.enuns.StatusDoRegistroEnum;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@EqualsAndHashCode(of = "id", callSuper = false)
@Setter
@Getter
@Entity
@Table(name = "TAB_INSUMO")
@NoArgsConstructor(access = PUBLIC)
@AllArgsConstructor(access = PROTECTED)
@Cache(usage = NONSTRICT_READ_WRITE)
public class Insumo extends AuditableBase {

    private static final long serialVersionUID = -4885091941126527156L;
    @Id
    @Column(name = "PK_INSUMO")
    @GeneratedValue(strategy = IDENTITY)
    private Long id;
    @ManyToOne(targetEntity = Unidade.class)
    @JoinColumn(name = "FK_UNIDADE")
    private Unidade unidade;
    @ManyToOne(targetEntity = Grupo.class)
    @JoinColumn(name = "FK_GRUPO")
    private Grupo grupo;
    @Column(name = "CD_CODIGO_EAN")
    private String codigoEan;
    @Column(name = "CD_CODIGO_EXPORTACAO")
    private String codigoExportacao;
    @Column(name = "DS_NOME")
    private String nome;
    @Column(name = "DS_DESCRICAO")
    private String descricao;
    @Enumerated(STRING)
    @Column(name = "ST_PESAVEL")
    private SimNaoEnum pesavel;
    @Enumerated(STRING)
    @Column(name = "ST_FASE")
    private InsumoFaseEnum fase;
    @OneToMany(mappedBy = "insumo", targetEntity = ProdutoInsumo.class)
    @Cache(usage = NONSTRICT_READ_WRITE)
    @BatchSize(size = 20)
    private Collection<ProdutoInsumo> produtosInsumos;
    @OneToMany(mappedBy = "insumo", targetEntity = InsumoLoja.class)
    @Cache(usage = NONSTRICT_READ_WRITE)
    @BatchSize(size = 20)
    private Collection<InsumoLoja> insumoLojas;
    @OneToMany(mappedBy = "insumo", targetEntity = InsumoLojaFornecedor.class)
    @Cache(usage = NONSTRICT_READ_WRITE)
    @BatchSize(size = 20)
    private Collection<InsumoLojaFornecedor> insumosLojasFornecedores;

    public Insumo(Long id, String codigoEan, String nome, StatusDoRegistroEnum statusDoRegistro, Unidade unidade, Grupo grupo, InsumoFaseEnum fase, String grupoNome, String unidadeNome) {
        this.id = id;
        this.codigoEan = codigoEan;
        this.nome = nome;
        this.getMetadadoAuditoria().setStatusDoRegistro(statusDoRegistro);
        this.unidade = unidade;
        this.grupo = grupo;
        this.fase = fase;
        this.unidade.setNome(unidadeNome);
        this.grupo.setNome(grupoNome);
    }
}

Grupo

package br.com.ghnetsoft.comprasfood.model;

import static javax.persistence.EnumType.STRING;
import static javax.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;
import static org.hibernate.annotations.CacheConcurrencyStrategy.NONSTRICT_READ_WRITE;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;

import br.com.ghnetsoft.comprasfood.model.enuns.ProdutoInsumoEnum;
import br.com.ghnetsoft.principal.auditoria.AuditableBase;
import br.com.ghnetsoft.principal.enuns.StatusDoRegistroEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@EqualsAndHashCode(of = "id", callSuper = false)
@Setter
@Getter
@Entity
@Builder
@Table(name = "TAB_GRUPO")
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor(access = PROTECTED)
@Cache(usage = NONSTRICT_READ_WRITE)
public class Grupo extends AuditableBase {

    private static final long serialVersionUID = -373887947568758268L;
    @Id
    @Column(name = "PK_GRUPO")
    @GeneratedValue(strategy = IDENTITY)
    private Long id;
    @ManyToOne(targetEntity = Categoria.class)
    @JoinColumn(name = "FK_CATEGORIA")
    private Categoria categoria;
    @Column(name = "DS_NOME")
    private String nome;
    @Enumerated(STRING)
    @Column(name = "ST_GRUPO_TIPO")
    private ProdutoInsumoEnum grupoTipo;

    public Grupo(Long id, String nome, StatusDoRegistroEnum statusDoRegistro, ProdutoInsumoEnum grupoTipo, Categoria categoria, String categoriaNome) {
        this.id = id;
        this.nome = nome;
        this.getMetadadoAuditoria().setStatusDoRegistro(statusDoRegistro);
        this.grupoTipo = grupoTipo;
        this.categoria = categoria;
        this.categoria.setNome(categoriaNome);
    }
}

Setor

package br.com.ghnetsoft.comprasfood.model;

import static javax.persistence.EnumType.STRING;
import static javax.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;
import static org.hibernate.annotations.CacheConcurrencyStrategy.NONSTRICT_READ_WRITE;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;

import br.com.ghnetsoft.comprasfood.model.enuns.ProdutoInsumoEnum;
import br.com.ghnetsoft.principal.auditoria.AuditableBase;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@EqualsAndHashCode(of = "id", callSuper = false)
@Setter
@Getter
@Entity
@Builder
@Table(name = "TAB_SETOR")
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor(access = PROTECTED)
@Cache(usage = NONSTRICT_READ_WRITE)
public class Setor extends AuditableBase {

    private static final long serialVersionUID = -1825560977083410942L;
    @Id
    @Column(name = "PK_SETOR")
    @GeneratedValue(strategy = IDENTITY)
    private Long id;
    @Column(name = "DS_NOME")
    private String nome;
    @Enumerated(STRING)
    @Column(name = "ST_SETOR_TIPO")
    private ProdutoInsumoEnum setorTipo;
}

Feito

A questão é que tenho que buscar todas categorias.

Um dos filtros da tela é a loja.

Usa SQL + DTO, bem mais prático e sem essa confusao de classes de entidades.

1 curtida

E pro count nem DTO vai precisar, só mesmo fazer o SQL e retornar um int ou long.

1 curtida

@guilhermebhte aconselho verificar o mapeamento das entidades associadas, esses OneToMany, ManyToOne, e etc.

Observe que esta gerando outer joins estranhos para fazer um count. Provavelmente essas classes estao com mapeamento errado em relação a sua regra de negócio, pois segundo você disse, não está retornando conforme o esperado.

PS: Se voce nao conseguir resolver esse bug, faça um um método count com a query customizada como vc deseja, porém, isso está com cara de erro no mapeamento, e pode trazer outras consequências se não for resolvido.

1 curtida