2012-08-09 34 views
83

Bueno, la pregunta casi dice todo. Usando JPARepository ¿cómo actualizo una entidad?¿Cómo actualizo una entidad usando spring-data-jpa?

JPARepository tiene solo un método de guardar, que no me dice si es crear o actualizar realmente. Por ejemplo, insertar un objeto simple al usuario de base de datos, que tiene tres campos: nombre y apellidos y 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 "Guardar", que en este momento es una inserción 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 está bien. Ahora quiero actualizar a este usuario, digamos cambiar su edad. Bien, podría usar 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!

+1

¿Estás seguro de que el ID se reescribe cuando se guarda un objeto existente en la base de datos ?? Nunca tuve esto en mi proyecto tbh –

+0

@ByronVoorbach yup tienes razón, acabo de probar esto. actualice la pregunta también, thx – Eugene

+1

Hola amigo, puedes mirar este enlace http://stackoverflow.com/questions/24420572/update-or-saveorupdate-in-crudrespository-is- there-any-options-available puedes ser un enfoque como saveOrUpdate() – ibrahimKiraz

Respuesta

107

La identidad de las entidades se define por sus claves principales. Como firstname y lastname no son partes de la clave principal, no puede indicarle a JPA que trate User s con los mismos firstname sy lastname como iguales si tienen userId s diferentes.

lo tanto, si desea actualizar un User identificado por su firstname y lastname, es necesario encontrar que User por una consulta, y luego cambiar campos correspondientes del objeto encontrado tu. 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.

EDIT:

tal vez debería elaborar sobre la semántica general de la APP. Hay dos enfoques principales para el diseño de las API de persistencia:

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

  • Unidad de enfoque de trabajo. En este caso, tiene un conjunto de objetos administrado por la biblioteca de persistencia. Todos los cambios que realice 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 necesite insertar un nuevo registro en la base de datos, haga el objeto correspondiente administrado. Los objetos gestionados se identifican por sus claves principales, de modo que si crea un objeto con clave primaria predefinida administrada, 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 administre como se describe arriba. Significa que llamar al save() en un objeto con una identificación predefinida actualizará el registro de la base de datos correspondiente en lugar de insertar uno nuevo, y también explica por qué save() no se llama create().

+0

bueno, sí, creo que sé esto. Me refería estrictamente a spring-data-jpa. Tengo dos problemas con esta respuesta ahora: 1) se supone que los valores comerciales no son parte de la clave primaria, eso es algo conocido, ¿no? Por lo tanto, tener el primer nombre y el apellido como clave principal no es bueno. Y 2) ¿Por qué este método no se llama crear, sino que se guarda en spring-data-jpa? – Eugene

+0

@Eugene: actualizado. – axtavt

+0

"guardar() en Spring Data JPA está respaldado por merge() en JPA simple" ¿realmente miró el código? Acabo de hacerlo, y tanto las copias de seguridad persisten como las de fusión. Persistirá o se actualizará en función de la presencia de la identificación (clave principal). Esto, creo, debería documentarse en el método guardar. Así que guardar es en realidad fusionarse o persistir. – Eugene

52

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

Para actualizar una entidad mediante la consulta a continuación, el ahorro no es eficiente porque requiere dos consultas y, posiblemente, la consulta puede ser bastante caro, ya que puede unirse a otras tablas y cargar cualquier colección que tenga fetchType=FetchType.EAGER

Spring-data-jpa soporta la operación de actualización.
Debe definir el método en la interfaz del repositorio. Y lo anotó 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 la definición de consulta personalizada y @Modifying es por decir spring-data-jpa que esta consulta es una operación de actualización y requiere executeUpdate() no executeQuery().

+0

hey its not working! – bks4line

+2

Asegúrese de ejecutarlo en la transacción – hussachai

+1

¡Hola! Gracias estoy usando data beans de primavera. Por lo tanto, se encargará automáticamente de mi actualización. S save (entidad S); se ocupa automáticamente de la actualización. ¡No tuve que usar tu método! ¡Gracias de todos modos! – bks4line

4

Uso de 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.

1

Así es como he resuelto el problema:

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