12

My controller

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

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

This method works but it's pretty ugly for me. Let's say that the user have just changed the firstname field in the view, how can I adapt my code to only call the function to set the firstname ?

Something like the Observer pattern to notify field that have change ?

melkir
  • 405
  • 1
  • 5
  • 22
  • r u using hibernate ? – Musaddique S Feb 12 '16 at 07:49
  • yes i'm using hibernate, spring-boot-starter-data-jpa to be more precise – melkir Feb 12 '16 at 07:54
  • see my below answer use dynamicUpdate=true. it will update only changed values. – Musaddique S Feb 12 '16 at 07:54
  • 1
    Using spring-data-jpa, and having a repository extending CrudRepository, you should simply be able to save your entity with the ID already set, and spring-data will overwrite the entity with the same id. No need to individually set properties of the entity. See Patrick's answer below. – user152468 Feb 12 '16 at 09:56

2 Answers2

3

if you are using hibernate then there is one attribute in hibernate dynamicUpdate = true which will update only updated fields in db

like below code

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

for hibenrate 4 + use these

@DynamicInsert(true)
@DynamicUpdate(true)
Musaddique S
  • 1,539
  • 2
  • 15
  • 36
  • The annotations is all I need ? I'm asking this because my updateUser method is still setting all fields. But I agree that this will reduce database queries for the ".save()" method. – melkir Feb 12 '16 at 07:56
  • No. there is no way to set only updated data. because user should have all data. because finally it is going to update in database so hibernate need all data otherwise hibernate will update null if user doesn't have attribute value.. – Musaddique S Feb 12 '16 at 08:01
1

I suppose that your code works like this:

An user want to change some data of his user entity. Means in frontend you already show him all his entries from the user table of the DB like firstname, lastname and so on.

For example the user changed his firstname and hit the save button. Your controller receive the user entity inclusive the user.id, the new firstname and all the old set values. If your code works like this you can easily save() the user entity. There is no need to fetch the user from the DB first.

So just do it like this:

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

The Repository knows the Id of the user entity and just update the complete entity.

And for the reason you dont have the Id in your user entity use the Id from your controller like this:

@Override
public void updateUser(User user, Long Id) {
    user.setId(Id);
    userRepository.save(user);
}
Patrick
  • 12,336
  • 15
  • 73
  • 115
  • Thank you for your explanations ! – melkir Feb 12 '16 at 21:00
  • 3
    It doesn't answer the question. The question is : "How to update only attributes that have changed ". The answer, still update the attributes inside userRepository.save(...). it just doesn't do sets but behind the hood the set to the data base will occur. Example: user.firstName = 'lolo', the user wants to change user.lastName= 'koko'. but @trudy intercept it and change also the first name. The update will change both – lolo Nov 06 '16 at 09:15
  • @lolo Maybe it does not answer the question of 100% but it was exactly the solution he searched for. Because he does not wanted an "ugly" method of `updateUser `. So dont know if the downvote is justified. – Patrick Nov 06 '16 at 10:26
  • 3
    @Patrick The idea behind the problem its not code convention, its data integrity. – lolo Nov 06 '16 at 14:43