简体   繁体   English

用 Java 中的 Lombok 更新不可变的 object?

[英]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 之外的每个变量似乎都可能在未来发生变化。

Using Lombok :使用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:在这种情况下,您可以使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM