Como melhorar essa minha consulta

5 respostas
jpajavahibernate
Dayson_Rodrigues

Bom amigos, estou aprendendo JPA com Hibernate e estou com pequeno problema, ao carregar meu Carro ele está trazendo todos os modelos, devido a um exemplo no curso que estou assistindo, vejamos que faz vários select.

OBS: Vi que posso fazer isso, diminuindo varios select só que não estou conseguindo.
Segue meu codigo.

@Entity
@Data
public class Carro implements Serializable {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long codigo;
	
	@NotBlank
	@NotNull
	@Pattern(regexp="([a-zA-Z]{3}-\\d{4})?")
	@Size(max=8) 
	@Column(unique = true,nullable = false , length=8)
	private String placa;
	
	@NotBlank
	@NotNull
	@Size(max=15) 
	@Column(nullable = false , length=15)
	private String cor;
	
	@NotBlank
	@NotNull
	@Pattern(regexp="\\d{4}")
	@Column(length=4)
	private String ano;
	
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name="codigo_modeloCarro")
	private ModeloCarro modeloCarro;

ModeloCarro

@Entity
@Table(name = "modelo_carro")
@Data
public class ModeloCarro implements Serializable{

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long codigo;

	@NotNull
	@NotBlank
	@Size(max = 30, min = 2)
	@Column(nullable = false, length = 30)
	private String nome;

	@Enumerated(EnumType.STRING)
	private Categoria categoria;

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "codigo_fabricante")
	private Fabricante fabricante;

Minha Consulta

public List<Carro> buscarTodos() {
		CriteriaBuilder builder = manager.getCriteriaBuilder();
		CriteriaQuery<Carro> criteriaQuery = builder.createQuery(Carro.class);
		
		Root<Carro> carro = criteriaQuery.from(Carro.class);
		
		Join<Carro, ModeloCarro> modelo = (Join) carro.fetch("modeloCarro"); //Já traz toda propriedade do modelo
		List<Carro> carros = manager.createQuery(criteriaQuery).getResultList();
		
		return carros;
	}

Meu Resultado da consulta

Hibernate: 
  Hibernate: 
select
    carro0_.codigo as codigo1_0_,
    carro0_.ano as ano2_0_,
    carro0_.cor as cor3_0_,
    carro0_.codigo_modeloCarro as codigo_m5_0_,
    carro0_.placa as placa4_0_ 
from
    Carro carro0_ limit ?
Hibernate: 
select
    count(carro0_.codigo) as col_0_0_ 
from
    Carro carro0_
Hibernate: 
select
    modelocarr0_.codigo as codigo1_4_0_,
    modelocarr0_.categoria as categori2_4_0_,
    modelocarr0_.codigo_fabricante as codigo_f4_4_0_,
    modelocarr0_.nome as nome3_4_0_ 
from
    modelo_carro modelocarr0_ 
where
    modelocarr0_.codigo=?
Hibernate: 
select
    modelocarr0_.codigo as codigo1_4_0_,
    modelocarr0_.categoria as categori2_4_0_,
    modelocarr0_.codigo_fabricante as codigo_f4_4_0_,
    modelocarr0_.nome as nome3_4_0_ 
from
    modelo_carro modelocarr0_ 
where
    modelocarr0_.codigo=?
Hibernate: 
select
    modelocarr0_.codigo as codigo1_4_0_,
    modelocarr0_.categoria as categori2_4_0_,
    modelocarr0_.codigo_fabricante as codigo_f4_4_0_,
    modelocarr0_.nome as nome3_4_0_ 
from
    modelo_carro modelocarr0_ 
where
    modelocarr0_.codigo=?
Hibernate: 
select
    modelocarr0_.codigo as codigo1_4_0_,
    modelocarr0_.categoria as categori2_4_0_,
    modelocarr0_.codigo_fabricante as codigo_f4_4_0_,
    modelocarr0_.nome as nome3_4_0_ 
from
    modelo_carro modelocarr0_ 
where
    modelocarr0_.codigo=?
Hibernate: 
select
    modelocarr0_.codigo as codigo1_4_0_,
    modelocarr0_.categoria as categori2_4_0_,
    modelocarr0_.codigo_fabricante as codigo_f4_4_0_,
    modelocarr0_.nome as nome3_4_0_ 
from
    modelo_carro modelocarr0_ 
where
    modelocarr0_.codigo=?
Hibernate: 
select
    modelocarr0_.codigo as codigo1_4_0_,
    modelocarr0_.categoria as categori2_4_0_,
    modelocarr0_.codigo_fabricante as codigo_f4_4_0_,
    modelocarr0_.nome as nome3_4_0_ 
from
    modelo_carro modelocarr0_ 
where
    modelocarr0_.codigo=?

5 Respostas

lvbarbosa

Tem certeza que esses selects depois do primeiro são causados na linha do getResultList()? Tenho uma leve impressão que são os selects do Lazy Loading depois que esse método retorna e você acessa o ModeloCarro. Penso isso porque essa linha

Join<Carro, ModeloCarro> modelo = (Join) carro.fetch("modeloCarro");

não faz o select, mas cria um objeto que deveria ser utilizado na query de alguma forma. Nunca experimentei fazer join dessa forma com a Criteria API, mas conheço seu design e essas criações de “blocos” para a query final não aciona a query por si só.

Dayson_Rodrigues

olá, obrigado pela ajuda. Na realidade não entendi muito bem que explicou.

lvbarbosa

Esse objeto do tipo Join não dá trigger na query. O mero ato de criar esse objeto Join<Carro, ModeloCarro> modelo não emite uma query ao banco de dados. Você precisa utilizar esse objeto dentro da query de alguma forma (que ainda não sei como) para que o join seja feito no primeiro select. Vou pesquisar aqui e já venho te ajudar, caso ninguém apareça.

lvbarbosa
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Carro> carroQuery = cb.createQuery(Carro.class);

Root<Carro> carroRoot = carroQuery.from(Carro.class);
carroRoot.fetch("modelo", JoinType.INNER); // essa linha desencadeia o fetch 
carroQuery.select(carroRoot);
TypedQuery<Carro> carroTypedQuery = em.createQuery(carroQuery);

Fiz assim e a query foi:

Hibernate: 
    select
        carro0_.id as id1_0_0_,
        modelo1_.id as id1_1_1_,
        carro0_.modelo_id as modelo_i2_0_0_,
        modelo1_.nome as nome2_1_1_ 
    from
        Carro carro0_ 
    inner join
        Modelo modelo1_ 
            on carro0_.modelo_id=modelo1_.id

Sem aquela linha, a query fica assim:

Hibernate: 
    select
        carro0_.id as id1_0_,
        carro0_.modelo_id as modelo_i2_0_ 
    from
        Carro carro0_

Hibernate: 
    select
        modelo0_.id as id1_1_0_,
        modelo0_.nome as nome2_1_0_ 
    from
        Modelo modelo0_ 
    where
        modelo0_.id=?
lvbarbosa

Não estava completamente certo sobre isso. Eu achava que a Criteria API era imutável. Acontece que os métodos alteram os objetos onde são chamados e retornam o próprio objeto, ao invés de criar um novo com a modificação.

Criado 1 de julho de 2017
Ultima resposta 1 de jul. de 2017
Respostas 5
Participantes 2