我在两个表之间有一个ManyToMany关系,用户和关键字。用户是该关系的所有者。如果我删除用户,我会先从此用户中删除所有关键字,然后删除用户。这可以按预期工作。
但我不知道如何删除关键字并自动删除与所有用户的关系。
到目前为止,这是我的代码。
@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
我用谷歌搜索了许多不同的东西,但没有任何作用。
我感谢任何帮助。
非常感谢,
马
答案 0 :(得分: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()。附加实体的状态自动且透明地保存到数据库中。