【问题标题】:Property population via `wither` methods通过 `wither` 方法填充属性
【发布时间】:2019-01-15 10:24:09
【问题描述】:

Property Population 在使用不可变对象时无法按预期工作。

我正在尝试遵循spring-data-couchbase-3.1.4.RELEASE reference docsProperty Population 部分,这表明我可以使用适当的@wither 方法传入一个不可变实体来设置id。但是,当我尝试它时,返回的实体仍然具有 ID 的 null 值。

com/example/demospringdatacouchbaseapp/model/Car.java

import static org.springframework.data.couchbase.core.mapping.id.GenerationStrategy.USE_ATTRIBUTES;
import org.springframework.data.couchbase.core.mapping.Document;
import org.springframework.data.couchbase.core.mapping.id.GeneratedValue;
import org.springframework.data.couchbase.core.mapping.id.IdAttribute;
import com.couchbase.client.java.repository.annotation.Field;
import com.couchbase.client.java.repository.annotation.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Value;
import lombok.experimental.Wither;

@Value
@AllArgsConstructor
@Builder(toBuilder=true)
@Document
public class Car {

  public static final String ID_DELIMITER = ".";

  @Id
  @GeneratedValue(strategy = USE_ATTRIBUTES, delimiter = ID_DELIMITER)
  @Wither
  String id;

  @Field
  @IdAttribute(order=0)
  String manufacturer;

  @Field
  @IdAttribute(order=1)
  String model;

  @Field
  @IdAttribute(order=2)
  String spec;

  @Field
  String colour;

}

com/example/demospringdatacouchbaseapp/repository/CarRepository.java

import java.util.Collection;
import org.springframework.data.couchbase.repository.CouchbaseRepository;
import com.example.demospringdatacouchbaseapp.model.Car;

public interface CarRepository extends CouchbaseRepository<Car, String> {

  Collection<Car> findByColour(String colour);

}

Create simple car test

  @Test
  public void createSingCarTest() {

    /*
     * Given
     */

    Car givenCar = createMadWeeClio();

    /*
     * When
     */

    Car persistedCar = repository.save(givenCar);

    /*
     * Then
     */

    assertThat(persistedCar).isEqualTo(givenCar.withId(getExpectedId(givenCar)));

  }

  ...

  private String getExpectedId(Car givenCar) {
    return givenCar.getManufacturer() + Car.ID_DELIMITER + givenCar.getModel() + Car.ID_DELIMITER
        + givenCar.getSpec();
  }

  private Car withExpectedId(Car car) {
    return car.withId(getExpectedId(car));
  }

  private Car createMadWeeClio() {
    return Car.builder().manufacturer("RenaultSport").model("Clio").spec("200 Cup").colour("white")
        .build();
  }

  private Car createMadMeg() {
    return Car.builder().manufacturer("RenaultSport").model("Megane").spec("R.S Trophy")
        .colour("Yellow").build();
  }

我预计 CouchbaseRepository::save 操作会返回我的不可变实体对象的新实例,其中填充了自动生成的 ID 属性。但是,在我的测试中它返回为 null

传入可变实体会导致 id 字段按预期设置。我还可以看到在 couchbase 中填充了 ID 字段。

【问题讨论】:

    标签: couchbase immutability lombok spring-data-couchbase


    【解决方案1】:

    我认为问题在于 save 操作没有创建您的 Car 对象的新实例 - 而是会尝试将 id 设置到对象上(但不能因为它不可变)。

    @Value Lombok 注释导致的方法看起来像

    Car withId(String id) {
        return new Car(id, this.model, this.spec, this.colour);
    }
    

    但是当你save你的对象时这个方法不会被调用。

    当您从数据库中检索对象时,会调用withId 方法。因此,如果您从数据库中返回所有对象(或使用其他一些条件(例如模型)搜索它),您会发现它们实际上具有带值的 id 属性。文档在这里介绍了这一点:

    https://docs.spring.io/spring-data/couchbase/docs/3.1.4.RELEASE/reference/html/#mapping.property-population

    【讨论】:

    • 感谢@robjwilkins 的回复。正是文档的那一部分让我相信 spring-data-couchbase 将在从 save 方法返回之前使用 wither 方法创建不可变对象的新实例。特别是声明的行: > 如果属性是不可变的,但公开了一个 wither 方法(见下文),我们使用 wither 创建一个具有新属性值的新实体实例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多