Hibernate JPA级联删除问题

发布于 2024-11-09 08:02:28 字数 4824 浏览 0 评论 0原文

为了解释我的问题,我创建了这个简单的项目,其中包含两个表:item 和 order1(其中 item 以 orderId 作为外键)。

现在,当我尝试从订单表中删除一行时,我收到错误消息,指出特定订单 id 与“item”表中的少数项目链接。

所以,我所做的是迭代所有项目对象(使用“急切”加载),并为每个对象调用 destroy() 。删除所有项目后,我调用 order.destroy()。 但现在,我收到以下错误:

Exception in thread "main" javax.persistence.RollbackException: Error while commiting the transaction
        at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71)
        at     com.sourind.test.testorm.controller.ItemJpaController.destroy(ItemJpaController.java:112)
        at com.sourind.test.testorm.App.main(App.java:31)
Caused by: org.hibernate.ObjectDeletedException: deleted entity passed to persist:     [com.sourind.test.testorm.entity.Item#<null>]

我正在使用 Hibernate(JPA 2.0 )。任何有关此事的帮助将不胜感激。

作为参考,我正在复制由 netbeans 创建的实体类:

@Entity
@Table(name = "item", catalog = "test", schema = "")
@NamedQueries({
@NamedQuery(name = "Item.findAll", query = "SELECT i FROM Item i"),
@NamedQuery(name = "Item.findById", query = "SELECT i FROM Item i WHERE i.id = :id"),
@NamedQuery(name = "Item.findByName", query = "SELECT i FROM Item i WHERE i.name = :name")})
public class Item implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @Column(name = "name")
    private String name;
    @JoinColumn(name = "orderId", referencedColumnName = "id")
    @ManyToOne(optional = false)
    private Order1 order1;

    public Item() {
    }

    public Item(Integer id) {
       this.id = id;
    }

public Item(Integer id, String name) {
    this.id = id;
    this.name = name;
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Order1 getOrder1() {
    return order1;
}

public void setOrder1(Order1 order1) {
    this.order1 = order1;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (id != null ? id.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof Item)) {
        return false;
    }
    Item other = (Item) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "com.sourind.test.testorm.entity.Item[id=" + id + "]";
}

}

和 order1 类:

@Entity
@Table(name = "order", catalog = "test", schema = "")
@NamedQueries({
    @NamedQuery(name = "Order1.findAll", query = "SELECT o FROM Order1 o"),
    @NamedQuery(name = "Order1.findById", query = "SELECT o FROM Order1 o WHERE o.id = :id"),
    @NamedQuery(name = "Order1.findByOrderDate", query = "SELECT o FROM Order1 o WHERE o.orderDate = :orderDate")})
public class Order1 implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @Column(name = "orderDate")
    @Temporal(TemporalType.TIMESTAMP)
private Date orderDate;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "order1", fetch=FetchType.EAGER)
private List<Item> itemList;

public Order1() {
}

public Order1(Integer id) {
    this.id = id;
}

public Order1(Integer id, Date orderDate) {
    this.id = id;
    this.orderDate = orderDate;
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public Date getOrderDate() {
    return orderDate;
}

public void setOrderDate(Date orderDate) {
    this.orderDate = orderDate;
}

public List<Item> getItemList() {
    return itemList;
}

public void setItemList(List<Item> itemList) {
    this.itemList = itemList;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (id != null ? id.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof Order1)) {
        return false;
    }
    Order1 other = (Order1) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "com.sourind.test.testorm.entity.Order1[id=" + id + "]";
}

}

提前致谢, 苏里

For explaning my issue, I have created this simple project with two tables : item and order1 (with item having orderId as Foreign Key).

Now when I try to delete a row from order table, i get error saying that particular order id is linked with few items in 'item' table.

So, what i do is i iterate over all the item objects (using 'Eager' loading) , and call destroy() for each of them. And after deleteing all the items , I call order.destroy().
But now, I get the following error:

Exception in thread "main" javax.persistence.RollbackException: Error while commiting the transaction
        at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71)
        at     com.sourind.test.testorm.controller.ItemJpaController.destroy(ItemJpaController.java:112)
        at com.sourind.test.testorm.App.main(App.java:31)
Caused by: org.hibernate.ObjectDeletedException: deleted entity passed to persist:     [com.sourind.test.testorm.entity.Item#<null>]

I am using Hibernate(JPA 2.0 ). Any help in this matter would be greatly appreciated.

For reference, I am copying the entity classes created by netbeans:

@Entity
@Table(name = "item", catalog = "test", schema = "")
@NamedQueries({
@NamedQuery(name = "Item.findAll", query = "SELECT i FROM Item i"),
@NamedQuery(name = "Item.findById", query = "SELECT i FROM Item i WHERE i.id = :id"),
@NamedQuery(name = "Item.findByName", query = "SELECT i FROM Item i WHERE i.name = :name")})
public class Item implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @Column(name = "name")
    private String name;
    @JoinColumn(name = "orderId", referencedColumnName = "id")
    @ManyToOne(optional = false)
    private Order1 order1;

    public Item() {
    }

    public Item(Integer id) {
       this.id = id;
    }

public Item(Integer id, String name) {
    this.id = id;
    this.name = name;
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Order1 getOrder1() {
    return order1;
}

public void setOrder1(Order1 order1) {
    this.order1 = order1;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (id != null ? id.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof Item)) {
        return false;
    }
    Item other = (Item) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "com.sourind.test.testorm.entity.Item[id=" + id + "]";
}

}

And the order1 class:

@Entity
@Table(name = "order", catalog = "test", schema = "")
@NamedQueries({
    @NamedQuery(name = "Order1.findAll", query = "SELECT o FROM Order1 o"),
    @NamedQuery(name = "Order1.findById", query = "SELECT o FROM Order1 o WHERE o.id = :id"),
    @NamedQuery(name = "Order1.findByOrderDate", query = "SELECT o FROM Order1 o WHERE o.orderDate = :orderDate")})
public class Order1 implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @Column(name = "orderDate")
    @Temporal(TemporalType.TIMESTAMP)
private Date orderDate;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "order1", fetch=FetchType.EAGER)
private List<Item> itemList;

public Order1() {
}

public Order1(Integer id) {
    this.id = id;
}

public Order1(Integer id, Date orderDate) {
    this.id = id;
    this.orderDate = orderDate;
}

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public Date getOrderDate() {
    return orderDate;
}

public void setOrderDate(Date orderDate) {
    this.orderDate = orderDate;
}

public List<Item> getItemList() {
    return itemList;
}

public void setItemList(List<Item> itemList) {
    this.itemList = itemList;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (id != null ? id.hashCode() : 0);
    return hash;
}

@Override
public boolean equals(Object object) {
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof Order1)) {
        return false;
    }
    Order1 other = (Order1) object;
    if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "com.sourind.test.testorm.entity.Order1[id=" + id + "]";
}

}

Thanks in advance,
Souri

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

差↓一点笑了 2024-11-16 08:02:28

@Alex这是 ItemJpaController#destroy() 的代码

public void destroy(Integer id) throws NonexistentEntityException {
    EntityManager em = null;
    try {
        em = getEntityManager();
        em.getTransaction().begin();
        Item item;
        try {
            item = em.getReference(Item.class, id);
            item.getId();
        } catch (EntityNotFoundException enfe) {
            throw new NonexistentEntityException("The item with id " + id + " no longer exists.", enfe);
        }
        Order1 order1 = item.getOrder1();
        if (order1 != null) {
            order1.getItemList().remove(item);
            order1 = em.merge(order1);
        }
        em.remove(item);
        em.getTransaction().commit();
    } finally {
        if (em != null) {
            em.close();
        }
    }
}

,而且,我使用的 hibernate 版本没有 DELETE_ORPHAN 级联类型。

另外,我如何获得会话?我应该在 destroy() 方法内的 JpaController 类中获取它,还是在我从中创建/删除对象的 mail 方法中获取它?

@Alex Here is the code for ItemJpaController#destroy()

public void destroy(Integer id) throws NonexistentEntityException {
    EntityManager em = null;
    try {
        em = getEntityManager();
        em.getTransaction().begin();
        Item item;
        try {
            item = em.getReference(Item.class, id);
            item.getId();
        } catch (EntityNotFoundException enfe) {
            throw new NonexistentEntityException("The item with id " + id + " no longer exists.", enfe);
        }
        Order1 order1 = item.getOrder1();
        if (order1 != null) {
            order1.getItemList().remove(item);
            order1 = em.merge(order1);
        }
        em.remove(item);
        em.getTransaction().commit();
    } finally {
        if (em != null) {
            em.close();
        }
    }
}

And also, the version of hibernate I am using did not have DELETE_ORPHAN cascade type.

Also, how do I get session? and should I get it in the JpaController class inside the destroy() method or in the mail method from which I am creating/deleting objects.?

£烟消云散 2024-11-16 08:02:28

您应该能够删除订单记录并让它删除所有关联的项目记录。为此,您需要向订单和项目之间的关联添加另一个级联类型。

@OneToMany(cascade=CascadeType.ALL, mappedBy = "order1", fetch=FetchType.EAGER, orphanRemoval=true)
private List<Item> itemList;

这告诉 hibernate 当您删除父 Order 时,它应该删除子 Item 记录。

session.delete(order);

此删除将向下级联到子项记录并将其删除。

You should just be able to delete the Order record and have it delete all of the associated Item records. To do this you need to add another cascade type to the association between the Order and the Items.

@OneToMany(cascade=CascadeType.ALL, mappedBy = "order1", fetch=FetchType.EAGER, orphanRemoval=true)
private List<Item> itemList;

This tells hibernate that when you delete the parent Order it should delete the child Item records.

session.delete(order);

This delete will cascade down to the child Item records and remove them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文