使用 hibernate 保存从查询中获取的实体
我有一个基本的 Hibernate/JPA 问题。我想找到保存实体的最佳实践解决方案。我有一个实体列表,其中许多可能会被更改,所以我想立即保存它们。
我相信一切都非常标准。 (出于可读性原因,只是示例代码)
实体:汽车
@Entity
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private id;
private String model;
// .... Setter
// .... Getter
}
服务类:CarService
@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? */
}
}
控制器:CarEditController
@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) 。理论上这很简单,但我怎么知道哪个实体是新的?
文档建议 entityManager .flush(),理论上会更新所有现有实体并插入所有新实体。它有效,但前提是我使用 find() 获取实体。
问题:
我想一步获取所有实体,添加新实体,然后将它们全部保存在一种方法 (btn_saveClick()) 中。如何最好地完成这项任务?
I hava a basic Hibernate/JPA question. I want to find a best practice solution for saving entities. I have a List of Entities and many of them might be altered so I want to save them all at once.
I believe everything is pretty much standard. (Just example code for readability reasons)
Entity: Car
@Entity
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private id;
private String model;
// .... Setter
// .... Getter
}
Service Class: CarService
@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? */
}
}
Controller: CarEditController
@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);
}
}
}
I found quite a few ways of saving the entity. The obvious are entityManager.merge(car) for existing entities and entityManager.persist(car) for new ones. In theory thats easy but how do I know which entity is new?
The documentation suggests entityManager.flush(), which in theory updates all existing and inserts all new entities. It works but only if I fetch the entity with find().
The Question:
I want to fetch all entities in one step, add new ones and then save them all in one methode (btn_saveClick()). How is this task best accomplished?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
只需检查
@Id
是否已设置。然而,更常见的方法是提供单独的
create()
和update()
服务方法。Just check if the
@Id
is been set.More common approach, however, is to offer separate
create()
andupdate()
service methods.我不熟悉 JPA,但在 hibernate 中有
session.saveOrUpdate()
更新:
据我了解 JPA,它的
merge
就像session.merge 这是完全不同的,因为它在
persist
/save
/update
/saveOrUpdate 时不跟踪提供给它的对象的更改
将跟踪后续更改到汽车,导致细微的差异更新:
因为您使用相同的实体管理器,所以应该足以
没有持久和合并的细微差异
I'm not familiar with JPA but in hibernate there is
session.saveOrUpdate()
Update:
As i understand JPA, its
merge
is likesession.merge
which is totally different as it doesn't track changes to object supplied to it whilepersist
/save
/update
/saveOrUpdate
would track subsequent changes to car, leading to subtle differencesUpdate:
since you use the same entitymanager it should suffice to
without the subtle difference of persist and merge
刷新操作将对当前 Hibernate 会话中的所有实体进行操作 - 插入新实体并更新现有实体(如果它们已更改)。
您需要确保所有实体都附加到会话。正如您所说,您可以通过使用合并来做到这一点。加载所有实体后,会话将在事务结束时关闭。然后,您的对象处于分离状态,即已被持久化,但不再附加到会话。
我会修改你的逻辑,以便你的 carService#save 获取一个列表。然后它可以对每一个调用合并(将它们附加到会话)。然后,当事务结束时,Hibernate 将立即刷新数据库中的所有更改。
The flush operation will operate on all entities in the current Hibernate session - new entities are inserted and existing entities are updated if they have changed.
You need to ensure that all entities are attached to the session. You do this by using merge as you correctly say. After you have loaded all of the entities the session is closed when the transaction ends. Your objects are then in a detached state i.e. have been persisted but are no longer attached to a session.
I would amend your logic so that your carService#save takes a List. It can then call merge on each one (attaching them to the session). Then when your transaction ends Hibernate will flush all changes to the database at once.