Updating one field in JPA entity
I have an Entity User
that is assigned a system privilege in a function开发者_如何转开发. I have a web page where you select a user from a drop down and submit the form to the server. On the server side I want to update only one field for that entity.
My User entity will have default values for all objects except the one field that gets set and its id. Do I need to do a findById
then update the specific field then do the merge or is there a way to tell the to only update that field?
Do I need to do a findById then update the specific field then do the merge
That would be the regular approach, except that you don't need to merge a managed entity, just let JPA detect the changes and update it automatically.
or is there a way to tell the to only update that field?
No. But you could use a "short" version of your User
(with only the field(s) to update). Another option would be to use a Bulk Update Operation but this is IMO really not a good use case. I wouldn't use this approach.
Reference
- JPA 1.0 specification
- 4.10 Bulk Update and Delete Operations
JPA 2.1 now support update criteria that allow you to partial update entity via javax.persistence.criteria.CriteriaUpdate<T>
.
Javadoc here.
Example code:
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();
More details on JPA 2.1 partial update here.
If you are updating an entity that is selected by a client, you have two options.
1) If the User being selected is represented in the client as a detached entity, then when you receive the user entity in your server bean, you only need to assign the new field value, then perform an em.merge(selectedUser). This has the negative effect where the state of the user may have changed between user selection to your server performing the update, causing undesirable results.
2) Just have the form submit the user ID, then use the findById to lookup the user, modify your entity, then commit the change. If this is a server managed persistence unit, you don't need to commit.
精彩评论