我正在将 Spring Boot 与 Spring Data 和 H2 in-memory db 一起使用,并想尝试在任何地方使用值对象而不是字符串,我发现了这个简洁的库:AutoValue来创建值对象。所以这是我的实体:
@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;
}
}
这是其中一个值对象(由于 AutoValue,它们都很相似):
@AutoValue
abstract class State {
static State create(String stateName) {
return new AutoValue_State(stateName);
}
abstract String stateName();
}
我该如何解决?
EDIT1:这是 AddressTest 确认 AutoValue 实际上创建字段并且工作正常:
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);
}
编辑2:状态为值对象:
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 + '\'' +
'}';
}
}