Boa noite, tudo bem? Eu tava "brincando de testar os codígos" e me veio um erro, acho que eu entendo o porque dele, mais não o motivo dele estar acontecendo! Ok vamos la, irei postar as minhas classes modelo.
@SuppressWarnings("serial")
@Entity
@NamedQueries({
@NamedQuery(name = "Produto.lista", query = "Select p from Produto p join fetch p.fornecedor"),
@NamedQuery(name = "Produto.fornecedores", query = "Select f from Fornecedor f")
})
public class Produto implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long codigo;
private String descricao;
private Integer quantidade;
private BigDecimal preco;
@ManyToOne
@JoinColumn(name = "fornecedor_codigo")
private Fornecedor fornecedor = new Fornecedor();
@OneToMany(mappedBy = "produto")
private List<Item> itens = new ArrayList<Item>();
@SuppressWarnings("serial")
@Entity
@NamedQueries({ @NamedQuery(name = "Venda.funcionarios", query = "Select f from Funcionario f")
})
public class Venda implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long codigo;
@Temporal(TemporalType.DATE)
private Calendar horario = Calendar.getInstance();
private BigDecimal valorTotal = BigDecimal.valueOf(0.0D);
@ManyToOne
@JoinColumn(name = "funcionario_codigo")
private Funcionario funcionario = new Funcionario();
@OneToMany(mappedBy = "venda")
private List<Item> itens = new ArrayList<Item>();
@SuppressWarnings("serial")
@Entity
public class Item implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long codigo;
private Integer quantidade;
private BigDecimal valorParcial;
@ManyToOne
@JoinColumn(name = "produto_codigo")
private Produto produto = new Produto();
@ManyToOne
@JoinColumn(name = "venda_codigo")
private Venda venda = new Venda();
Bom como podem ver minhas classes, tem outras mais oque está ocorrendo é o problema nessas aqui. Vou tentar explicar o erro, olhando no banco de dados, minha tabela item tem duas fk, uma de produto e uma de venda. Porem testando meus códigos que andei apreendendo aqui na alura, fiz a minha classe de vendaBean, ontem nessa classe eu faço a relação do produto e item e venda.
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
import br.com.bercalini.farmacia.anotacao.Transacional;
import br.com.bercalini.farmacia.dao.FuncionarioDao;
import br.com.bercalini.farmacia.dao.ItemDao;
import br.com.bercalini.farmacia.dao.VendaDao;
import br.com.bercalini.farmacia.modelo.Funcionario;
import br.com.bercalini.farmacia.modelo.Item;
import br.com.bercalini.farmacia.modelo.Produto;
import br.com.bercalini.farmacia.modelo.Venda;
import br.com.bercalini.farmacia.util.Mensagem;
@SuppressWarnings("serial")
@Named
@ViewScoped
public class VendaBean implements Serializable {
@Inject
private Venda venda;
@Inject
private VendaDao vendaDao;
@Inject
private Mensagem mensagem;
@Inject
private FuncionarioDao funcionarioDao;
@Inject
private Item item;
@Inject
private ItemDao itemDao;
private List<Item> itens = new ArrayList<Item>();
@Transacional
public void salvar() {
if (venda.getCodigo() == null) {
item.setVenda(venda);
vendaDao.salvar(venda);
itemDao.salvar(item);
mensagem.mensagem("VENDA SALVA COM SUCESSO");
} else {
}
this.venda = new Venda();
this.itens = new ArrayList<Item>();
}
public void adicionarVenda(Produto produto) {
int posicaoEncontrada = -1;
for (int posicao = 0; posicao < itens.size() && posicaoEncontrada < 0; posicao++) {
Item temporario = itens.get(posicao);
if (temporario.getProduto().getCodigo().equals(produto.getCodigo())) {
posicaoEncontrada = posicao;
}
}
Item item = new Item();
item.setProduto(produto);
if (posicaoEncontrada < 0) {
item.setQuantidade(1);
item.setValorParcial(produto.getPreco());
itens.add(item);
} else {
Item itemTemporario = itens.get(posicaoEncontrada);
item.setQuantidade(itemTemporario.getQuantidade() + 1);
item.setValorParcial(produto.getPreco().multiply(new BigDecimal(item.getQuantidade())));
itens.set(posicaoEncontrada, item);
}
venda.setValorTotal(venda.getValorTotal().add(produto.getPreco()));
}
public void remover(Item item) {
int posicaoEncontrada = -1;
for (int posicao = 0; posicao < itens.size() && posicaoEncontrada < 0; posicao++) {
Item temporario = itens.get(posicao);
if (temporario.getProduto().getCodigo().equals(item.getProduto().getCodigo())) {
posicaoEncontrada = posicao;
}
}
if(posicaoEncontrada > -1) {
itens.remove(posicaoEncontrada);
venda.setValorTotal(venda.getValorTotal().subtract(item.getValorParcial()));
}
}
public void carregarDadosVenda() {
venda.setHorario(venda.getHorario());
Funcionario funcionario = funcionarioDao.buscarPorCodigo(1L);
venda.setFuncionario(funcionario);
venda.setValorTotal(venda.getValorTotal());
}
public List<Funcionario> getListaFuncionarios() {
return vendaDao.listaFuncionario();
}
public List<Produto> getListaProdutos() {
return vendaDao.listaProduto();
}
public Venda getVenda() {
return venda;
}
public void setVenda(Venda venda) {
this.venda = venda;
}
public List<Item> getItens() {
return itens;
}
public void setItens(List<Item> itens) {
this.itens = itens;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public ItemDao getItemDao() {
return itemDao;
}
public void setItemDao(ItemDao itemDao) {
this.itemDao = itemDao;
}
}
Também irei postar o minha visão aqui.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/template/template.xhtml">
<ui:define name="conteudo">
<div class="ui-fluid">
<h:form id="formularioVendas">
<p:growl id="mensagem" showDetail="true" sticky="true" />
<p:dataTable id="tabelaProduto" paginator="true" rows="4"
value="#{vendaBean.listaProdutos}" var="produto"
emptyMessage="Nenhum produto encontrado">
<f:facet name="header">Venda</f:facet>
<p:column headerText="Nome">
<h:outputText value="#{produto.descricao}" />
</p:column>
<p:column headerText="Quantidade">
<h:outputText value="#{produto.quantidade}" />
</p:column>
<p:column headerText="Preço">
<h:outputText value="#{produto.preco}" />
</p:column>
<p:column headerText="Fornecedor">
<h:outputText value="#{produto.fornecedor.descricao}" />
</p:column>
<p:column headerText="Opção">
<p:panelGrid columns="2">
<p:commandButton icon="fa fa-fw fa-plus"
title="Adicionar produto"
action="#{vendaBean.adicionarVenda(produto)}"
update=":formularioVendas:tabelaItens :formularioVendas:valor " />
</p:panelGrid>
</p:column>
</p:dataTable>
<p:separator />
<p:dataTable id="tabelaItens" value="#{vendaBean.itens}" var="item"
paginator="true" rows="3" emptyMessage="Nenhum Item encontrado">
<p:column headerText="Produto">
<h:outputText value="#{item.produto.descricao}" />
</p:column>
<p:column headerText="Valor item">
<h:outputText value="#{item.valorParcial}" />
</p:column>
<p:column headerText="Quantidade">
<h:outputText value="#{item.quantidade}" />
</p:column>
<p:column headerText="Fornecedor">
<h:outputText value="#{item.produto.fornecedor.descricao}" />
</p:column>
<p:column headerText="Opção">
<p:commandButton icon="fa fa-fw fa-remove"
actionListener="#{vendaBean.remover(item)}"
update=":formularioVendas:tabelaItens :formularioVendas:pne"
title="Remover produto" />
</p:column>
</p:dataTable>
<h:panelGrid columns="3" id="pne">
<p:outputLabel value="Valor Total: " for="valor" />
<p:inputText id="valor" value="#{vendaBean.venda.valorTotal}"
readonly="true" size="11" />
<p:commandButton value="Finalizar venda"
actionListener="#{vendaBean.carregarDadosVenda}"
oncomplete="PF('finalizar').show();"
update=":formularioVendas :dialogo" />
</h:panelGrid>
</h:form>
<p:dialog appendTo="@(body)" header="Finalizar compra"
closable="true" draggable="true" modal="true" resizable="false"
widgetVar="finalizar" id="dialogo">
<h:form>
<h:panelGrid columns="2">
<p:outputLabel value="Data: " />
<p:inputText readonly="true"
value="#{vendaBean.venda.horario.time}">
<f:convertDateTime pattern="dd/MM/yyyy"
timeZone="America/Sao_Paulo" />
</p:inputText>
<p:outputLabel value="Funcionario: " />
<p:inputText readonly="true"
value="#{vendaBean.venda.funcionario.nome}" />
<p:outputLabel value="Valor total: " />
<p:inputText readonly="true" value="#{vendaBean.venda.valorTotal}" />
<p:commandButton value="Finalizar"
actionListener="#{vendaBean.salvar}" update="formularioVendas"
onclick="PF('finalizar').hide();" />
<p:commandButton value="Voltar" onclick="PF('finalizar').hide();" />
</h:panelGrid>
</h:form>
</p:dialog>
</div>
</ui:define>
</ui:composition>
</html>
no meu metodo salvar quando clico nele na minha visão o erro é que o produto esta transient.
Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing: br.com.bercalini.farmacia.modelo.Item.produto -> br.com.bercalini.farmacia.modelo.Produto
at org.hibernate.engine.spi.CascadingAction$8.noCascade(CascadingAction.java:380)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:176)
at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:160)
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:151)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
... 49 more
Mais eu não quero salvar o produto novamente! Fiz uma visão separada para adicionar um produto, e to mostrando os meus produtos no meu html de venda. Na hora de apertar o botão só queria salvar a minha venda, e com os meus itens dessa venda! Oque estou errando?