Mostrando postagens com marcador JPA. Mostrar todas as postagens
Mostrando postagens com marcador JPA. Mostrar todas as postagens

quarta-feira, 10 de março de 2021

JPA 2.1 - Criteria Builder, evitando query adicional causada por FetchType Lazy (lazy-loading)

 Hoje durante a utilização da api criteria para consultas dinâmicas enquanto realizava um curso, me deparei com uma coisa bem chata, no qual eu possuo 3 beans.
  • Estado
  • Cidade
  • Usuário
Ocorria o seguinte inconveniente, devido essa consulta ser usada em filtros decidi usar o CriteriaBuilder pela facilidade em criar  dinamicamente as consultas, porem todas as vezes que eu realizava uma consulta sempre recebia duas consultas adicionais, uma para Cidade e outra para Estado. E antes que me perguntem sim! marquei como lazy essas relações e não desejo nem quero que sejam JoinType Eager sempre, porem ao usar o CriteriaBuilder ele ignora completamente e volta a usar o lazy-loading.

  
    select
        cliente0_.codigo as codigo1_2_,
        cliente0_.cpf_cnpj as cpf_cnpj2_2_,
        cliente0_.email as email3_2_,
        cliente0_.cep as cep4_2_,
        cliente0_.codigo_cidade as codigo_11_2_,
        cliente0_.complemento as compleme5_2_,
        cliente0_.logradouro as logradou6_2_,
        cliente0_.numero as numero7_2_,
        cliente0_.nome as nome8_2_,
        cliente0_.telefone as telefone9_2_,
        cliente0_.tipo_pessoa as tipo_pe10_2_ 
    from
        cliente cliente0_ 
    where
        1=1 limit ?;

    select
        cidade0_.codigo as codigo1_1_0_,
        cidade0_.codigo_estado as codigo_e3_1_0_,
        cidade0_.nome as nome2_1_0_ 
    from
        cidade cidade0_ 
    where
        cidade0_.codigo=?;

    select
        estado0_.codigo as codigo1_3_0_,
        estado0_.nome as nome2_3_0_,
        estado0_.sigla as sigla3_3_0_ 
    from
        estado estado0_ 
    where
        estado0_.codigo=?

O que de fato não é nem de longe ideal para um bom desempenho, mas então oque fazer ? será que existe uma forma de incorporar na primeira query as duas adicionais ? E a resposta é sim! basta fazer o fetch ,  nas relações que deseja evitar as consultas adicionais, mesma coisa que fazemos no HQL.

   Root cliente = querie.from(Cliente.class);           
            
   cliente.fetch(Cliente_.ENDERECO)//Representa o endereço 
          .fetch(Endereco_.CIDADE, JoinType.LEFT)//Realiza o Fetch de Cliente com Cidade
          .fetch(Cidade_.ESTADO, JoinType.LEFT);  //Realiza o Fetch da Cidade com estado
  
A partir de agora a consulta gerada é a seguinte.
  
    select
        cliente0_.codigo as codigo1_2_0_,
        cidade1_.codigo as codigo1_1_1_,
        estado2_.codigo as codigo1_3_2_,
        cliente0_.cpf_cnpj as cpf_cnpj2_2_0_,
        cliente0_.email as email3_2_0_,
        cliente0_.cep as cep4_2_0_,
        cliente0_.codigo_cidade as codigo_11_2_0_,
        cliente0_.complemento as compleme5_2_0_,
        cliente0_.logradouro as logradou6_2_0_,
        cliente0_.numero as numero7_2_0_,
        cliente0_.nome as nome8_2_0_,
        cliente0_.telefone as telefone9_2_0_,
        cliente0_.tipo_pessoa as tipo_pe10_2_0_,
        cidade1_.codigo_estado as codigo_e3_1_1_,
        cidade1_.nome as nome2_1_1_,
        estado2_.nome as nome2_3_2_,
        estado2_.sigla as sigla3_3_2_ 
    from
        cliente cliente0_ 
    left outer join
        cidade cidade1_ 
            on cliente0_.codigo_cidade=cidade1_.codigo 
    left outer join
        estado estado2_ 
            on cidade1_.codigo_estado=estado2_.codigo 
    where
        1=1 limit ?

Espero ter ajudado pessoas que assim como eu tiveram muitos problemas,  para conseguir realizar esse simples procedimento assim como era feito no HQL.

terça-feira, 1 de outubro de 2019

JPA MAPEAMENTO MAP COM CHAVE ENUM E VALOR OBJECT


A baixo a descrição em código de como Mapear um objeto do tipo Map tendo como chave um Enum e valor uma Entidade que poderia ser qualquer outro Objeto

@Data @AllArgsConstructor @NoArgsConstructor @Builder
@Entity
@Table(schema = "gdf",name = "tb_VeiculoPneus")
 public
 class VeiculoPneus implements Serializable{

    @Id
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "CodVeiculo")
 private Veiculos codigoVeiculo;


    @OneToMany
    @JoinTable(name = "tb_VeiculoPosicaoPneu",schema = "gdf"
       ,uniqueConstraints = 
         @UniqueConstraint(name="UK_PNEU_VEICULOPOSICAOPNEU"
          ,columnNames={"CodPneu"})
       ,joinColumns= 
         @JoinColumn(name="CodVeiculoPneus"
          ,foreignKey= 
            @ForeignKey(name="FK_VEICULOPNEUS_VEICULOPOSICAOPNEU")
         )
       ,inverseJoinColumns=  
         @JoinColumn(name="CodPneu"
          ,foreignKey= 
            @ForeignKey(name="FK_PNEU_VEICULOSPOSICAOPNEU")
         ) 
    )
    @MapKeyEnumerated(EnumType.STRING)
    @MapKeyClass(PosicaoPneu.class)
    @MapKeyColumn(name ="CodPosicao")
 private Map<PosicaoPneu,Pneu> pneus;   

 }

Este mapeamento gera a seguinte saída SQL:

 create table gdf.tb_VeiculoPosicaoPneu
 (
    CodVeiculoPneus int not null
  , CodPneu         bigint not null
  , CodPosicao      varchar(255) not null
  , primary key (CodVeiculoPneus, CodPosicao)
        )
  
 alter table gdf.tb_VeiculoPosicaoPneu 
       add constraint UK_PNEU_VEICULOPOSICAOPNEU 
 unique (CodPneu)
 
 alter table gdf.tb_VeiculoPosicaoPneu 
       add constraint FK_PNEU_VEICULOSPOSICAOPNEU 
       foreign key (CodPneu )
       references gdf.tb_Pneu
    
 alter table gdf.tb_VeiculoPosicaoPneu 
       add constraint FK_VEICULOPNEUS_VEICULOPOSICAOPNEU 
       foreign key (CodVeiculoPneus) 
       references gdf.tb_VeiculoPneus