这个问题让我很伤心:
让我们说这个非常简单的案例:
(弹簧/休眠/ JPA2 / @ PersistenceContext(类型= PersistenceContextType.TRANSACTION))
我们有DAO实体:
class User{
private Set<Car> carSet;
... usual setters + getters
}
class Car{
private User user;
... usual setters + getters
}
以下哪一项是carId删除汽车的推荐方法及原因(这将在http post请求中完成,除此删除外不会执行其他操作)?
1)简单的删除操作;
Car car = dao.find(Car.class, carId);
dao.remove(car);
2)首先清理参考文献。这种方法何时推荐?
Car car = dao.find(Car.class, carId);
car.getUser().getCarSet().remove(car); // this one as far as I know will usually fetch the other cars, and I think is not optimal, am I right?
car.setUser(null);
dao.remove(car);
提前谢谢
答案 0 :(得分:2)
看起来Car指向User,换句话说,Car有一个指向User的外键属性。因此,删除Car也将删除对User的引用。这也将从用户的车载中删除Car。因此,您需要做的就是选项1.
答案 1 :(得分:1)
简而言之,这取决于关系的拥有方。
为了简化它,让我们假设一个虚拟规则:拥有方总是带有外键的那个(对于整个故事,我会推荐一本好书,如Pro JPA 2: Mastering the Java™ Persistence API)。由于您从@ManyToOne
到Car
之间存在User
关系,因此根据我们的虚拟规则,Car
是拥有方:
*---------------* *--------------*
| CAR | | USER |
*---------------* *--------------*
| CARD_ID (PK) | ~-> | USER_ID (PK) |
| USER_ID (FK) | --~ *--------------*
*---------------*
当您移除拥有方时,不必做任何其他事情。
在您的情况下,由于汽车是拥有方,您可以简单地移除汽车,即dao.remove(car);
就足够了。
现在让我们考虑相反的情况。假设您需要删除User
,即引用的一方。
如果删除与其关联的汽车的用户(假设没有级联行为),则数据库DELETE
操作将因FK违规而失败。
tumb的规则是:关系维护是应用程序的责任。这意味着调整关系的相反(拥有)方面的参考。
如果car table中的外键列可以是NULL
,则可以在删除用户之前使用car.setUser(null);
。这会在您的数据库中留下孤儿车。
如果外键列为NOT NULL
,则在删除用户之前,您需要将该车与其他用户关联:
car.setUser(anotherUser);
或者将汽车从数据库中一起移除:
dao.remove(car);
正如我所说,关系维护还有很多。 JPA具有@CascadeType
s等功能;双向@ManyToMany
关系,可以任意选择拥有方;单向@OneToMany
(带连接表)等。但我认为这几乎总结了基础知识。