[英]Update an immutable object with Lombok in Java?
I have a domain class Person
annotated with Lombok @Value
thus marking it as immutable, having has 3 fields.我有一个域 class
Person
用 Lombok @Value
注释,因此将其标记为不可变,有 3 个字段。
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.如果确实存在,我需要从数据库中获取
Person
object 并更新money
字段。
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.我可能需要在我的
Person
class 中创建一个updatePerson()
但不知道该怎么做。 Or do I need to do something else?还是我需要做其他事情?
Person.java
: Person.java
:
@Value
@Builder
public class Person {
private final UUID id;
private final String job;
private final BigDecimal money;
}
I am using Java 15.我正在使用 Java 15。
You can also use another feature of lombok, which doesn't require you to use a builder.您还可以使用 lombok 的另一个功能,它不需要您使用构建器。 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.它被称为
@With
并且使用此注释将创建不可变的设置器,这意味着设置器返回一个新的 object ,除了您想要更改的属性之外,它具有旧的属性。
@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.一般来说,我不确定使 object 不可变是否真的是个好主意。 Every variable except UUID seems like it could change in the future.
除了 UUID 之外的每个变量似乎都可能在未来发生变化。
@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:在这种情况下,您可以使用
Builder
模式:
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:您可以创建一个
copyWith()
方法:
public class Person {
...
public Person copyWith(BigDecimal money) {
return new Person(this.id, this.job, money);
}
}
The class is immutable; class 是不可变的; you can never change the values of an instance of that class.
您永远无法更改该 class 实例的值。
Instead, you must create a new instance of the class.相反,您必须创建 class 的新实例。
Do not write a builder;不要写生成器; you are already using Lombok, just use the
@Builder
annotation and Lombok will create a builder for you.您已经在使用 Lombok,只需使用
@Builder
注释,Lombok 就会为您创建一个构建器。
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.您必须创建 class 的新实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.