Columns for Value Objects in entities are not crea

2019-08-01 05:07发布

问题:

I'm using Spring Boot with Spring Data and H2 in-memory db and wanted to try using Value Objects instead of Strings everywhere and I found this neat library: AutoValue to create Value Objects. So here is my entity:

@Entity
@Access(AccessType.FIELD) // so I can avoid using setters for fields that won't change
class Address {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long addressId;

  @Embedded private State state;
  @Embedded private ZipCode zipCode;
  @Embedded private City city;
  @Embedded private Street street;

  // many customers might live at the same address
  @OneToMany(mappedBy = "address")
  private final Set<Customer> customers = new HashSet<>();

  // jpa requirement
  public Address() {
  }

  Address(State state, ZipCode zipCode, City city, Street street) {
    this.state = state;
    this.zipCode = zipCode;
    this.city = city;
    this.street = street;
  }

  public Long getAddressId() {
    return addressId;
  }

  public State getState() {
    return state;
  }

  public ZipCode getZipCode() {
    return zipCode;
  }

  public City getCity() {
    return city;
  }

  public Street getStreet() {
    return street;
  }

  public Set<Customer> getCustomers() {
    return customers;
  }

}

And here is one of the Value Objects (they are all similiar thanks to AutoValue):

@AutoValue
abstract class State {

  static State create(String stateName) {
    return new AutoValue_State(stateName);
  }

  abstract String stateName();
}

And when I check my database there are no Columns for Object Values:

How can I fix that?

EDIT1: Here is AddressTest confirming that AutoValue actually creates fields and works ok:

  public class AddressTest {

    private static final String ANY_STATE = "ANY STATE";
  private static final String ANY_ZIP_CODE = "ANY ZIP CODE";
  private static final String ANY_CITY = "ANY CITY";
  private static final String ANY_STREET = "ANY STREET";

  @Test
  public void shouldConstructValidAddress() {
    // given
    State anyState = State.create(ANY_STATE);
    ZipCode anyZipCode = ZipCode.create(ANY_ZIP_CODE);
    City anyCity = City.create(ANY_CITY);
    Street anyStreet = Street.create(ANY_STREET);

    // when
    Address address = new Address(State.create(ANY_STATE), ZipCode.create(ANY_ZIP_CODE),
        City.create(ANY_CITY), Street.create(ANY_STREET));

    // then
    assertThat(address.getState()).isEqualTo(anyState);
    assertThat(address.getZipCode()).isEqualTo(anyZipCode);
    assertThat(address.getCity()).isEqualTo(anyCity);
    assertThat(address.getStreet()).isEqualTo(anyStreet);
  }

EDIT 2: State as value object:

    final class State {

  private final String stateName;

  State(String stateName) {
    this.stateName = stateName;
  }

  public String getStateName() {
    return stateName;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    State state = (State) o;
    return stateName != null ? stateName.equals(state.stateName) : state.stateName == null;
  }

  @Override
  public int hashCode() {
    return stateName != null ? stateName.hashCode() : 0;
  }

  @Override
  public String toString() {
    return "State{" +
        "stateName='" + stateName + '\'' +
        '}';
  }
}