首页 文章

Hibernate:ManyToMany逆删除

提问于
浏览
2

我在两个表之间有一个ManyToMany关系,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 回答

  • 2

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

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

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

    现在回答您的问题,您可以删除用户:从用户删除所有关键字以删除,因为用户是关联的所有者 . 删除关键字时应用相同的逻辑:从引用它的所有用户中删除关键字,并删除关键字:

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

    请注意,在使用附加实体时,您不必调用update() . 附加实体的状态自动且透明地保存到数据库中 .

相关问题