Escrevi com sucesso meu primeiro exemplo de filho mestre com hibernação. Depois de alguns dias, peguei novamente e atualizei algumas bibliotecas. Não tenho certeza do que eu fiz, mas eu nunca poderia fazê-lo funcionar novamente. Alguém poderia me ajudar a descobrir o que há de errado no código que está retornando a seguinte mensagem de erro:
org.hibernate.PersistentObjectException: detached entity passed to persist: example.forms.InvoiceItem
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:127)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:799)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:791)
.... (truncated)
mapeamento de hibernação:
<hibernate-mapping package="example.forms">
<class name="Invoice" table="Invoices">
<id name="id" type="long">
<generator class="native" />
</id>
<property name="invDate" type="timestamp" />
<property name="customerId" type="int" />
<set cascade="all" inverse="true" lazy="true" name="items" order-by="id">
<key column="invoiceId" />
<one-to-many class="InvoiceItem" />
</set>
</class>
<class name="InvoiceItem" table="InvoiceItems">
<id column="id" name="itemId" type="long">
<generator class="native" />
</id>
<property name="productId" type="long" />
<property name="packname" type="string" />
<property name="quantity" type="int" />
<property name="price" type="double" />
<many-to-one class="example.forms.Invoice" column="invoiceId" name="invoice" not-null="true" />
</class>
</hibernate-mapping>
EDIT: InvoiceManager.java
class InvoiceManager {
public Long save(Invoice theInvoice) throws RemoteException {
Session session = HbmUtils.getSessionFactory().getCurrentSession();
Transaction tx = null;
Long id = null;
try {
tx = session.beginTransaction();
session.persist(theInvoice);
tx.commit();
id = theInvoice.getId();
} catch (RuntimeException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
throw new RemoteException("Invoice could not be saved");
} finally {
if (session.isOpen())
session.close();
}
return id;
}
public Invoice getInvoice(Long cid) throws RemoteException {
Session session = HbmUtils.getSessionFactory().getCurrentSession();
Transaction tx = null;
Invoice theInvoice = null;
try {
tx = session.beginTransaction();
Query q = session
.createQuery(
"from Invoice as invoice " +
"left join fetch invoice.items as invoiceItems " +
"where invoice.id = :id ")
.setReadOnly(true);
q.setParameter("id", cid);
theInvoice = (Invoice) q.uniqueResult();
tx.commit();
} catch (RuntimeException e) {
tx.rollback();
} finally {
if (session.isOpen())
session.close();
}
return theInvoice;
}
}
Invoice.java
public class Invoice implements java.io.Serializable {
private Long id;
private Date invDate;
private int customerId;
private Set<InvoiceItem> items;
public Long getId() {
return id;
}
public Date getInvDate() {
return invDate;
}
public int getCustomerId() {
return customerId;
}
public Set<InvoiceItem> getItems() {
return items;
}
void setId(Long id) {
this.id = id;
}
void setInvDate(Date invDate) {
this.invDate = invDate;
}
void setCustomerId(int customerId) {
this.customerId = customerId;
}
void setItems(Set<InvoiceItem> items) {
this.items = items;
}
}
InvoiceItem.java
public class InvoiceItem implements java.io.Serializable {
private Long itemId;
private long productId;
private String packname;
private int quantity;
private double price;
private Invoice invoice;
public Long getItemId() {
return itemId;
}
public long getProductId() {
return productId;
}
public String getPackname() {
return packname;
}
public int getQuantity() {
return quantity;
}
public double getPrice() {
return price;
}
public Invoice getInvoice() {
return invoice;
}
void setItemId(Long itemId) {
this.itemId = itemId;
}
void setProductId(long productId) {
this.productId = productId;
}
void setPackname(String packname) {
this.packname = packname;
}
void setQuantity(int quantity) {
this.quantity = quantity;
}
void setPrice(double price) {
this.price = price;
}
void setInvoice(Invoice invoice) {
this.invoice = invoice;
}
}
EDITAR: objeto JSON enviado do cliente:
{"id":null,"customerId":3,"invDate":"2005-06-07T04:00:00.000Z","items":[
{"itemId":1,"productId":1,"quantity":10,"price":100},
{"itemId":2,"productId":2,"quantity":20,"price":200},
{"itemId":3,"productId":3,"quantity":30,"price":300}]}
EDITAR: Alguns detalhes:
tentei salvar a fatura de duas maneiras:
O objeto json mencionado acima foi fabricado manualmente e o passou para uma nova sessão do servidor. Neste caso, absolutamente nenhuma atividade foi realizada antes de chamar o método save, portanto, não deve haver nenhuma sessão aberta exceto aquela aberta no método save
Dados existentes carregados usando o método getInvoice e eles transmitiram os mesmos dados após remover o valor da chave. Também acredito que deve fechar a sessão antes de salvar, pois a transação está sendo confirmada no método getInvoice.
Em ambos os casos, estou recebendo a mesma mensagem de erro que está me forçando a acreditar que algo está errado com o arquivo de configuração de hibernação ou classes de entidade ou método de salvamento.
Informe-me se devo fornecer mais detalhes
Invoice
primeiro, para obter o id e depois salvarInvoiceItem
. Você também pode jogar em cascata.Aqui você usou valor nativo e atribuindo valor à chave primária, em que a chave primária nativa é gerada automaticamente.
Portanto, o problema está chegando.
fonte
Isso existe na relação @ManyToOne. Resolvi esse problema usando apenas CascadeType.MERGE em vez de CascadeType.PERSIST ou CascadeType.ALL. Espero que ajude você.
@ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name="updated_by", referencedColumnName = "id") private Admin admin;
Solução:
@ManyToOne(cascade = CascadeType.MERGE) @JoinColumn(name="updated_by", referencedColumnName = "id") private Admin admin;
fonte
Provavelmente, o problema está fora do código que você está mostrando aqui. Você está tentando atualizar um objeto que não está associado à sessão atual. Se não é a Fatura, então talvez seja um InvoiceItem que já foi persistido, obtido do banco de dados, mantido ativo em algum tipo de sessão e então você tenta persistir em uma nova sessão. Isso não é possível. Como regra geral, nunca mantenha seus objetos persistentes ativos nas sessões.
A solução será obter todo o gráfico do objeto da mesma sessão com a qual você está tentando persistir. Em um ambiente da web, isso significaria:
Se você continuar tendo problemas, poste alguns dos códigos que estão chamando seu serviço.
fonte
Duas soluções 1. use merge se quiser atualizar o objeto 2. use save se quiser apenas salvar o novo objeto (certifique-se de que a identidade seja nula para permitir que o hibernate ou o banco de dados o gere) 3. se você estiver usando um mapeamento como
@OneToOne ( fetch = FetchType.EAGER, cascade = CascadeType.ALL) @JoinColumn (name = "stock_id")
Em seguida, use CascadeType.ALL para CascadeType.MERGE
obrigado Shahid Abbasi
fonte
Para JPA corrigido usando EntityManager merge () em vez de persist ()
EntityManager em = getEntityManager(); try { em.getTransaction().begin(); em.merge(fieldValue); em.getTransaction().commit(); } catch (Exception e) { //do smthng } finally { em.close(); }
fonte
Eu tive o "mesmo" problema porque estava escrevendo
@GeneratedValue(strategy = GenerationType.IDENTITY)
Excluí essa linha por não precisar dela no momento, estava testando com objetos e tal. Eu acho que é
<generator class="native" />
no seu casoNão tenho nenhum controlador e minha API não está sendo acessada, é apenas para teste (no momento).
fonte