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

Resuelto Eugene asked hace 12 años • 17 respuestas

Bueno, la pregunta lo dice prácticamente todo. Usando JPARepository, ¿cómo actualizo una entidad?

JPARepository solo tiene un método para guardar , que no me dice si realmente se está creando o actualizando. Por ejemplo, inserto un Objeto simple en el Usuario de la base de datos, que tiene tres campos : y firstname:lastnameage

 @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;
  }
}

Luego simplemente llamo save(), que en este punto es en realidad una inserción en la base de datos:

 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);

Hasta ahora, todo bien. Ahora quiero actualizar este usuario, digamos cambiar su edad. Para ello podría utilizar una Consulta, ya sea QueryDSL o NamedQuery, lo que sea. Pero, considerando que solo quiero usar spring-data-jpa y JPARepository, ¿cómo le digo que en lugar de insertar quiero hacer una actualización?

Específicamente, ¿cómo le digo a spring-data-jpa que los usuarios con el mismo nombre de usuario y nombre son en realidad IGUAL y que se supone que la entidad existente debe actualizarse? Anular iguales no resolvió este problema.

Eugene avatar Aug 09 '12 17:08 Eugene
Aceptado

La identidad de las entidades está definida por sus claves primarias. Dado que firstnamey lastnameno son partes de la clave principal, no puede decirle a JPA que trate Userlos mensajes con los mismos firstnamesys lastnamecomo iguales si tienen userIds diferentes.

Entonces, si desea actualizar un objeto Useridentificado por su firstnamey lastname, debe encontrarlo Usermediante una consulta y luego cambiar los campos apropiados del objeto que encontró. Estos cambios se descargarán automáticamente en la base de datos al final de la transacción, por lo que no necesita hacer nada para guardar estos cambios explícitamente.

EDITAR:

Quizás debería dar más detalles sobre la semántica general de JPA. Hay dos enfoques principales para el diseño de API de persistencia:

  • enfoque de inserción/actualización . Cuando necesite modificar la base de datos, debe llamar explícitamente a los métodos de la API de persistencia: llama insertpara insertar un objeto o updatepara guardar el nuevo estado del objeto en la base de datos.

  • Enfoque de unidad de trabajo . En este caso tienes un conjunto de objetos administrados por la biblioteca de persistencia. Todos los cambios que realice en estos objetos se descargarán automáticamente en la base de datos al final de la Unidad de trabajo (es decir, al final de la transacción actual en un caso típico). Cuando necesite insertar un nuevo registro en la base de datos, haga que se administre el objeto correspondiente . Los objetos administrados se identifican por sus claves principales, de modo que si crea un objeto con una clave principal predefinida administrada , se asociará con el registro de la base de datos con la misma identificación y el estado de este objeto se propagará a ese registro automáticamente.

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

axtavt avatar Aug 09 '2012 10:08 axtavt

Dado que la respuesta de @axtavt se centra en JPAnospring-data-jpa

Actualizar una entidad mediante una consulta y luego 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-jpaadmite la operación de actualización.
Debe definir el método en la interfaz del Repositorio y anotarlo con @Queryy @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);

@Queryes para definir una consulta personalizada y @Modifyinges para indicar spring-data-jpaque esta consulta es una operación de actualización y que executeUpdate()no requiere executeQuery().

Puede especificar el tipo de devolución como int, teniendo la cantidad de registros que se actualizan.


Nota : Ejecute este código en una Transacción .

hussachai avatar Jun 30 '2015 22:06 hussachai

Como ya han mencionado otros, el save()mismo contiene operaciones de creación y actualización.

Solo quiero agregar un suplemento sobre lo que hay detrás del save()método.

En primer lugar, veamos la jerarquía de extensión/implementación de CrudRepository<T,ID>, ingrese la descripción de la imagen aquí

Ok, verifiquemos la save()implementación en SimpleJpaRepository<T, ID>,

@Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

Como puede ver, primero verificará si la ID existe o no, si la entidad ya está allí, solo se actualizará por merge(entity)método y, en caso contrario, se insertará un nuevo registro por persist(entity)método.

Eugene avatar Dec 11 '2018 03:12 Eugene

El método de datos de primavera save()le ayudará a realizar ambas cosas: agregar un nuevo elemento y actualizar un elemento existente.

Simplemente llama save()y disfruta de la vida :))

Amir Mhp avatar Jun 03 '2019 10:06 Amir Mhp