我有这个项目结构:
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也有它们)。所以事情是:有没有办法删除设置,而不是手动从用户删除它们(可能有很多用户有很多设置,迭代它可能需要很多时间)?
答案 0 :(得分:1)
你是对的,你不能以任何一种自动的方式删除它们 - 它们永远不会是孤儿。我认为你能做的最好就是给自己写一个辅助方法。例如如果你有一个ServiceDao类,你只需添加一个帮助器:
public void deleteServiceAndSettings(Service service) {
for (UserServiceSettings setting : service.getUserServiceSettings()) {
session.delete(setting);
}
session.delete(service);
}
答案 1 :(得分:1)
如果UserServiceSettings在删除服务时(如果用户也引用了服务),那么为什么不删除UserServiceSettings。他们不是孤儿,必须根据您的业务逻辑明确删除。
三个想法:
使用ORM批量删除实体。
它与迭代没什么不同,但可以在使用ORM时进行优化。
List settingsCopy = new ArrayList<>(service.getSettings());
service.getSettings().clear();
myDao.deleteAll(settingsCopy);
使用直接HSQL / SQL进行批量删除。
这取决于您正在使用的框架,但通常可能是这样的,可能在您的repository / dao类中:
delete from UserServiceSettingsImpl o where o.service.id = ?
但是,hibernate确实如此删除时不支持JOIN,afaik,所以这不起作用。通常需要重新编写HSQL以使用“删除id IN(...)”类型格式。
在数据库DDL中设置CASCADE DELETE
和CASCADE UPDATE
,在ORM框架之外。 (不推荐。)
然而,如果有可能通过多个线程同时修改服务和用户的UserServiceSettings(即使具有正确的事务边界),或者如果这些实体将是删除后在orm上下文中使用,无需重新加载。在这种情况下,您可能会使用最后两种方法遇到意外和偶发错误,而应该迭代设置并通过ORM删除,即使它效率很低。
即使采用第一种方法,在删除共享实体时避免高度并发环境中的错误也很棘手。