1

这个问题让我很生气:

所以让我们说这个非常简单的案例:

(spring/Hibernate/jpa2/@PersistenceContext(type=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);

先感谢您

4

2 回答 2

2

看起来 Car 指向 User,换句话说,Car 有一个指向 User 的外键属性。因此删除 Car 也会删除对 User 的引用。这也会从用户的 Car Set 中移除 Car。因此,选项 1 就是您需要做的所有事情。

于 2012-08-30T18:45:29.060 回答
1

简而言之,这取决于关系的拥有方。

为简化起见,让我们假设一个虚拟规则:拥有方始终是具有外键的一方(对于整个故事,我会推荐一本好书,例如Pro JPA 2: Mastering the Java™ Persistence API)。由于您与to有@ManyToOne关系,根据我们的虚拟规则,是拥有方:CarUserCar

   *---------------*       *--------------*     
   |      CAR      |       |     USER     |     
   *---------------*       *--------------*     
   |  CARD_ID (PK) |   ~-> | USER_ID (PK) |     
   |  USER_ID (FK) | --~   *--------------*     
   *---------------*       

当您删除拥有方时,无需执行任何其他操作。

在您的情况下,由于汽车是拥有方,您可以简单地移除汽车,即dao.remove(car);就足够了。

现在让我们考虑相反的情况。假设您需要删除 a User,即被引用的一面。

如果您删除与汽车关联的用户(假设没有级联行为),数据库DELETE操作将因 FK 违规而失败。

通俗易懂的规则是:关系维护是应用程序的责任。这意味着在关系的相反(拥有)方面调整参考。

如果 car 表中的外键列可以是NULL您可以car.setUser(null);在删除用户之前使用的。这将在您的数据库中留下一辆孤车。

如果外键列是NOT NULL,在删除用户之前,您需要将汽车与另一个用户关联:

   car.setUser(anotherUser);

或者一起从数据库中删除汽车:

   dao.remove(car);

正如我所说,关系维护远不止这些。JPA 有@CascadeTypes 等特性;@ManyToMany可以任意选择拥有方的双向关系;单向@OneToMany(带有连接表)等。但我认为这几乎总结了基础知识。

于 2012-08-30T21:07:56.990 回答