Como persistir ManyToOne?

Bem galera sou iniciante em hibernate/JPA então não saco de muitas coisas… estou montando um sisteminha de vendas como exemplo. Nele eu tenho duas entidadaes que se relacionam. Item e Venda.

Codigo Entidade Item:

@Entity(name = "tb_item")
@Table(name= "tb_item")
public class Item implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String nome;

    private double preco;
    
    @ManyToOne
    private Venda vendas;

//Gets and Sets

Entidade Venda:

@Entity(name= "tb_venda")
@Table(name = "tb_venda")
public class Venda implements Serializable {
	private static final long serialVersionUID = 1L;
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	@Temporal(javax.persistence.TemporalType.DATE)
	private Date dataVenda;

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private Vendedor vendedor;

	@OneToMany(mappedBy = "vendas")
	private List<Item> itens;
	
	private double total;
//Gets and Sets

E aqui a “Action” para persistir a venda:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("MarketjpaPU");
        
        EntityManager em= emf.createEntityManager();
        
        em.getTransaction().begin();
        
        Venda venda = new Venda();
        
        List<Cliente> clientes = new ArrayList<Cliente>();
        
        clientes = (List<Cliente>) em.createQuery("SELECT e FROM tb_cliente e").getResultList();
        
        List<Vendedor> vendedores = new ArrayList<Vendedor>();
        
        vendedores = (List<Vendedor>) em.createQuery("SELECT e FROM tb_vendedor e").getResultList();
        
       //Setando o cliente na venda (meio tosco mas eu n sei usar o find, acho q ele devia servir tbm)
        for(Cliente clienteAtual : clientes){
            if(cadastroItensGUI.getOpcoesCliente().getSelectedItem().toString().equals(clienteAtual.getNome())){
                venda.setCliente(clienteAtual);
            }
        }
        
        for(Vendedor vendedorAtual : vendedores){
            if(cadastroItensGUI.getOpcoesVendendor().getSelectedItem().toString().equals(vendedorAtual.getNome())){
                venda.setVendedor(vendedorAtual);
            }
        }
        
     //Aqui eu retorno os itens cadastrados na janela swing e seto no meu objeto venda
       venda.setItens(cadastroItensGUI.getItensVenda());
       
       DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
        
        Date data = null;
        
        data = (Date) format.parse(cadastroItensGUI.getCampoVenda().getText());
        
        venda.setDataVenda(data);
        
        venda.setTotal(Double.parseDouble(cadastroItensGUI.getTotalVenda().getText()));
        
        em.persist(venda);
        
        em.getTransaction().commit();
        
        em.close();
     }

As inserções estão sendo feitas de forma manual no banco de dados. (Cliente, Item, Vendedor)

Eu penso que ao salvar a venda eu iria inserir itens na tabela de itens (tb_item) com uma referencia para a venda… assim eu poderia fazer um relatório de quais itens foram comprados em determinada venda.

Bem acontece que ao salvar a venda… não são inseridos itens na tabela de itens com suas respectivas FK’s de Venda… mas a venda é inserida com sucesso. Não sei se esse relacionamento não é a forma correta talvez eu esteja pensando errado :frowning:

cara,

da uma olhada num teste que eu postei nesse link tem um exemplo que vai te ajudar.

t+

E ai Lord, beleza?

Cara espero que minhas dicas possam lhe ajudar.

Vou fazer algumas observações para começar,

if(cadastroItensGUI.getOpcoesCliente().getSelectedItem()

Nesta linha acima vc está fazendo um for para pegar o cliente atual certo, mas o getSelectedItem já não lhe retorno o objeto do clienteAtual ??, exemplo

Cliente clienteAtual = (Cliente) cadastroItensGUI.getOpcoesCliente().getSelectedItem();

O mesmo serve para o vendedor. :wink:

Talvez o motivo que os itens não são setados para a venda é que vc ainda não os setou qdo pegou da tela :wink:

faça um for neles e seta a venda primeiro :wink:

cadastroItensGUI.getItensVenda()
for .....
 itemVenda.setVenda(venda);

depois é só persistir

entendeu?

espero que ajude,

abs,

Evandro

Eu adicionei o seguinte trecho de código…

List<Item> itens = cadastroItensGUI.getItensVenda();
      
      for(Item i : itens){
    	  i.setVendas(venda);
      }

Depois setei a lista de itens na venda e tentei persistir:

venda.setItens(itens);
em.persist(venda);

E mesmo assim nada é adicionado na tabela tb_item. (nela só há os itens iniciais já inseridos manualmente)

Sobre pegar o objeto direto com o getSelectdItem, tipo a lista só no combobox é uma lista de String e não de objetos ai não da pra fazer como vc postou (mas cou arrumar isso… fica até mais elegante/com melhor performance.

cara,

so vc ver o link q passei acima, que tem um exemplo para te ajudar.

t+

Você precisa informar o atributo cascade, para habilitar a persistência transitiva:

@OneToMany(mappedBy = "vendas" , cascade={CascadeType.PERSIST, CascadeType.MERGE })  
private List<Item> itens;

Além do mais, o ideal é você encapsular sua lista de itens:

class Venda{
   private List<Item> itens = new ArrayList<Item>();

   public void addItem(Item item){
       itens.add(item);
       item.setVenda(this);
   }
   
    public void addAllItens(Collection<Item> itensCol){
        for(Item item : itensCol){
           this.addItem(item);
        }
   }

   public List<Item> getItens(){
        return Collections.unmodifiableList(itens);
   }
}

Isso é necessário, pois ao recuperar seu objeto do banco, o Hibernate substitui o seu ArrayList por uma implementação de List própria do framework. Se você manipular a referência diretamente, você perde essa List. Assim, o ideal é manter o encapsulamento da lista, e ir expondo os métodos de manipulação da lista conforme necessário.