【问题标题】:Hibernate @ManyToMany delete relationHibernate @ManyToMany 删除关系
【发布时间】:2009-08-19 11:54:21
【问题描述】:

我有 2 个实体:User 和 UsersList。

@Entity
@Table(name = "USERS")
public class User {
    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @ManyToMany(cascade = CascadeType.REMOVE, mappedBy = "users")
    private List<UsersList> usersLists = new ArrayList<UsersList>();

    public List<UsersList> getUsersLists() {
        return usersLists;
    }

    public void setUsersLists(List<UsersList> usersLists) {
        this.usersLists = usersLists;
    }
}

@Entity
@Table(name = "USERS_LIST")
public class UsersList {
    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @ManyToMany
    private List<User> users = new ArrayList<User>();

 public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
}

和这样的代码:

// 1
List<User> dbUsers; // 3 the user instances are persisted in DB
UsersList usersList = new UsersList();
usersList.setUsers(dbUsers);

// 2 - now persist the usersList using hibernate...
saveWithHibernate(usersList); 

//3 - delete using a persisted user
deleteWithHibernate(dbUsers.get(0).getId());

在哪里

deleteWithHibernate(Long id) {
        User usr = hibernateTemplate.get(User.class, id);
        hibernateTemplate.delete(usr);
}

在第 1 步中,我在 USERS (USER_ID) 表中有 3 行。

在第 2 步(第二条评论)之后,我在 USERS_LIST (USERS_LIST_ID) 表中有 1 行,在连接表 USERS_LIST_USERS (USER_ID, USERS_LIST_ID) 中有 3 行。

我想在第 3 步中实现以下目标:当我从表 USERS 中删除一个用户时 - 假设 USER_ID = 4 的用户,我只想从连接表中删除 USER_ID = 4 的行,和其他人留下来。

我的问题有注释解决方案吗?

【问题讨论】:

  • deleteWithHibernate 方法是什么样的?

标签: hibernate annotations many-to-many


【解决方案1】:

你需要的是@JoinTable 属性:

Hibernate 不知道多对多关系相互引用,并且可能会创建两个连接表。如果您在关系的两侧指定相同的@JoinTable,它将按预期工作。

确保 joinColumn 和 inverseJoinColumn 在对立面上是对立的 关系的双方。

  • 一侧的joinColumn ==另一侧的inverseJoinColumn
  • 一侧的inverseJoinColumn ==另一侧的joinColumn

我希望这会有所帮助。

@Entity
public class Role extends Identifiable {

    @ManyToMany(cascade ={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinTable(name="Role_Permission",
            joinColumns=@JoinColumn(name="Role_id"),
            inverseJoinColumns=@JoinColumn(name="Permission_id")
        )
    public List<Permission> getPermissions() {
        return permissions;
    }

    public void setPermissions(List<Permission> permissions) {
        this.permissions = permissions;
    }
}

@Entity
public class Permission extends Identifiable {

    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinTable(name="Role_Permission",
            joinColumns=@JoinColumn(name="Permission_id"),
            inverseJoinColumns=@JoinColumn(name="Role_id")
        )
    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

}

【讨论】:

  • 我在我的解决方案中使用了“@JoinTable”,但仍然无法删除行。有必要提到你提到的所有级联吗?
  • OP 使用mappedBy,这还不足以让hibernate 知道@JoinTable 应该是什么样子吗?明确列出 @JoinTable 名称和列似乎有点多余,除非您真的想确保使用您的确切名称。
【解决方案2】:

我认为你必须作为这个注释

    @OnDelete(action = OnDeleteAction.CASCADE)
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

并将 cascade.remove 更改为 CascadeType.ALL 你的代码必须是这样的

   @ManyToMany(cascade = CascadeType.ALL, mappedBy = "users")
   @OnDelete(action = OnDeleteAction.CASCADE)
   @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
   private List<UsersList> usersLists = new ArrayList<UsersList>();

【讨论】:

  • @OnDelete 是特定于休眠的注解,在 JPA 中不可用。