query mkyong example data java jpa spring-data-jpa

java - mkyong - ¿Cómo actualizo una entidad usando spring-data-jpa?



spring data rest (4)

Bueno, la pregunta casi dice todo. Usando JPARepository ¿cómo actualizo una entidad?

JPARepository tiene solo un método de guardar , que no me dice si es crear o actualizar realmente. Por ejemplo, inserto un objeto simple en el usuario de la base de datos, que tiene tres campos: nombre y apellido y antigüedad:

@Entity public class User { private String firstname; private String lastname; //Setters and getters for age omitted, but they are the same as with firstname and lastname. private int age; @Column public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } @Column public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } private long userId; @Id @GeneratedValue(strategy=GenerationType.AUTO) public long getUserId(){ return this.userId; } public void setUserId(long userId){ this.userId = userId; } }

Entonces simplemente "guardo", que en este momento es un inserto en realidad:

User user1 = new User(); user1.setFirstname("john"); user1.setLastname("dew"); user1.setAge(16); userService.saveUser(user1);// This call is actually using the JPARepository: userRepository.save(user);

Ok, todo esta bien Ahora quiero actualizar a este usuario, digamos cambiar su edad. Bueno, podría utilizar una consulta para QueryDSL o NamedQuery, lo que sea. Pero, considerando que solo quiero usar spring-data-jpa y el JPARepository, ¿cómo puedo decirle que en lugar de insertar quiero hacer una actualización?

Específicamente, ¿cómo le digo a spring-data-jpa que los usuarios que tienen el mismo nombre de usuario y nombre son en realidad IGUALES y que se supone que debe actualizar la entidad. Anular Iguales no funcionó.

¡Gracias!


Así es como resolví el problema:

User inbound = ... User existing = userRepository.findByFirstname(inbound.getFirstname()); if(existing != null) inbound.setId(existing.getId()); userRepository.save(inbound);


Dado que la respuesta de @axtavt se centra en JPA no en spring-data-jpa

Para actualizar una entidad mediante consultas, guardar no es eficiente porque requiere dos consultas y posiblemente la consulta puede ser bastante costosa, ya que puede unir otras tablas y cargar cualquier colección que tenga fetchType=FetchType.EAGER

Spring-data-jpa admite la operación de actualización.
Debes definir el método en la interfaz del repositorio y anotarlo con @Query y @Modifying .

@Modifying @Query("update User u set u.firstname = ?1, u.lastname = ?2 where u.id = ?3") void setUserInfoById(String firstname, String lastname, Integer userId);

@Query es para definir consultas personalizadas y @Modifying es para indicar a spring-data-jpa que esta consulta es una operación de actualización y requiere executeUpdate() no executeQuery() .


La identidad de las entidades se define por sus claves principales. Como firstname y lastname no son partes de la clave principal, no puede decirle a JPA que trate a los User con los mismos firstname y lastname igual que si tuvieran diferentes userId .

Por lo tanto, si desea actualizar un User identificado por su nombre y lastname , debe buscarlo por medio de una consulta y luego cambiar los campos correspondientes del objeto que encontró. Estos cambios se enviarán automáticamente a la base de datos al final de la transacción, de modo que no necesita hacer nada para guardar estos cambios de forma explícita.

EDITAR:

Tal vez debería profundizar en la semántica general de JPA. Hay dos enfoques principales para el diseño de API de persistencia:

  • insertar / actualizar enfoque . Cuando necesite modificar la base de datos, debe llamar explícitamente a los métodos de persistencia API: llame a insert para insertar un objeto, o update para guardar un nuevo estado del objeto en la base de datos.

  • Enfoque de unidad de trabajo . En este caso, tiene un conjunto de objetos administrados por la biblioteca de persistencia. Todos los cambios que haga en estos objetos se enviarán automáticamente a la base de datos al final de la Unidad de trabajo (es decir, al final de la transacción actual en el caso típico). Cuando necesita insertar un nuevo registro en la base de datos, hace que el objeto correspondiente sea administrado . Los objetos administrados se identifican por sus claves principales, de modo que si hace que un objeto con clave primaria predefinida sea administrado , se asociará con el registro de la base de datos del mismo ID, y el estado de este objeto se propagará a ese registro automáticamente.

JPA sigue el enfoque posterior. save() en Spring Data JPA está respaldado por merge() en JPA simple, por lo tanto, hace que su entidad se administre como se describe arriba. Significa que al llamar a save() en un objeto con una identificación predefinida se actualizará el registro de la base de datos correspondiente en lugar de insertar uno nuevo, y también se explica por qué save() no se llama create() .


Usando spring-data-jpa save (), estaba teniendo el mismo problema que @DtechNet. Quiero decir que cada save () creaba un nuevo objeto en lugar de una actualización. Para resolver esto, tuve que agregar la "versión" archivada a la entidad y la tabla relacionada.