Я успешно написал свой первый главный дочерний пример с помощью спящего режима. Через несколько дней я снова взял его и обновил некоторые библиотеки. Не знаю, что я сделал, но я больше никогда не смогу заставить его работать. Может ли кто-нибудь помочь мне выяснить, что не так в коде, который возвращает следующее сообщение об ошибке:
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)
отображение гибернации:
<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>
РЕДАКТИРОВАТЬ: 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;
}
}
РЕДАКТИРОВАТЬ: объект JSON, отправленный от клиента:
{"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}]}
РЕДАКТИРОВАТЬ: Некоторые детали:
я пытался сохранить счет двумя способами:
Вручную изготовил вышеупомянутый объект json и передал его новому сеансу сервера. В этом случае перед вызовом метода сохранения не было совершено никаких действий, поэтому не должно быть никаких открытых сеансов, кроме сеанса, открытого в методе сохранения.
Загружены существующие данные с помощью метода getInvoice, и они передали те же данные после удаления значения ключа. Я считаю, что это тоже должно закрыть сеанс перед сохранением, поскольку транзакция фиксируется в методе getInvoice.
В обоих случаях я получаю одно и то же сообщение об ошибке, которое заставляет меня полагать, что что-то не так с файлом конфигурации спящего режима, классами сущностей или методом сохранения.
Пожалуйста, дайте мне знать, если мне нужно предоставить более подробную информацию
Invoice
сначала сохраните , чтобы он получил идентификатор, а затем сохранитеInvoiceItem
. Вы также можете поиграть с каскадом.Здесь вы использовали собственный и присвоили значение первичному ключу, в собственном первичный ключ создается автоматически.
Отсюда возникает проблема.
источник
Это существует в отношении @ManyToOne. Я решил эту проблему, просто используя CascadeType.MERGE вместо CascadeType.PERSIST или CascadeType.ALL. Надеюсь, это поможет тебе.
@ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name="updated_by", referencedColumnName = "id") private Admin admin;
Решение:
@ManyToOne(cascade = CascadeType.MERGE) @JoinColumn(name="updated_by", referencedColumnName = "id") private Admin admin;
источник
Скорее всего, проблема заключается вне кода, который вы нам здесь показываете. Вы пытаетесь обновить объект, не связанный с текущим сеансом. Если это не Invoice, то, возможно, это InvoiceItem, который уже был сохранен, получен из базы данных, сохранен в каком-то сеансе, а затем вы пытаетесь сохранить его в новом сеансе. Это невозможно. Как правило, никогда не поддерживайте постоянные объекты в рабочем состоянии между сеансами.
Решение будет, например, в получении всего графа объекта из того же сеанса, в котором вы пытаетесь его сохранить. В веб-среде это будет означать:
Если у вас по-прежнему возникают проблемы, опубликуйте код, который вызывает вашу службу.
источник
Два решения 1. используйте слияние, если вы хотите обновить объект 2. используйте сохранение, если вы хотите просто сохранить новый объект (убедитесь, что идентификатор равен нулю, чтобы спящий режим или база данных сгенерировали его) 3. если вы используете сопоставление, например
@OneToOne ( fetch = FetchType.EAGER, cascade = CascadeType.ALL) @JoinColumn (name = "stock_id")
Затем используйте CascadeType.ALL в CascadeType.MERGE
спасибо Шахид Аббаси
источник
Для JPA исправлено использование EntityManager merge () вместо persist ()
EntityManager em = getEntityManager(); try { em.getTransaction().begin(); em.merge(fieldValue); em.getTransaction().commit(); } catch (Exception e) { //do smthng } finally { em.close(); }
источник
У меня была такая же проблема, потому что я писал
@GeneratedValue(strategy = GenerationType.IDENTITY)
Я удалил эту строку из-за того, что в данный момент она мне не нужна, я тестировал с объектами и так далее. Я думаю, что это
<generator class="native" />
в твоем случаеУ меня нет контроллера, и мой API не используется, он предназначен только для тестирования (на данный момент).
источник