I have a domain class Person
annotated with Lombok @Value
thus marking it as immutable, having has 3 fields.
In my service layer, I am making a call to the repository to check if the the person exists or not.
If it does exist, I need to take the Person
object from the database and update the money
field.
Since it is immutable, this cannot be done. I was reading some articles and came across that this can be done using builder pattern.
I will probably need to create a updatePerson()
in my Person
class but not sure how to do it. Or do I need to do something else ?
Person.java
:
@Value
@Builder
public class Person {
private final UUID id;
private final String job;
private final BigDecimal money;
}
I am using Java 15.
CodePudding user response:
You can also use another feature of lombok, which doesn't require you to use a builder. It's called @With
and using this annotation will create immutable setters, meaning that the setter returns a new object with the attributes of the old one except for the attribute that you wanted to change.
@Value
public class Person {
/* You don't need to write final if you are using @Value. Lombok will make the variables final for you.
In theory you do not even need to write private,
because Lombok makes variables private by default instead of package private.*/
private UUID id;
private String job;
@With
private BigDecimal money;
}
Person newPerson = person.withMoney(new Big decimal("10"));
In general I'm not sure if making the object immutable is really a good idea. Every variable except UUID seems like it could change in the future.
CodePudding user response:
Using Lombok
:
@Value
@Builder(toBuilder = true)
public class Person {
private final UUID id;
private final String job;
private final BigDecimal money;
}
personObjectFromDatabase.toBuilder().setMoney(...).build()
OR
You can use the Builder
pattern in that case:
public class Person {
private final UUID id;
private final String job;
private final BigDecimal money;
public static class PersonBuilder {
private UUID id;
private String job;
private BigDecimal money;
public PersonBuilder(Person defaultPerson){
this.id = defaultPerson.getId();
this.job = defaultPerson.getJob();
this.money = defaultPerson.getMoney();
}
public PersonBuilder withId(UUID id) {
this.id = UUID;
return this;
}
public PersonBuilder withJob(String job) {
this.job = job;
return this;
}
public PersonBuilder withMoney(BigDecimal money) {
this.money = money;
return this;
}
public Person build() {
return new Person(id, job, money);
}
}
}
Use this builder like the following:
Person person = new Person.PersonBuilder(personObjectFromDatabase)
.withMoney(...)
.build();
OR
You can just create a copyWith()
method:
public class Person {
...
public Person copyWith(BigDecimal money) {
return new Person(this.id, this.job, money);
}
}
CodePudding user response:
The class is immutable; you can never change the values of an instance of that class.
Instead, you must create a new instance of the class.
Do not write a builder;
you are already using Lombok,
just use the
@Builder
annotation and Lombok will create a builder for you.
Edit: You are using the builder annotation. The soltion you are looking for appears to be this:
you must create a new instance of the class.