Como melhorar essa minha consulta

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=?

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ó.

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

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.

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=?

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.