Search code examples
javaobjectassign

Is there a "clean" way to replace all attribute values of an object in Java with values from another object of the same type?


A quick explanation first. Let's say we have a method which takes a Student object and an Id as attributes and updates student with given Id with information contained in passed object. So far the easiest solution I've found is as follows:

  1. We search our repository looking for student that we want to update.
  2. Should we find it we then use setters in order to set the new values.
    public void updateStudent(Long id, Student newStudent) {
        Student studentToBeUpdated = studentRepo
                .findStudentById(id)
                .orElseThrow(() ->
                        new UserNotFoundException("Student with id " + id + " was not found"));
        studentToBeUpdated.setFirstName(newStudent.getFirstName());
        studentToBeUpdated.setLastName(newStudent.getLastName());
        studentToBeUpdated.setEmail(newStudent.getEmail());
    }

So, job well done, we can go home, right? Well, now lets hypothetically say our project grew a lot and we have to add 20 more attributes to our Student class. Suddenly we have to update this method manually as well as any other method that does a similar thing. Not good. Also we just created some boilerplate code which is bad.

What I'm really looking for is a way to do all this without thinking about how many attributes our Student class has or what these attributes are, even if they are themselves enums, arrays or even other objects. What I'd like is something like this:

studentToBeUpdated.replace(newStudent);

Is this possible or is it just my wishful thinking? The next best thing would probably be creating a method that would do all this by myself but it's still not a perfect solution because it would also have to be edited every time class attributes change.


Solution

  • For mapping between two Java objects you can use something like MapStruct or you can write your own mappers, essentially extracting the boilerplate code into a separate class/service.

    If you decide to create your own mapper, you can use reflection or you can do it by using setter methods or builder pattern (also Lombok's @Builder can help avoiding to write the boilerplate for builder pattern).

    ...now lets hypothetically say our project grew a lot and we have to add 20 more attributes to our Student class. Suddenly we have to update this method manually as well as any other method that does a similar thing.

    Certainly your entities and consequently your databases can grow in the number of fields/columns, but this in general should not be as big of a deal if you extract all the mappings and transformations in different classes. In most of the cases you will have to update a subset of the fields anyway.