休眠:ManyToMany反删除
我在两个表格User和Keyword之间有一个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 "/";
}
}
如果我浏览到/删除/关键字,我得到以下异常:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.blabla.prototype.Keyword.users, no session or session was closed
我搜索了很多不同的东西,但没有任何效果。
我感谢任何帮助。
非常感谢你,
马尔科
LazyInitializationException与删除无关。 您正在加载控制器中的关键字。 这使服务加载关键字,而不用初始化其懒惰的用户列表。 然后将该关键字返回给控制器,并提交事务,并关闭会话,使关键字脱离会话。
然后,您将此分离的关键字传递给该服务以将其删除。 该服务因此收到分离的关键字,并尝试访问其用户列表。 由于关键字已分离且用户列表尚未加载,因此会导致LazyInitializationException。
服务方法应该将关键字的ID作为参数删除,加载它,然后使用附加的关键字进行处理,然后继续删除。
现在回答你的问题,你删除了用户的权利:删除用户的所有关键字以删除,因为用户是关联的所有者。 删除关键字时应用相同的逻辑:从所有引用它的用户中删除关键字,并删除关键字:
public void deleteKeyword(Integer id) {
Keyword keyword = getKeyword(id);
for (User user : keyword.getUsers()) {
user.removeKeyword(keyword);
}
session.delete(keyword);
}
请注意,您在使用附加实体时不必调用update()。 附加实体的状态会自动并透明地保存到数据库中。
链接地址: http://www.djcxy.com/p/48831.html