2016-02-12 11 views
9

Mój kontrolerJak zaktualizować tylko atrybuty, które zostały zmienione - Spring MVC

@RequestMapping(value = "/user/{id}", method = RequestMethod.GET) 
public String updateUserById(@PathVariable("id") Long id, Model model) { 
    User user = userRepository.findOne(id); 
    model.addAttribute(user); 
    return "admin/editUser"; 
} 

@RequestMapping(value = "/user/{id}", method = RequestMethod.POST) 
@ResponseBody 
public String updateUserById(@PathVariable("id") Long id, @ModelAttribute User user) { 
    userRepository.updateUser(id, user); // with a try catch 
} 

DAO

@Override 
public void updateUser(Long id, User user) { 
    User userDB = userRepository.findOne(id); 
    userDB.setFirstName(user.getFirstName()); 
    userDB.setLastName(user.getLastName()); 
    userDB.setEmail(user.getEmail()); 
    userDB.setUsername(user.getUsername()); 
    userRepository.save(userDB); 
} 

Ta metoda działa, ale jest to dość brzydki dla mnie. Powiedzmy, że użytkownik właśnie zmienił pole pierwszego imienia w widoku, w jaki sposób mogę zaadaptować mój kod, aby wywoływał tylko funkcję ustawiania imienia?

Coś jak wzorzec Obserwatora do pola powiadomień, które uległy zmianie?

+0

Użycie hibernacji? – Musaddique

+0

Tak, używam hibernacji, spring-boot-starter-data-jpa, aby być bardziej precyzyjnym – melkir

+0

zobacz moją odpowiedź poniżej użyj dynamicUpdate = true. zaktualizuje tylko zmienione wartości. – Musaddique

Odpowiedz

3

Przypuszczam, że Twój kod działa tak:

Użytkownik chce zmienić niektóre dane swojego user entity. W interfejsie użytkownika widać już wszystkie jego wpisy z tabeli użytkownika w DB, takie jak imię, nazwisko i tak dalej.

Na przykład użytkownik zmienił swoje imię i kliknął przycisk zapisu. Twój kontroler otrzymuje jednostkę użytkownika zawierającą user.id, nowe imię i wszystkie stare ustawione wartości. Jeśli twój kod działa w ten sposób, możesz łatwo uzyskać jednostkę użytkownika. Nie ma potrzeby pobierania użytkownika z bazy danych.

Więc po prostu to zrób tak:

@Override 
public void updateUser(User user) { 
    userRepository.save(user); 
} 

Repository zna identyfikator jednostki użytkownika i po prostu zaktualizować kompletną całość.

I z tego powodu nie masz Id w swojej jednostce użytkownika użyć Id od kontrolera tak:

@Override 
public void updateUser(User user, Long Id) { 
    user.setId(Id); 
    userRepository.save(user); 
} 
+0

Dziękuję za wyjaśnienia! – melkir

+0

To nie odpowiada na pytanie. Pytanie brzmi: "Jak zaktualizować tylko te atrybuty, które uległy zmianie". Odpowiedź nadal aktualizuje atrybuty wewnątrz userRepository.save (...). po prostu nie robi zestawów, ale za oknem pojawia się zestaw do bazy danych. Przykład: user.firstName = 'lolo', użytkownik chce zmienić user.lastName = 'koko'. ale @trudy przechwytuje to i zmienia także imię. Aktualizacja zmieni się zarówno – lolo

+0

@lolo Może to nie jest odpowiedź na pytanie 100%, ale to było właśnie rozwiązanie, którego szukał. Ponieważ nie chce "brzydkiej" metody "updateUser". Więc nie wiem, czy ostateczne uzasadnienie jest uzasadnione. – Patrick

1

jeśli używasz hibernacji to nie jest jeden atrybut w hibernacji dynamicUpdate = true która zaktualizuje tylko zaktualizowane pola w dB

jak poniżej kod

@Entity 
@Table(name = "User") 
@org.hibernate.annotations.Entity(
     dynamicUpdate = true 
) 
public class User 

dla hibenrate 4 + wykorzystywać te

@DynamicInsert(true) 
@DynamicUpdate(true) 
+0

Adnotacje to wszystko, czego potrzebuję? Pytam o to, ponieważ moja metoda updateUser wciąż ustawia wszystkie pola. Zgadzam się jednak, że zmniejszy to liczbę zapytań do bazy danych dla metody ".save()". – melkir

+0

Nie. Nie można ustawić tylko zaktualizowanych danych. ponieważ użytkownik powinien mieć wszystkie dane. ponieważ w końcu będzie aktualizowany w bazie danych, więc hibernacja potrzebuje wszystkich danych inaczej hibernacja zaktualizuje null, jeśli użytkownik nie ma wartości atrybutu .. – Musaddique

-1

Załóżmy jest to Twoja użytkownika.

@Entity 
public class User{ 
    String userName; 
} 

Następnie na stronie jsp można zrobić coś jak poniżej.

<input type = "text" name = "userName" value = "${userName}" data-changed = "false" class="form_elem"/> 

<script> 
    $(".form_elem").change(function(){ 
     $(this).data("changed", true); 
    }); 

    function submit(){ 
     $(".form_elem").each(function(){ 
      if($(this).data("changed") == false){ 
       $(this).val(""); 
      } 
     }); 
     //Do submit here 
    } 
</script> 

I znowu w dao, które można umieścić na pustym czeku

@Override 
public void updateUser(Long id, User user) { 
    User userDB = userRepository.findOne(id); 
    if(user.getFirstName() != null){ 
     userDB.setFirstName(user.getFirstName()); 
    } 
} 

Prosimy pamiętać, kod ten nie został przetestowany i czeka downvotes.

Powiązane problemy