我有这样的项目结构:
class UserServiceSettingsImpl {
...
@ManyToOne
private UserImpl user;
@ManyToOne
private ServiceImpl service;
...
}
class ServiceImpl {
....
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "service", orphanRemoval = true)
private Set<UserServiceSettingsImpl> userServiceSettings;
....
}
class UserImpl {
....
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
private Set<UserServiceSettingsImpl> serviceSettings;
....
}
我正在尝试删除 Service 及其所属的所有内容 (UserServiceSettingsImpl),但意外的是,此设置没有被删除(我想是因为它们不是孤儿,因为 UserImpl 也有它们)。所以问题是:有没有一种方法可以删除设置,而不需要手动从用户中删除它们(可能有很多用户有很多设置,迭代它可能需要很多时间)?
最佳答案
如果 UserServiceSettings 也被用户引用,那么在删除服务时,为什么 UserServiceSettings 不会被删除,您是正确的。它们不是孤立的,必须根据您的业务逻辑明确删除。
三个想法:
使用ORM批量删除实体。
它与迭代没有太大区别,但可以在仍然使用 ORM 的同时进行优化。List settingsCopy = new ArrayList<>(service.getSettings()); service.getSettings().clear(); myDao.deleteAll(settingsCopy);
直接使用HSQL/SQL批量删除。
这取决于您使用的框架,但通常是这样的,可能在您的存储库/dao 类中:
delete from UserServiceSettingsImpl o where o.service.id = ?
但是,hibernate 在删除时不支持 JOIN,据我所知,所以这不起作用。通常需要重新编写 HSQL 以使用“delete where id IN(...)”类型格式。设置
CASCADE DELETE
和CASCADE UPDATE
位于数据库 DDL 中,位于 ORM 框架之外。 (不推荐。)
但是,如果服务和用户的 UserServiceSettings 有可能通过多个线程同时修改(即使事务边界正确),或者如果这些实体将被修改,那么最后两个选项就会出现问题。删除后在 orm 上下文中使用,无需重新加载。在这种情况下,您可能会在使用最后两种方法时遇到意外和偶发的错误,而应该迭代设置并通过 ORM 进行删除,即使效率很低。
即使使用第一种方法,在删除共享实体时避免高并发环境中的错误也可能很棘手。
关于java - Hibernate 中的孤立删除(当有多个映射对象时),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22561384/