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ę!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ł User
S z tymi samymi firstname
s I lastname
s jako równe, jeśli mają różne userId
S.
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, lubupdate
, 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()
.
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()
.
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.
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);
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);
}
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