我用hibernate成功编写了我的第一个master child示例。几天后我再次拿起它并升级了一些图书馆。不知道我做了什么,但我再也不能让它再次运行。有人会帮我弄清楚在返回错误信息的代码中出现了什么问题:
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映射:
<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方法中提交。
在这两种情况下,我都收到相同的错误消息,迫使我认为hibernate配置文件或实体类或save方法有问题。
如果我需要提供更多详情,请与我们联系
答案 0 :(得分:99)
您没有提供许多相关详细信息,因此我猜您已调用getInvoice
,然后您使用结果对象设置了一些值并调用save
,并假设您的对象更改将被保存。
但是,persist
操作适用于全新的瞬态对象,如果已分配id,则操作失败。在您的情况下,您可能希望拨打saveOrUpdate
而不是persist
。
您可以在"detached entity passed to persist error" with JPA/EJB code
找到一些讨论和参考答案 1 :(得分:10)
这里您使用了本机并为主键分配值,本机主键是自动生成的。
因此问题即将来临。
答案 2 :(得分:3)
很可能问题出在您向我们展示的代码之外。您正在尝试更新与当前会话无关的对象。如果它不是Invoice,那么它可能是一个已经持久化的InvoiceItem,从db中获取,在某种会话中保持活动状态,然后您尝试将其保留在新会话中。这是不可能的。作为一般规则,永远不要让持久对象在会话中保持活动状态。
解决方案将是从您尝试持久化的同一会话中获取整个对象图。在网络环境中,这意味着:
如果您在发布一些调用您服务的代码时遇到问题。
答案 3 :(得分:1)
我在写作时遇到了“相同”的问题
@GeneratedValue(strategy = GenerationType.IDENTITY)
我删除了该行,因为目前不需要,我正在测试对象等。我认为您的情况是<generator class="native" />
我没有任何控制器,我的API尚未访问,仅用于测试(当前)。
答案 4 :(得分:0)
This exists in @ManyToOne relation.I solved this issue by just using CascadeType.MERGE instead of CascadeType.PERSIST or CascadeType.ALL. Hope it helps you.
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="updated_by", referencedColumnName = "id")
private Admin admin;
Solution:
@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name="updated_by", referencedColumnName = "id")
private Admin admin;
答案 5 :(得分:0)
对于使用EntityManager merge()而不是persist()修复的JPA
EntityManager em = getEntityManager();
try {
em.getTransaction().begin();
em.merge(fieldValue);
em.getTransaction().commit();
} catch (Exception e) {
//do smthng
} finally {
em.close();
}
答案 6 :(得分:0)
两种解决方案
1.如果要更新对象,请使用合并
2.如果只想保存新对象,请使用保存(确保标识为空以让休眠或数据库生成它)
3.如果您使用的是类似
的映射
@OneToOne(获取= FetchType.EAGER,级联= CascadeType.ALL)
@JoinColumn(name =“ stock_id”)
然后将CascadeType.ALL用作CascadeType.MERGE
谢谢 Shahid Abbasi
答案 7 :(得分:0)
分享我的经验,因为问题标题更通用。原因之一可能是 @GeneratedValue 用于唯一 id,但随后再次设置了 id。
示例
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "COURSE")
public class Course {
@Id
@GeneratedValue
private Long id;
private String name;
}
以下代码抛出异常:org.hibernate.PersistentObjectException: detached entity passed to persist:a.b.c.Course
因为在构造函数中设置了 Id。
Course course = new Course(10L, "testcourse");
testEntityManager.persist(course);
解决方案
避免设置 Id ,因为它是自动生成的(在实体类中指定)
Course course = new Course();
course.setName("testcourse");
testEntityManager.persist(course);