Обновление одного поля в сущности JPA

у меня есть объект User, которому назначается системная привилегия в функции. У меня есть веб-страница, на которой вы выбираете пользователя из раскрывающегося списка и отправляете форму на сервер. На стороне сервера я хочу обновить только одно поле для этой сущности.

моя сущность пользователя будет иметь значения по умолчанию для всех объектов, кроме одного поля, которое получает set и его id. Мне нужно сделать findById затем обновите конкретное поле, затем выполните слияние или есть способ сказать, чтобы только обновить это поле?

3 ответов


мне нужно сделать findById затем обновить конкретное поле, а затем выполнить слияние

это был бы обычный подход, за исключением того, что вам не нужно объединять управляемый объект, просто позвольте JPA обнаружить изменения и обновить его автоматически.

или есть способ сказать, чтобы только обновить это поле?

нет. Но вы можете использовать "короткую" версию вашего User (только с полем (полями) для обновления). Другой вариант было бы использовать Массовая Операция Обновления но это ИМО действительно не хороший вариант использования. Я бы не стал использовать такой подход.

ссылка

  • спецификация JPA 1.0
    • 4.10 массовое обновление и удаление операций

JPA 2.1 теперь поддерживает критерии обновления, которые позволяют вам частично обновлять сущность через javax.persistence.criteria.CriteriaUpdate<T>.

Javadoc здесь.

пример кода:

EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();

// create user
em.getTransaction().begin();
User user = new User();
user.setUsername("user@example.com");
user.setPassword("password");
user.setCreatedAt(new Date());
em.persist(user);
em.getTransaction().commit();
// end create user

assert user.getId() != 0;

System.out.println("Before update user Date of Birth: " + user.getDateOfBirth());

// update user date of birth
em.getTransaction().begin();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaUpdate<User> updateCriteria = cb.createCriteriaUpdate(User.class);
Root<User> root = updateCriteria.from(User.class);
// update dateOfBirth property
updateCriteria.set(root.get("dateOfBirth"), new Date());
// set where clause
updateCriteria.where(cb.equal(root.get("id"), user.getId()));
// update
int affected = em.createQuery(updateCriteria).executeUpdate();
System.out.println("Affected row: " + affected);
em.getTransaction().commit();
// end update user date of birth


// select user again to verify
em.getTransaction().begin();
em.refresh(user);

System.out.println("After update User Date of Birth: " + user.getDateOfBirth());

em.getTransaction().commit();
em.close();

подробнее о в JPA 2.1 частичное обновление здесь.


Если вы обновляете объект, выбранный клиентом, у вас есть два варианта.

1) Если выбранный пользователь представлен в клиенте как отдельная сущность, то при получении сущности пользователя в компоненте сервера вам нужно только назначить новое значение поля, а затем выполнить em.слияния(selectedUser). Это имеет отрицательный эффект, когда состояние пользователя может измениться между выбором пользователя на ваш сервер, выполняющий обновление, вызывая нежелательные результаты.

2) просто отправьте форму ID пользователя, затем используйте findById для поиска пользователя, измените свою сущность, а затем зафиксируйте изменение. Если это управляемая сервером единица сохраняемости, фиксация не требуется.