Jak zaktualizować podmiot za pomocą spring-data-jpa?

Pytanie mówi wszystko. Korzystanie z JPARepository jak zaktualizować podmiot?

JPARepository ma tylko metodę save , która nie mówi mi, czy jest to create czy update. Na przykład, wstawiam prosty obiekt do użytkownika bazy danych, który ma trzy pola: firstname i lastname oraz age:

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

Potem po prostu "zapisuję", co w tym momencie jest wkładką faktycznie:

 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 wszystko w porządku. Teraz chcę zaktualizować tego użytkownika, powiedzieć Zmień w jego wieku. Przydałoby mi się zapytanie do tego QueryDSL lub NamedQuery, cokolwiek. Ale biorąc pod uwagę, że chcę tylko użyć spring-data-jpa i jparepository, Jak mogę powiedzieć, że zamiast wstawki chcę zrobić aktualizację?

W szczególności jak mogę powiedzieć spring-data-jpa, że użytkownicy, którzy mają tę samą nazwę użytkownika i imię są w rzeczywistości równi i że ma to na celu aktualizację encji. / Align = "left" /

Dziękuję!
Author: Eugene, 2012-08-09

5 answers

Tożsamość podmiotów jest określona przez ich klucze podstawowe. Ponieważ firstname i lastname nie są częściami klucza głównego, nie można powiedzieć JPA, aby traktował UserS z tymi samymi firstnames I lastnames jako równe, jeśli mają różne userIdS.

Tak więc, jeśli chcesz zaktualizować User zidentyfikowane przez jego firstname i lastname, Musisz znaleźć User za pomocą zapytania, a następnie zmienić odpowiednie pola znalezionego obiektu. Zmiany te zostaną automatycznie przeniesione do bazy danych po zakończeniu transakcji, tak, że nie trzeba robić nic, aby zapisać te zmiany jawnie.

EDIT:

Być może powinienem rozwinąć ogólną semantykę JPA. Istnieją dwa główne podejścia do projektowania API trwałości: [18]}

  • Metoda Insert / update . Jeśli chcesz zmodyfikować bazę danych, powinieneś jawnie wywołać API metody persistence: wywołujesz insert, aby wstawić obiekt, lub update, aby zapisać nowy stan obiektu do baza danych.

  • Podejście Unit of Work . W tym przypadku masz zestaw obiektów zarządzanych przez persistence library. Wszystkie zmiany wprowadzone w tych obiektach zostaną automatycznie załadowane do bazy danych po zakończeniu pracy (tj. po zakończeniu bieżącej transakcji w typowym przypadku). Gdy musisz wstawić nowy rekord do bazy danych, zarządzasz odpowiednim obiektem . zarządzane obiekty są identyfikowane za pomocą kluczy głównych, tak więc, jeśli utworzysz obiekt z predefiniowanym kluczem głównym managed, zostanie on skojarzony z rekordem bazy danych o tym samym id, a stan tego obiektu zostanie automatycznie propagowany do tego rekordu.

JPA podąża za późniejszym podejściem. save() W Spring Data JPA jest wspierane przez merge() w zwykłym JPA, dlatego sprawia, że Twój podmiot zarządza jak opisano powyżej. Oznacza to, że wywołanie save() na obiekcie o predefiniowanym id zaktualizuje odpowiedni rekord bazy danych zamiast wstawiania nowego, a także wyjaśnia, dlaczego {[12] } nie jest wywoływana create().

 129
Author: axtavt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-09 11:43:23

Ponieważ odpowiedź @axtavt skupia się na JPA nie spring-data-jpa

Aby zaktualizować encję poprzez zapytanie, zapisywanie nie jest efektywne, ponieważ wymaga dwóch zapytań i prawdopodobnie zapytanie może być dość kosztowne, ponieważ może dołączyć do innych tabel i załadować wszelkie kolekcje, które mają fetchType=FetchType.EAGER

Spring-data-jpa obsługuje operację aktualizacji.
Metodę należy zdefiniować w interfejsie repozytorium.i dodała do niego @Query i @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 jest do definiowania zapytań niestandardowych i @Modifying jest do powiedzenia spring-data-jpa, że to zapytanie jest operacją aktualizacji i wymaga executeUpdate(), a nie executeQuery().

 70
Author: hussachai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-01 10:43:12

Using spring-data - JPA save(), Miałem ten sam problem co @DtechNet. Chodzi mi o to, że każde save () tworzyło nowy obiekt zamiast update. Aby to rozwiązać, musiałem dodać" version " złożony do encji i powiązanej tabeli.

 6
Author: smile,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-06 18:54:40

Oto jak rozwiązałem problem:

User inbound = ...
User existing = userRepository.findByFirstname(inbound.getFirstname());
if(existing != null) inbound.setId(existing.getId());
userRepository.save(inbound);
 4
Author: Adam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-21 15:40:56

Możesz po prostu użyć tej funkcji z save() JPAfunction, ale obiekt wysłany jako parametr musi zawierać istniejący identyfikator w bazie danych, w przeciwnym razie nie będzie działać, ponieważ save() kiedy wysyłamy obiekt bez id, dodaje bezpośrednio wiersz w bazie danych, ale jeśli wysyłamy obiekt z istniejącym identyfikatorem, zmienia kolumny już znalezione w bazie danych.

public void adduser(Userinfos u) {

User userFromDb = userRepository.findById(u.getid());

//crush the variables of the object found
userFromDb.setFirstname("john"); 
userFromDb.setLastname("dew");
userFromDb.setAge(16);

userRepository.save(userFromDb);
}
 0
Author: Californium,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-30 10:27:43