我有一个基本的Hibernate / JPA问题。我想为保存实体找到最佳实践解决方案。我有一个实体列表,其中许多可能会被修改,所以我想立即保存它们。
我相信一切都非常标准。 (仅出于可读性原因的示例代码)
@Entity
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private id;
private String model;
// .... Setter
// .... Getter
}
@Named
@Transactional
public class CarServiceImpl implements CarService {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<Car> findAll() {
TypedQuery<Car> q = entityManager.createQuery(
"FROM Car", Car.class);
return q.getResultList();
}
@Override
public void saveEntity (Car car) {
/* What exactly am I doing here? */
}
}
@Named
public class CarEditController implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
private CarService carService;
private List<Car> cars;
public List<Car> getCars () {
return carService.findAll();
}
public void setCars (List<Car> cars) {
this.cars = cars;
}
public void btn_newClick() {
Car newCar = new Car();
car setModel("BMW");
cars.add(newCar);
}
public void btn_saveClick() {
for (Car car : cars) {
carService.saveEntity(car);
}
}
}
我找到了很多保存实体的方法。显而易见的是现有实体的 entityManager.merge(car)和新实体的 entityManager.persist(car)。理论上这很容易,但我怎么知道哪个实体是新的?
documentation建议 entityManager.flush(),理论上更新所有现有实体并插入所有新实体。只有当我使用 find()获取实体时,它才有效。
问题:
我想一步获取所有实体,添加新实体,然后将它们全部保存在一个方法中(btn_saveClick())。如何最好地完成这项任务?
答案 0 :(得分:2)
我不熟悉JPA,但在休眠状态下有session.saveOrUpdate()
for(Car car : existingAndNewCars)
{
session.saveOrUpdate(car);
}
更新
据我了解JPA,其merge
与session.merge
类似,完全不同,因为在persist
/ save
/ update
/ saveOrUpdate
/时,它不会跟踪对其提供的对象的更改@Override
public void saveEntity (Car car) {
if (car.getId() == null) {
entityManager.persist(car);
}
/ {{1}}会跟踪对汽车的后续更改,从而导致细微的差异
更新
因为您使用相同的实体管理器,所以
就足够了{{1}}
没有持久和合并的细微差别
答案 1 :(得分:2)
只需检查是否已设置@Id
。
@Override
public void saveEntity (Car car) {
if (car.getId() == null) {
entityManager.persist(car);
} else {
entityManager.merge(car);
}
}
然而,更常见的方法是提供单独的create()
和update()
服务方法。
答案 2 :(得分:1)
刷新操作将对当前Hibernate会话中的所有实体进行操作 - 插入新实体并更新现有实体。
您需要确保所有实体都附加到会话。您正确地说,使用合并执行此操作。加载所有实体后,会话在事务结束时关闭。然后,您的对象处于分离状态,即已保留但不再连接到会话。
我会修改你的逻辑,以便你的carService#save获取一个List。然后它可以在每个上调用merge(将它们附加到会话)。然后,当您的事务结束时,Hibernate将立即刷新对数据库的所有更改。