【问题标题】:Deleting in hibernate with multiple relations在具有多个关系的休眠中删除
【发布时间】:2014-11-08 09:53:18
【问题描述】:

我的实体:

@Entity
public class User{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "userId")
    private Long id;
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<UC> owned = new ArrayList<UC>();
}

@Entity
public class UC{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @JoinColumn(name = "ukId")
    private Long id;
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "userId")
    private User user;
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "catId")
    private Cat cat;
}

@Entity
public class Cat{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "catId")
    private Long id;
    @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
    private List<UC> owned = new ArrayList<UC>();
}

所以这是我的问题,实际上很少。

问题 #1:

我删除了一个 Cat 对象,我在 Cat 的拥有列表上设置了 cascadeType.All,所以当我删除 Cat 对象时,UC 中所有带有 Cat 的记录都将被删除,但是我得到“删除的对象将被重新保存通过级联”,那是因为我在 UC 中与用户有另一个关系,他将 UC 存储在列表中。当我从 UC 中删除 Cat 对象和记录时,我不想删除 User 对象,因此在 UC 中在 @ManyToOne 上设置级联是不行的。我应该怎么做?在删除 Cat 之前,我应该从用户拥有的列表中删除所有 UC 实例吗?如果是这种情况,我在 UC 中的关系比此处显示的要多,我也必须从其他列表中删除实例。

问题 #2:

类似的情况,但我有常规的多对多关系我想删除连接表记录而不删除关系的另一端。

【问题讨论】:

  • 不确定我是否完全明白这一点:是否要删除一个 Cat 实体并自动删除 UC 表中对该 cat 的所有引用?
  • 是的,但不会删除用户或其他相关实体。当我在 UC 中不使用级联时,我在删除用户时收到错误消息。我只想删除Cat, UC 中包含Cat 的记录并更新猫的用户列表。

标签: java mysql hibernate


【解决方案1】:

这是我的解决方案。 首先,我将通过这种方式在 OneToMany 关联上设置孤儿删除。

@OneToMany(mappedBy = "cat", cascade = CascadeType.ALL, orphanRemoval = true)

然后,假设您有一个要删除的用户 u 和一个 Cat c。这段代码应该可以正常工作

    // Remove a cat and update the other entities
    Session s = sessionFactory.openSession();
    s.beginTransaction();
    s.delete(c);
    for (UC uc : c.getOwned())
        uc.getUser().getOwned().remove(uc);
    s.update(u);
    s.getTransaction().commit();
    s.close();

【讨论】:

  • 所以我从用户中删除了所有出现的 UC,但正如我所说,我与 UC 有更多的关系,这意味着我必须对所有其他集合都这样做。这是正确的做法吗?
  • 好吧,如果您不想通过代码执行此操作,您始终可以强制命中数据库以再次检索用户(更新集合)。例如,您可以调用s.delete(c),关闭会话,打开新会话并调用u = s.get(User.class, u.getId())。关键是,当您调用s.delete(c) 时,它实际上删除了 UC 表中的所有引用(即在数据库上);但是,本地集合(即拥有的列表)不会自动更新。因此,如果您不想手动更新它,则必须再次访问数据库(但我认为这不是更好的解决方案)
  • @JohnSmith 同样,从答案代码中,您可以仅对要删除的实体(即 cat c)执行工作,并从其集合(即拥有的列表 uc)中获取引用到不应该被删除的实体(即用户 u)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-17
  • 2014-08-22
  • 2019-07-31
相关资源
最近更新 更多