使用 hibernate 保存从查询中获取的实体

发布于 2025-01-08 03:35:14 字数 2015 浏览 1 评论 0原文

我有一个基本的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

顾冷 2025-01-15 03:35:14

只需检查 @Id 是否已设置。

@Override
public void saveEntity (Car car) {
    if (car.getId() == null) {
        entityManager.persist(car);
    } else {
        entityManager.merge(car);
    }
}

然而,更常见的方法是提供单独的 create()update() 服务方法。

Just check if the @Id is been set.

@Override
public void saveEntity (Car car) {
    if (car.getId() == null) {
        entityManager.persist(car);
    } else {
        entityManager.merge(car);
    }
}

More common approach, however, is to offer separate create() and update() service methods.

海拔太高太耀眼 2025-01-15 03:35:14

我不熟悉 JPA,但在 hibernate 中有 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);
}

没有持久和合并的细微差异

I'm not familiar with JPA but in hibernate there is session.saveOrUpdate()

for(Car car : existingAndNewCars)
{
    session.saveOrUpdate(car);
}

Update:

As i understand JPA, its merge is like session.merge which is totally different as it doesn't track changes to object supplied to it while persist/save/update/saveOrUpdate would track subsequent changes to car, leading to subtle differences

Update:

since you use the same entitymanager it should suffice to

@Override
public void saveEntity (Car car) {
    if (car.getId() == null) {
        entityManager.persist(car);
}

without the subtle difference of persist and merge

聊慰 2025-01-15 03:35:14

刷新操作将对当前 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文