JPA - 持久化一对多关系。

80
也许这是个愚蠢的问题,但它困扰着我。
我有一个员工到车辆的双向一对多关系。当我第一次将员工持久化到数据库中(即它没有分配ID时),我也希望它相关联的车辆得到持久化。
目前这对我来说很好用,但是我的已保存的车辆实体没有自动映射到相关联的员工,并且在数据库中,Vehicle表中的employee_id外键列为空。
我的问题是,是否可以在同一时间内持久化车辆的员工和员工本身?我意识到需要先保存员工,然后再保存车辆。JPA能否自动为我完成此操作?还是我需要做类似以下的事情:
Vehicle vehicle1 = new Vehicle();
Set<Vehicle> vehicles = new HashSet<Vehicle>();
vehicles.add(vehicle1);

Employee newEmployee = new Employee("matt");
newEmployee.setVehicles(vehicles);
Employee savedEmployee = employeeDao.persistOrMerge(newEmployee);

vehicle1.setAssociatedEmployee(savedEmployee);
vehicleDao.persistOrMerge(vehicle1);

谢谢!

编辑:如请求所示,这是我的映射(不包括其他所有的方法等)。

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="employee_id")
    private Long id;

    @OneToMany(mappedBy="associatedEmployee", cascade=CascadeType.ALL)
    private Set<Vehicle> vehicles;

    ...

}

@Entity 
public class Vehicle {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="vehicle_id")
    private Long id;

    @ManyToOne
    @JoinColumn(name="employee_id")
    private Employee associatedEmployee;

    ...
}

我刚刚意识到我应该在我的Employee类中定义了以下方法:

public void addVehicle(Vehicle vehicle) {
    vehicle.setAssociatedEmployee(this);
    vehicles.add(vehicle);
}

现在,上面的代码将看起来像这样:

Vehicle vehicle1 = new Vehicle();

Employee newEmployee = new Employee("matt");
newEmployee.addVehicle(vehicle1);
Employee savedEmployee = employeeDao.persistOrMerge(newEmployee);

简单清晰得多。感谢大家的帮助!

2个回答

59

在持久化员工之前,您需要设置车辆上的 associatedEmployee。

Employee newEmployee = new Employee("matt");
vehicle1.setAssociatedEmployee(newEmployee);
vehicles.add(vehicle1);

newEmployee.setVehicles(vehicles);

Employee savedEmployee = employeeDao.persistOrMerge(newEmployee);

3
哦,好的。那样可以。但我想是否有一种方法,我不必明确地在车辆上设置关联的员工? - JMM
我认为使用JPA是不可能的。我还使用过Hibernate,如果我没记错的话,那是可以实现的。 - Bobby
感谢您指出我原来代码中的问题,我已经更新了它,并说明了我将如何解决它。 - JMM
你很厉害... 很棒的解决方案... 我遇到这个问题好几天了... 我自己也想到了这个解决方案,但感觉不太合理。 - GorillaApe
4
答案不完整。由于“默认情况下,不会级联任何操作”,您仍需要设置级联。 - petertc

33
一种实现方法是在关系中的"One"一侧设置级联选项:
class Employee {
   // 

   @OneToMany(cascade = {CascadeType.PERSIST})
   private Set<Vehicles> vehicles = new HashSet<Vehicles>();

   //
}

通过这种方式,当您调用
Employee savedEmployee = employeeDao.persistOrMerge(newEmployee);

它还将拯救车辆。


嗨,感谢回复。我已经按照您建议的设置了级联,并且车辆已经被保存了。我的问题是,当这些车辆被保存时,我希望它们的外键列employee_id包含我刚刚保存的员工的ID。 - JMM
1
外键应该保存在级联中...您能否发送您用于检查的@OneToMany和@ManyToOne注释?最好的问候,Denes - user218435
10
问题出在mappedBy属性上,它定义了关系的拥有者是“多”的那一方。这种方式通常在双向一对多的关系中使用,但可以改变拥有者为您所需的“一”的那一方。本链接第2.2.5.3.2.1节提供了如何进行更改的示例。http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html最好的问候,Denes - user218435

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接