0

Here is an example from the official documentation (You need to scroll down a little)

class Person {

  private final @Id Long id;                                                
  private final String firstname, lastname;                                 
  private final LocalDate birthday;
  private final int age; 

  private String comment;                                                   
  private @AccessType(Type.PROPERTY) String remarks;                        

  static Person of(String firstname, String lastname, LocalDate birthday) { 

    return new Person(null, firstname, lastname, birthday,
      Period.between(birthday, LocalDate.now()).getYears());
  }

  Person(Long id, String firstname, String lastname, LocalDate birthday, int age) { 

    this.id = id;
    this.firstname = firstname;
    this.lastname = lastname;
    this.birthday = birthday;
    this.age = age;
  }

  Person withId(Long id) {                                                  
    return new Person(id, this.firstname, this.lastname, this.birthday);
  }

  void setRemarks(String remarks) {                                         
    this.remarks = remarks;
  }
}

I have a few questions about this.

  1. Person withId(Long id) Does the referenced construction function not exist in the example?

  2. Person withId(Long id) There is a description in the official documentation :"The same pattern is usually applied for other properties that are store managed but might have to be changed for persistence operations". Can I understand it this way: After successfully saving the instance, WithOutIdPerson can be used for other field changes and saved again, and SavedPerson can be used for other upper level operations?

  3. Why is the last step of the factory of () called in the example??

Thank you~

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
Hyman Yang
  • 33
  • 6
  • What is `SavedPerson` you are referring to in (2)? What is the example you are referring to in (3)? – Jens Schauder Dec 10 '19 at 06:59
  • (2) ```SavedPerson``` is an entity that has been saved to the repository and carries an ID identifier. ```WithOutIdPerson```Is a new entity that is not saved to the repository and has no ID identifier. (3) The example is **Example.56** in the official document labeled **6th** small step of color. The question I want to ask is why the last step calls of() factory method. thank you~ – Hyman Yang Dec 10 '19 at 11:24

1 Answers1

1

Question 1

Person withId(Long id) Does the referenced construction function not exist in the example?

That is probably a bug in the documentation, it should look like this:

Person withId(Long id) {                                                  
    return new Person(id, this.firstname, this.lastname, this.birthday, this.age);
}

Question 2

After successfully saving the instance, WithOutIdPerson can be used for other field changes and saved again, and SavedPerson can be used for other upper level operations?

If I understand you correct you are wondering if this would work:

Person p = Person.of( "Peter", "Parker", someDate);
Person saved  = personRepository.save(p);
Person savedAgain = personRepository.save(p);

If the id attribute of Person is set by the database and it is an immutable attribute (it has a wither as given in the example) then p and saved (and savedAgain) are distinct entities and the two save operations result in two rows being stored in the database and saved and savedAgain having distinct ids and p has still id equal to null.

Question 3

Why is the last step of the factory of() called in the example?

Actually, of() isn't called at all in the example code. Why a factory method is recommended over overloaded constructors is explained in note number (6) of the code:

The class exposes a factory method and a constructor for object creation. The core idea here is to use factory methods instead of additional constructors to avoid the need for constructor disambiguation through @PersistenceConstructor. Instead, defaulting of properties is handled within the factory method.

Without the factory you would have two constructors and would need to use @PersistenceConstructor on one in order to tell Spring Data which one to use for instance creation.

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
  • Use ```personRepository.findById(ID id)``` to return a ```Person``` instance, so will the first call the ```of()``` factory method to build the instance? thanks~ – Hyman Yang Dec 10 '19 at 13:53