当前位置: 首页 > 知识库问答 >
问题:

Hibernate:ManyToMany反向删除

潘佐
2023-03-14

我在两个表User和Keyword之间有很多很多的关系。用户是关系的所有者。如果我删除了一个用户,我首先从这个用户删除所有关键字,然后删除这个用户。这与预期的一样工作。

但我不知道如何删除一个关键字,并自动删除与所有用户的关系。

这里是我到目前为止的代码。


    @Entity
    @Table(name = "user")

    public class User {

      @Id
      @Column(name = "id")
      @GeneratedValue
      private Integer id;

      @Column(name = "name")
      private String name;

      @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
      @Fetch(value = FetchMode.SUBSELECT)
      @JoinTable(name = "user_has_keyword", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "keyword_id"))
      private List keywords = new ArrayList();

      // Getters and setters
      ...
    }


    @Entity
    @Table(name = "keyword")
    public class Keyword {

      @Id
      @Column(name = "id")
      @GeneratedValue
      private Integer id;

      @Column(name = "keyword")
      private String keyword;

      @ManyToMany(mappedBy = "keywords")
      private List users = new ArrayList();

      // Getters and setters
      ...
    }


    @Service("myService")
    @Transactional("transactionManager")
    public class MyService {

      @Resource(name = "sessionFactory")
      private SessionFactory sessionFactory;

      @SuppressWarnings("unchecked")
      public List getAllUsers() {
        Session session = this.sessionFactory.getCurrentSession();

        Query query = session.createQuery("FROM User");

        return query.list();
      }

      public User getUser(Integer id) {
        Session session = this.sessionFactory.getCurrentSession();
        return (User) session.get(User.class, id);
      }

      public void addUser(User user) {
        Session session = this.sessionFactory.getCurrentSession();
        session.save(user);
      }

      public void deleteUser(User user) {
        Session session = this.sessionFactory.getCurrentSession();

        // 1st, delete relations
        user.getKeywords().clear();
        session.update(user);

        // 2nd, delete User object
        session.delete(user);
      }

      public Keyword getKeyword(Integer id) {
        Session session = this.sessionFactory.getCurrentSession();
        return (Keyword) session.get(Keyword.class, id);
      }

      public Keyword addKeyword(Keyword keyword) {
        Session session = this.sessionFactory.getCurrentSession();
        session.save(keyword);

        return keyword;
      }

      public void deleteKeyword(Keyword keyword) {
        Session session = this.sessionFactory.getCurrentSession();

        // 1st, delete relations
        keyword.getUsers().clear();
        session.update(keyword);

        // 2nd, delete User object
        keyword = getKeyword(keyword.getId());
        session.delete(keyword);
      }
    }


    @Controller
    public class MyController {

      @Resource(name = "myService")
      private MyService myService;

      @RequestMapping(value = "/add", method = RequestMethod.GET)
      public String add(Model model) {

        Keyword k = new Keyword();
        k.setKeyword("yellow");
        k = myService.addKeyword(k);

        User u1 = new User();
        u1.setName("Bart");
        u1.getKeywords().add(k);
        myService.addUser(u1);

        User u2 = new User();
        u2.setName("Lisa");
        u2.getKeywords().add(k);
        myService.addUser(u2);

        return "/";
      }

      @RequestMapping(value = "/delete/user", method = RequestMethod.GET)
      public String deleteUser(Model model) {

        User u = myService.getUser(1);
        myService.deleteUser(u);

        return "/";
      }

      @RequestMapping(value = "/delete/keyword", method = RequestMethod.GET)
      public String deleteKeyword(Model model) {

        Keyword k = myService.getKeyword(1);
        myService.deleteKeyword(k);

        return "/";
      }

    }

如果浏览到/delete/keyword,则会出现以下异常:


    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.blabla.prototype.Keyword.users, no session or session was closed

我在谷歌上搜索过,尝试过很多不同的方法,但都不奏效。

我很感激任何帮助。

非常感谢,

马可

共有1个答案

罗翰
2023-03-14

LazyInitializationException与删除无关。您正在控制器中加载一个关键字。这使得服务加载关键字,而不初始化其惰性用户列表。然后将此关键字返回到控制器,提交事务,关闭会话,使关键字与会话分离。

然后将这个分离的关键字传递给服务以删除它。因此,该服务接收一个分离的关键字,并尝试访问其用户列表。由于关键字已分离,用户列表尚未加载,这将导致LazyInitializationException。

服务方法应该将要删除的关键字的ID作为参数,加载它,从而处理附加的关键字,然后继续删除。

现在要回答您的问题,您对用户删除做了正确的处理:您从要删除的用户中移除所有关键字,因为该用户是关联的所有者。删除关键字时应用相同的逻辑:从所有引用该关键字的用户中删除该关键字,然后删除该关键字:

public void deleteKeyword(Integer id) {
    Keyword keyword = getKeyword(id);
    for (User user : keyword.getUsers()) {
        user.removeKeyword(keyword);
    }
    session.delete(keyword);
}

注意,在处理附加实体时不必调用update()。附加实体的状态会自动透明地保存到数据库中。

 类似资料:
  • Django演示了如何设置或覆盖在文档中使用外键的级联删除。 但是如果我们想让这种效果反过来呢?如果我们希望fk模型的删除导致该模型的删除,该怎么办? 谢谢

  • 问题内容: 我有一个包含两列的数据框,并且。在这种情况下,和的顺序并不重要;例如,我会考虑并将其重复。在熊猫中,从数据框中删除这些重复项的有效方法是什么? 理想情况下,输出将按column的值排序。 问题答案: 您可以在删除重复项之前对数据框的每一行进行排序: 如果您希望按列对结果进行排序:

  • 参考阅读:什么是反向Shell 这篇教程将会教你使用Python编写一个反向shell,首先我们先演示使用Python如何利用web服务器的功能,把文件从另一台主机传送过来。我们假设你有一台傀儡主机,你现在想下载傀儡机上面的的文件。那么你就可以使用shell(或meterpreter)去访问这台傀儡机,你可以通过一行Python代码把傀儡机建立成为一个web服务器,然后下载傀儡机上面的文件. 创建

  • 问题内容: 我有一个配对列表: 我想删除任何重复的地方 所以我们最后只是 如果不是这种情况,我可以对反向对进行内部和外部循环检查,然后追加到列表中,但是我敢肯定,有更多的Python方式可以达到相同的结果。 问题答案: 如果您需要保留列表中元素的顺序,则可以使用函数并使用以下方式设置理解: 或根本不像这样: 另一种方法是使用一个如图所示这里但是请注意,如果您的列表中有不同的元素这只是工作。因为li

  • 问题内容: 我在寻找解决方案时遇到了麻烦。我正在尝试使用JS(或其他库)来制作它,以便当用户在鼠标滚轮上向下滚动时,页面以与通常相反的方式滚动。 基本上,我希望页面的底部首先显示,并且随着用户滚动,我希望屏幕的顶部向下显示。我能够找到的唯一示例是http://conduit.com/的右列。 我已经建立了一个JSFiddle并提供了一个示例来帮助对其进行可视化。我知道这可能与以下内容有关: 但老实

  • 问题内容: 我在给像这样的物体 如何将字符串转换回对象? 问题答案: 您需要字符串。