Hibernate carregar lista automaticamente

Bom dia pessoas,

Ando lendo bastante sobre o hibernate, vendo exemplos, mas uma dúvida ainda está na minha cabeça: Se eu tenho uma classe Cliente

[code]public class Cliente {

private Long id;
private String nome;
private List pedidos;

}[/code]

E outra classe Pedido

[code]public class Pedido {

private Long id;
private Cliente cliente;

}[/code]

Utilizando anotações do hibernate eu consigo fazer com que o próprio hibernate carregue sozinho os pedidos de um cliente quando eu instancio um cliente, sem escrever nada de SQL?

Não sei se fui muito claro em minha dúvida, qualquer coisa é só perguntar que esclareço.

Muito obrigado desde já! Abraços!

Quando instancia não;

Mas eu entendi o que vc quis dizer, e sim, ele carrega essa lista automaticamente, se vc assim quiser;

Olá TJvargas,

Primeiramente, muito obrigado por dispor do seu tempo pra me ajudar!

Será que você poderia me ajudar a fazer isso, com estas classes aqui? Eu encontrei vários exemplos por ai, mas parece que sempre falta algo pra eu entender 100%.

Classe Cliente

[code]package models;

public class Cliente {

private Long id;
private String nome;
private List<Pedido> pedidos;

public Cliente() {
	
}

public Cliente(Long id, String nome, List<Pedido> pedidos) {
	this.id = id;
	this.nome = nome;
	this.pedidos = pedidos; 
}
public Long getId() {
	return id;
}
public void setId(Long id) {
	this.id = id;
}
public String getNome() {
	return nome;
}
public void setNome(String nome) {
	this.nome = nome;
}
public List<Pedido> getPedidos() {
	return pedidos;
}
public void setPedidos(List<Pedido> pedidos) {
	this.pedidos = pedidos;
}

}
[/code]

Classe Pedido

[code]package models;

public class Pedido {

private Long id;
private Cliente cliente;
private List<Produto> produtos;

public Pedido() {

}

public Pedido(Cliente cliente, List<Produto> produtos) {
	this.cliente = cliente;
	this.produtos = produtos;
}

public Pedido(Long id, Cliente cliente, List<Produto> produtos) {
	super();
	this.id = id;
	this.cliente = cliente;
	this.produtos = produtos;
}

public Long getId() {
	return id;
}

public void setId(Long id) {
	this.id = id;
}

public Cliente getCliente() {
	return cliente;
}

public void setCliente(Cliente cliente) {
	this.cliente = cliente;
}

public List<Produto> getProdutos() {
	return produtos;
}

public void setProdutos(List<Produto> produtos) {
	this.produtos = produtos;
}

}[/code]

Classe Produto

[code]package models;

public class Produto {

private Long id;
private String nome;
private String descricao;
private double preco;

public Produto(String nome, String descricao, double preco) {
	this.nome = nome;
	this.descricao = descricao;
	this.preco = preco;
}

public Produto() {
	
}

public Long getId() {
	return id;
}

public void setId(Long id) {
	this.id = id;
}

public String getNome() {
	return nome;
}

public void setNome(String nome) {
	this.nome = nome;
}

public String getDescricao() {
	return descricao;
}

public void setDescricao(String descricao) {
	this.descricao = descricao;
}

public double getPreco() {
	return preco;
}

public void setPreco(double preco) {
	this.preco = preco;
}

}[/code]

A única coisa que eu queria é que, ao eu ter um cliente carregado na memória, a lista de pedidos dele fosse preenchida automaticamente pelo hibernate. tem com você me ajudar?

Grato desde já, abraços!

Já tens algo anotado, ou algo funcionando?

Sim sim, segue abaixo

[code]package models;

import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

@Entity
public class Pedido {

@Id
@GeneratedValue
@Column(name="id_pedido")
private Long id;
@OneToMany
@JoinColumn(name = "id_cliente")
private Cliente cliente;
@ManyToMany
@JoinTable(name = "pedido_produto", joinColumns = @JoinColumn(name = "id_pedido"), inverseJoinColumns = @JoinColumn(name= "id_produto"))
private List<Produto> produtos;

public Pedido() {

}

public Pedido(Cliente cliente, List<Produto> produtos) {
	this.cliente = cliente;
	this.produtos = produtos;
}

public Pedido(Long id, Cliente cliente, List<Produto> produtos) {
	super();
	this.id = id;
	this.cliente = cliente;
	this.produtos = produtos;
}

public Long getId() {
	return id;
}

public void setId(Long id) {
	this.id = id;
}

public Cliente getCliente() {
	return cliente;
}

public void setCliente(Cliente cliente) {
	this.cliente = cliente;
}

public List<Produto> getProdutos() {
	return produtos;
}

public void setProdutos(List<Produto> produtos) {
	this.produtos = produtos;
}

}[/code]

[code]package models;

import java.util.List;
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.OneToMany;

@Entity
public class Cliente {

@Id
@GeneratedValue
@Column(name="id_cliente")
private Long id;
@Column(name="nome_cliente")
private String nome;
@ManyToOne
@JoinColumn(name = "id_pedido")
private List<Pedido> pedidos;

public Cliente() {
	
}

public Cliente(Long id, String nome, List<Pedido> pedidos) {
	this.id = id;
	this.nome = nome;
	this.pedidos = pedidos; 
}
public Long getId() {
	return id;
}
public void setId(Long id) {
	this.id = id;
}
public String getNome() {
	return nome;
}
public void setNome(String nome) {
	this.nome = nome;
}
public List<Pedido> getPedidos() {
	return pedidos;
}
public void setPedidos(List<Pedido> pedidos) {
	this.pedidos = pedidos;
}

}[/code]

[code]package models;

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

@Entity
public class Produto {

@Id
@GeneratedValue
@Column(name="id_produto")
private Long id;
@Column(name="nome_produto")
private String nome;
@Column(name="descricao_produto")
private String descricao;
@Column(name="preco_produto")
private double preco;

public Produto(String nome, String descricao, double preco) {
	this.nome = nome;
	this.descricao = descricao;
	this.preco = preco;
}

public Produto() {
	
}

public Long getId() {
	return id;
}

public void setId(Long id) {
	this.id = id;
}

public String getNome() {
	return nome;
}

public void setNome(String nome) {
	this.nome = nome;
}

public String getDescricao() {
	return descricao;
}

public void setDescricao(String descricao) {
	this.descricao = descricao;
}

public double getPreco() {
	return preco;
}

public void setPreco(double preco) {
	this.preco = preco;
}

}[/code]

Gerando a seguinte exception:

Mai 31, 2013 11:38:22 AM org.apache.catalina.core.StandardContext loadOnStartup Grave: Servlet /produtos threw load() exception org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: models.Pedido.cliente at org.hibernate.cfg.annotations.CollectionBinder.getCollectionBinder(CollectionBinder.java:327) at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1721) at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:767) at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:686) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3466) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3420) at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1348) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1747) at br.gov.sp.mococa.dao.MySQLDaoFactory.<init>(MySQLDaoFactory.java:22) at br.gov.sp.mococa.dao.DAOFactory.getDAOFactory(DAOFactory.java:17) at br.gov.sp.mococa.controllers.ClienteController.<init>(ClienteController.java:22) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:76) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:990) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:943) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464) at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:631) at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:588) at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:645) at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:508) at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:449) at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:133) at javax.servlet.GenericServlet.init(GenericServlet.java:160) at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1266) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1185) at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1080) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5027) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5314) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3920) at org.apache.catalina.loader.WebappLoader.backgroundProcess(WebappLoader.java:426) at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1345) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1530) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1540) at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1519) at java.lang.Thread.run(Unknown Source)

Minhas tabelas no MySQL:

cliente

id_cliente int not null pk
nome_cliente varchar

produto

id_produto int not null pk
descricao_produto varchar

pedido

id_pedido int not null pk
id_cliente fk (tabela cliente)

pedido_produto

id_pedido fk (tabela pedido)
id_produto fk (tabela produto)

Nesse caso, pra poder buscar uma lista dos pedidos de um cliente x, eu precisaria ter um método na minha classe clienteDAO, buscando por id do cliente. Mas eu queria que buscasse de outra forma, a partir do carregamento do usuário, já viesse a lista de pedidos dele carregada do bd automaticamente.

Vc mapeou invertido a relação pedido e cliente;
é

@ManyToOne @JoinColumn(name = "id_cliente") private Cliente cliente;
em Pedido;

e

@OneToMany (mappedBy = "cliente") //Sem join Column private List<Pedido> pedidos;

Porque vc tem a relação 1 cliente tem vários pedidos, certo?
E também vc tem a relação bidirecional, onde o cliente sabe todos os seus pedidos, e o pedido sabe quem é seu cliente; Por isso o mappedBy, ele informa que este relacionamento é bidirecional e quem vai ser o owner da relação;

TJvargas, muito obrigado, o erro era esse mesmo!

Mas agora ficou outra dúvida: tô tentando carregar a lista de pedidos de um cliente, pra isso, meu DAO está assim:

@Override public Cliente buscarPorNome(String nome) { Criteria criteria = session.createCriteria(Cliente.class); criteria.add(Restrictions.eq("nome_cliente", nome)); return (Cliente)criteria.setFirstResult(0); }

E meu Controller:

[code]@RequestMapping(value = “lista-pedidos”)
public void listarPedidos(HttpServletRequest request, Model model) {

	Session session = (Session)request.getAttribute("session");
	ClienteDAO clienteDAO = factory.getClienteDAO(session);
	
	List<Pedido> pedidos = clienteDAO.buscarPorNome("CLIENTE 1").getPedidos();
	
	for (Pedido pedido : pedidos) {
		System.out.println(pedido.getId());
	}
	
}[/code]

O erro da vez é que não posso dar cast pra Cliente a partir de um Criteria. Como eu faço pra retornar um objeto com criteria (nesse caso, o cliente, para pegar a lista de pedidos dele)?

Muito obrigado novamente, abraços.

Evita de usar Criteria, principalmente nesta fase sua de aprendizado;
Faz assim e testa;

    public Cliente buscarPorNome(String nome) {  
        Query query = session.createQuery("select c from cliente c where c.nome = :nome");  
        query.setParameter("nome", nome);

        return (Cliente)query.uniqueResult();  //Aqui depois vc precisa tomar alguns cuidados
    }  

Lembrando que é bom evitar este tipo de consulta para resultado único baseada em nome, é melhor e mais rápido pelo id; por nome seria mais ideal quando for uma pesquisa;
no caso ficaria melhor:

public Cliente findById(Integer id){ 
    Cliente cliente = session.get(Cliente.class, id);
    return cliente;
}

Olá TJVargas, muito obrigado novamente.

Então, eu entendo que devo ir um passo de cada vez pra me aprofundar em hibernate, mas preciso aprender o máximo possível nas duas próximas semanas.

Com Query eu já havia feito, e funfou legal.

Usando Criteria, tive que fazer o seguinte:

@Override public Cliente buscarPorNome(String nome) { Criteria criteria = session.createCriteria(Cliente.class); criteria.add(Restrictions.eq("nome", nome)); List<Cliente> clientes = criteria.list(); return clientes.get(0); }

Mas como tô retornando uma lista, e pegando o primeiro índice dela, ficou um código muito feio. O que eu poderia fazer para melhorar isso?

Outra dúvida é: na classe ClienteDAO, vou ficar com o seguinte método:

@Override public Cliente buscarPorNome(String nome) { Criteria criteria = session.createCriteria(Cliente.class); criteria.add(Restrictions.eq("nome", nome)); List<Cliente> clientes = criteria.list(); return clientes.get(0); }

Que seria responsável por retornar um cliente por nome, mas também, por retornar os pedidos do cliente. É uma boa prática essa, você recomendaria o uso deste método para retornar a lista de pedidos do usuário no controller, ou faço um outro método - na mesma classe, ou na classe PedidoDAO?

Muito obrigado desde já, abraços.

[quote]Lembrando que é bom evitar este tipo de consulta para resultado único baseada em nome, é melhor e mais rápido pelo id; por nome seria mais ideal quando for uma pesquisa;
no caso ficaria melhor: [/quote]

Sim sim, este é apenas um pequeno exemplo que imaginei pra começar a pôr em prática o que li essa semana.

Muito obrigado amigo, abraços.

Personas,

Tô tentando agora com relacionamento unidirecional entre cliente -> pedido e pedido -> produto, seguem minhas classes:

[code]package models;

import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

@Entity
public class Cliente {

@Id
@GeneratedValue
@Column(name="id_cliente")
private Long id;
@Column(name="nome_cliente")
private String nome;
@OneToMany
@JoinTable(name = "pedido", joinColumns = @JoinColumn(name = "id_cliente"), inverseJoinColumns = @JoinColumn(name= "id_pedido"))
private List<Pedido> pedidos;

public Cliente() {
	
}

public Cliente(Long id, String nome, List<Pedido> pedidos) {
	this.id = id;
	this.nome = nome;
	this.pedidos = pedidos; 
}
public Long getId() {
	return id;
}
public void setId(Long id) {
	this.id = id;
}
public String getNome() {
	return nome;
}
public void setNome(String nome) {
	this.nome = nome;
}
public List<Pedido> getPedidos() {
	return pedidos;
}
public void setPedidos(List<Pedido> pedidos) {
	this.pedidos = pedidos;
}

}[/code]

[code]package models;

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

@Entity
public class Produto {

@Id
@GeneratedValue
@Column(name="id_produto")
private Long id;
@Column(name="nome_produto")
private String nome;
@Column(name="descricao_produto")
private String descricao;
@Column(name="preco_produto")
private double preco;

public Produto(String nome, String descricao, double preco) {
	this.nome = nome;
	this.descricao = descricao;
	this.preco = preco;
}

public Produto() {
	
}

public Long getId() {
	return id;
}

public void setId(Long id) {
	this.id = id;
}

public String getNome() {
	return nome;
}

public void setNome(String nome) {
	this.nome = nome;
}

public String getDescricao() {
	return descricao;
}

public void setDescricao(String descricao) {
	this.descricao = descricao;
}

public double getPreco() {
	return preco;
}

public void setPreco(double preco) {
	this.preco = preco;
}

}[/code]

[code]package models;

import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

@Entity
public class Pedido {

@Id
@GeneratedValue
@Column(name="id_pedido")
private Long id;
@ManyToMany
@JoinTable(name = "pedido_produto", joinColumns = @JoinColumn(name = "id_pedido"), inverseJoinColumns = @JoinColumn(name= "id_produto"))
private List<Produto> produtos;

public Pedido() {

}

public Pedido(List<Produto> produtos) {
	this.produtos = produtos;
}

public Pedido(Long id, List<Produto> produtos) {
	super();
	this.id = id;
	this.produtos = produtos;
}

public Long getId() {
	return id;
}

public void setId(Long id) {
	this.id = id;
}

public List<Produto> getProdutos() {
	return produtos;
}

public void setProdutos(List<Produto> produtos) {
	this.produtos = produtos;
}

}[/code]

Tá tudo funcionando certinho agora, quando busco um cliente por nome no banco, já me vem a sua lista de pedidos, e dentro de cada linha da lista de pedidos, os produtos que estão neles.

Minha única dúvida é se não tô fazendo gambiarra. Essa é forma correta de relacionar estas 3 classes? Há algo a melhorar nesse relacionamento (quanto ao hibernate, apenas)?

Muito obrigado desde já. Abraços.

Relembrando:

Minhas tabelas no MySQL:

cliente

id_cliente int not null pk
nome_cliente varchar

produto

id_produto int not null pk
descricao_produto varchar

pedido

id_pedido int not null pk
id_cliente fk (tabela cliente)

pedido_produto

id_pedido fk (tabela pedido)
id_produto fk (tabela produto)

Se na sua busca por nome vc qr apenas um então utilize o uniqueResult() no lugar do list()

Mto obrigado!

Aproveitando a deixa, uma outra dúvida quanto ao mesmo assunto.

Na minha classe cliente tenho a lista de pedidos:

[code]@Entity
public class Cliente {

@Id
@GeneratedValue
@Column(name="id_cliente")
private Long id;
@Column(name="nome_cliente")
private String nome;
@OneToMany
@JoinTable(name = "pedido", joinColumns = @JoinColumn(name = "id_cliente"), inverseJoinColumns = @JoinColumn(name= "id_pedido"))
private List<Pedido> pedidos;

}[/code]

E na minha classe Pedido, preciso ter ao menos o id do cliente pra salvar na tabela pedido. Mas se fosse um sistema real, supondo que surgisse a necessidade de buscar um pedido por id também, vou precisar ter um objeto cliente em pedido para ter as informações completas de um cliente a partir do pedido. Até ai td bem. Mas e se não tivesse essa necessidade de buscar um pedido por id, e saber todos os dados do cliente, eu poderia deixar a classe Pedido apenas com o id do cliente? Segue abaixo exemplo

[code]@Entity
public class Pedido {

@Id
@GeneratedValue
@Column(name="id_pedido")
private Long id;
    private Long idCliente; // em vez de private Cliente cliente;
@OneToMany
@JoinTable(name = "pedido_produto", joinColumns = @JoinColumn(name = "id_pedido"), inverseJoinColumns = @JoinColumn(name= "id_produto"))
private List<Produto> produtos;

}[/code]

Seria má prática de programação isso? Muito obrigado desde já, abraços.

Cara, eu não entendi muito bem oq vc disse.

Mas o relacionamento seria assim:

@Entity
public class Cliente {

	@Id
	@GeneratedValue
	@Column(name="id_cliente")
	private Long id;

	@Column(name="nome_cliente")
	private String nome;

	@OneToMany(mappedBy = "cliente")
	private List<Pedido> pedidos;
}
@Entity
public class Pedido {
	
	@Id
	@GeneratedValue
	@Column(name="id_pedido")
	private Long id;

        @ManyToOne
	@JoinColumn( name = "id_cliente")
	private Cliente cliente;

}

Bom dia fdiaz2011,

Então, essa parte já saquei como funciona, a dúvida ficou quanto a teoria mesmo.

Vou tentar explicar por partes, acho que atropelei muita coisa no post anterior:

Esse relacionamento entre Pedido e Cliente, onde eu tenho um objeto Cliente dentro da classe pedido, funciona pro seguinte: inserir o id do cliente na tabela pedido, e retornar os detalhes do cliente caso eu busque um pedido pelo seu id, correto? Essa busca pelo id do pedido, eu precisaria mostrar na view os dados do cliente, então eu usaria expression language como seguinte: pedido.cliente.id, pedido.cliente.nome, etc.

Porém, caso eu não precisasse desta busca pelo id do pedido, eu só precisaria do id do cliente pra inserção no banco. Nisso eu poderia deixar a classe pedido sem o objeto cliente, apenas com o id do cliente no lugar dele:

[code]@Entity
public class Pedido {

@Id  
@GeneratedValue  
@Column(name="id_pedido")  
private Long id;  
    private Long idCliente; // em vez de private Cliente cliente;  
@OneToMany  
@JoinTable(name = "pedido_produto", joinColumns = @JoinColumn(name = "id_pedido"), inverseJoinColumns = @JoinColumn(name= "id_produto"))  
private List<Produto> produtos;  

} [/code]

A dúvida é: nesse caso, como cobriria minha necessidade, estaria mal modelada essa classe (trocar o objeto Cliente pelo Long idCliente)? Isso é gambiarra, ou uma má prática de programação na Orientação a Objetos ou a correta forma de utilizar hibernate? Eu não sou nenhum expert em OO (longe disso, tenho muito o que aprender ainda), mas não me parece nenhuma gambiarra deixar a classe Pedido como está logo acima do ponto de vista de Orientação a Objetos - nesse caso específico, em que só preciso da classe Pedido para persistir - salvar no banco - sem nenhuma consulta.

Caso eu tenha me perdido na explicação novamente, é só informar o que não expliquei bem.

Um grande abraço e novamente muito obrigado pela ajuda.

Entendi. Não faço assim, mas você pode sim fazer isso caso queira, mas vc perderia alguns benefícios.
Como por exemplo o citado por vc.

pedido.cliente.nome

Caso vc tenha uma lista de pedidos a ser listado em uma tabela e precise saber quais os dados do cliente de cada pedido, como fará ?
Terá q fazer uma nova busca na tabela de Cliente para cada pedido passando o idCliente e mesmo assim não estaria associado a um pedido.
Ou seja, vc teria q arrumar alguma forma de “amarrar” para para cada pedido um cliente.

Tens razão. Caso fosse um sistema real - e não um exemplo para estudos - não seria bom caso surgisse uma necessidade futura de mostrar os dados do cliente buscando por id do pedido.

Muito obrigado pela ajuda amigo, abraços.