[Resolvido] Dúvida inserção de registro com classe relacionada em hibernate JPA

9 respostas
Z

Senhores,

Estou com uma dúvida conceitual e gostaria de saber se alguém poderia me ajudar.
O problema é o seguinte, tenho duas classes relacionadas entre si:
Pedido e ItemPedido

Dentro da classe Pedido fiz o seguinte relacionamento:

@OneToMany @JoinColumn(name = "idItemPedido") private List<ItemPedido> itensPedido;
E dentro da classe ItemPedido tenho o seguinte relacionamento:

@ManyToOne @JoinColumn(name ="idPedido") private Pedido idPedido;
Montei um objeto pedido informando todos os atributos, inclusive os itens.
No momento em que fiz isso, o atributo IdPedido da classe ItemPedido ficou zerado, pois como não inseri o Pedido ainda no banco eu não tenho seu ID.

Minha dúvida é justamente essa, como faço para referenciar o ID do pedido que nem foi armazenado ainda no banco na classe ItemPedido?
Pelo o que eu andei lendo o hibernate atribuiria automaticamente essa informação, por se tratar de um atributo que indica o relacionamento entre as classes, mas ao tentar executar o método de inserção aqui ele gerou um erro.

Agradeço desde já por qualquer ajuda!

9 Respostas

H

Você sabe o impacto que tem em mapear os dois lados com JoinColumn? E um lado sem o mappedBy?

Leia aqui: JPA: Mini Livro - Primeiros passos e conceitos detalhados

Z

Olá amigo!
Obrigado pela resposta!

Comecei a ler aqui e vi que já cometi erros grosseiros no relacionamento. Vou arrumar aqui e qualquer coisa volto a perguntar.
Novamente, obrigado pela atenção!

Z

Amigo,

Li seu artigo e fiz as correções aqui.
Agora meu relacionamento ficou da seguinte forma:

ItemPedido
@ManyToOne
@JoinColumn(name = "idPedido")
private Pedido pedido;
Pedido
@OneToMany(mappedBy = "pedido")
private List<ItemPedido> itensPedido;
Na hora de instanciar a classe fiz como você disse, setei todos os atributos do pedido e depois setei o atributo itensPedido com um ArrayList que montei. Maravilha, gerou o objeto certinho, mas quando executei o comando save (para a classe pedido) o sistema armazenou só o registro na tabela Pedido.

O certo não seria ele armazenar o registro na tabela ItemPedido também? Já que existe um relacionamento entre elas.
No console ele não gerou nenhum erro.

Método de Inserção
@POST
	@Path("/inserir")
	@Consumes("application/json")
	public void createPedido(String stringJson) {
		try {
			ArrayList<ItemPedido> listaItemPedido = new ArrayList();

			JSONObject json = new JSONObject(stringJson);
			JSONArray pedidoProduto = json.getJSONArray("pedidoProduto");

			dispositivoDAO.beginTransaction();
			dispositivo = dispositivoDAO.find(json.getInt("idDispositivo"));
			dispositivoDAO.closeTransaction();

			formaPagamentoDAO.beginTransaction();
			this.formaPagamento = formaPagamentoDAO.find(json
					.getInt("idFormaPagamento"));
			formaPagamentoDAO.closeTransaction();

			getPedido().setFormaPagamento(formaPagamento);
			getPedido().setDispositivo(dispositivo);
			getPedido().setTotal(json.getDouble("total"));
			Date data = new Date();
			getPedido().setDataPedido(new java.sql.Date(data.getTime()));

			for (int i = 0; i < pedidoProduto.length(); i++) {
				JSONObject j = pedidoProduto.getJSONObject(i);

				produtoDAO.beginTransaction();
				produto = produtoDAO.find(j.getInt("idProduto"));
				produtoDAO.closeTransaction();

				itemPedido.setValor(j.getDouble("valor"));
				itemPedido.setQuantidade(j.getInt("quantidade"));
				itemPedido.setIdProduto(this.produto);
				itemPedido.setPedido(pedido);
				
				listaItemPedido.add(itemPedido);
			}

			pedido.setItensPedido(listaItemPedido);
		} catch (Exception e) {
			e.printStackTrace();
		}

		pedidoDAO.beginTransaction();
		pedidoDAO.save(this.pedido);
		pedidoDAO.commitAndCloseTransaction();
	}
Agradeço desde já pela ajuda!
Z
Fiz uma modificação no método de inserção. Logo abaixo da rotina que armazena o pedido eu adicionei:
itemPedidoDAO.beginTransaction();
itemPedidoDAO.save(itemPedido);
itemPedidoDAO.commitAndCloseTransaction();
Quando o sistema foi tentar persistir os dados do ItemPedido recebi o seguinte erro. Minha classe ItemPedido está mapeada da seguinte forma:
@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int idItemPedido;

	@ManyToOne
	@JoinColumn(name = "idPedido")
	private Pedido pedido;

	@OneToOne
	@JoinColumn(name = "idProduto")
	private Produto idProduto;

	@Column(nullable = false)
	private int quantidade;

	@Column(nullable = false)
	private double valor;

	@Column(nullable = true)
	private String observacao;
Enquanto minha classe pedido está mapeada da seguinte forma:
@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int idPedido;

	@OneToOne
	@JoinColumn(name = "idDisposistivo")
	private Dispositivo idDispositivo;

	@OneToOne
	@JoinColumn(name = "idFormaPagamento")
	private FormaPagamento idFormaPagamento;

	@Temporal(TemporalType.TIMESTAMP)
	private Date dataPedido;

	@Column(nullable = false)
	private double total;

	@OneToMany(mappedBy = "pedido")
	private List<ItemPedido> itensPedido;

Alguém saberia me dizer onde estou falhando?
Agradeço desde já por qualquer ajuda!

D

Amigo, ja tentou usar o Cascade?

@OneToMany  
@JoinColumn(name = "idItemPedido", cascade=CascadeType.ALL)  
private List<ItemPedido> itensPedido;
Z

Olá!

Realmente, com essa sua dica funcionou, no caso esse atributo que você me informou tem qual finalidade?

Outra coisa, não sei se estou fazendo algo na hora de gerar a lista de produtos, mas se tento armazenar dois produtos não consigo, ele armazena só um. Dei um debug no código e percebi que quando o sistema passa a segunda vez pela codificação:
for (int i = 0; i < pedidoProduto.length(); i++) {
				JSONObject j = pedidoProduto.getJSONObject(i);

				produtoDAO.beginTransaction();
				produto = produtoDAO.find(j.getInt("idProduto"));
				produtoDAO.closeTransaction();

				itemPedido.setValor(j.getDouble("valor"));
				itemPedido.setQuantidade(j.getInt("quantidade"));
				itemPedido.setIdProduto(this.produto);
				itemPedido.setPedido(pedido);
				
				listaItemPedido.add(itemPedido);
			}
Ele sobrescreve o valor do primeiro item. Fazendo com que fique dois espaços no ArrayList com o mesmo produto. Por exemplo, vamos dizer que passei o Produto A e o Produto B. Quando passo a primeira vez na codificação, instancio todas as informações do produto A. Ai quando vou passar a segunda vez, para atribuir os atributos do Produto B e incluir no Array ele armazena os valores corretamente só que altera as informações do Produto A, fazendo com que fique dois registros do Produto B no Array.

Saberia me dizer onde estou falhando??
E novamente, muito obrigado pela dica!

Z

Relaxa amigo, era começão de toca minha :lol: :lol:
Tinha colocado a instancia do objeto fora do for, ai fica difícil funcionar mesmo

Só ficou a questão do cascade que não entendi o porque usar ele.
Se você pudesse me explicar isso, ficaria agradecido

D

Opa amigo, no blog do Hebert Coelho http://uaihebert.com/?p=1622&page=23 (que é excelentíssimo por sinal) e que ele postou acima, você encontra explicação detalhada sobre o cascade.

Z

Realmente, não me atentei ao fato de ter a informação no conteúdo que ele já havia apresentado.
Li apenas a parte que eu julgava ser necessário e deixei passar a que realmente fazia relevância ao meu problemas.

Agora vou aproveitar o tempo e ler detalhadamente a informação!
Obrigado aos dois!!

Criado 20 de novembro de 2012
Ultima resposta 20 de nov. de 2012
Respostas 9
Participantes 3