代码之家  ›  专栏  ›  技术社区  ›  Laurent K

休眠删除查询的顺序

  •  4
  • Laurent K  · 技术社区  · 15 年前

    这是我的数据模型(简化)

    public class AddressBook {
        private List<Group> groups = new ArrayList<Group>();
        private List<People> peoples = new ArrayList<People>();
    
        @OneToMany(mappedBy = "addressbook", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
        @OnDelete(action = OnDeleteAction.CASCADE)
        @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
        public List<Group> getGroups() {
            return groups;
        }
    
        @OneToMany(mappedBy = "addressbook", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
        @OnDelete(action = OnDeleteAction.CASCADE)
        @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
        public List<People> getPeoples() {
            return peoples;
        }
    }
    
    
    public class Group {
        private AddressBook addressBook;
    
    
        @ManyToOne(fetch = FetchType.LAZY, optional = false)
        public void setAddressBook(AddressBook addressBook) {
            this.addressBook = addressBook;
        }
    }
    
    public class People {
        private AddressBook addressBook;
        private Group group;
    
        @ManyToOne(fetch = FetchType.LAZY, optional = false)
        public AddressBook getAddressBook() {
            return addressBook;
        }
        public Group getGroup() {
            return group;
        }
    }
    

    我想从我的通讯簿中删除一个完整的组,以及属于该组的所有人。所以我做了如下的事情:

    adressBook.getPeople().removeAll(peopleBelongingToGroupA);
    adressBook.getGroups().remove(groupA);
    

    但是当我的事务被提交时,Hibernate会先执行以下操作:

    delete from groups where groupName='groupA';
    

    而不是先删除人员。这就违反了我在人和团体之间的外键限制。

    有没有方法告诉Hibernate先删除用户,然后删除组?我的模型有缺陷吗?

    3 回复  |  直到 10 年前
        1
  •  2
  •   andygavin    15 年前

    你试过在每个@manytoone上设置层叠吗?您只在许多方面指定了地址簿上的级联删除。这是我所相信的每个协会的财产。

    在编写这些bean时,EJB3.0规范非常值得一手操作。见 http://jcp.org/en/jsr/detail?id=220

    更新: 再次阅读您的数据模型,这里的人可能缺少一个解释行为的注释。您是否在与人员组的链接上设置了级联?这就解释了为什么第一个语句首先尝试删除组。假设您想要一个对不级联的人的组的注释?

        2
  •  1
  •   Salandur    15 年前

    有两种选择

    1)在第二次删除之前调用flush

    2)在映射中添加一个“cascade”:即cascade=“delete”。删除组将同时删除组的成员。

        3
  •  0
  •   Chris Kessel    15 年前

    您可以将其作为两个事务来执行,也可以像前面提到的那样使用cascade=delete。实际上,您可能希望删除孤立的,它执行级联删除,但仅在完全孤立的情况下删除该人。这有两个好处:

    1)您所要做的就是删除该组并自动删除子组(假设您的映射设置正确)。 2)如果一个人可以属于多个组,则只有当该子对象是孤立的时,它才会删除该子对象,这意味着没有组引用它。

    如果一个子对象(本例中的人)可以有多个父对象,那么第二部分就很重要了,因此,除非删除了每个父关系,否则不应该删除子对象。