我想为Hibernate Entity实现 Null Object pattern 。
假设我们Person
实体有Address
字段。在一种情况下,必须在其他地方定义人员地址,可能无法定义。
@Entity
class Person {
String name;
@ManyToOne(targetEntity = Address.class)
IAddress address;
public Person(String name, IAddress address) {
this.name = name;
this.address = address;
}
}
interface IAddress {
String getCity();
String getStreet();
}
@Entity
class Address implements IAddress {
@Id
private Integer id;
private String city;
private String street;
public Address(String city, String street) {
this.city = city;
this.street = street;
}
@Override
public String getCity() {
return city;
}
@Override
public String getStreet() {
return street;
}
}
class NullObjectAddress implements IAddress {
@Override
public String getCity() {
return "London";
}
@Override
public String getStreet() {
return "Baker street";
}
}
我尝试保存人
Person per1 = new Person("Jhon Doe", new Address("Huge village", "main street"));
personRepository.save(per1); //that`s ok
Person per2 = new Person("Jhon Doe", new NullObjectAddress());
personRepository.save(per2); //throws exception
例外是:
org.springframework.orm.jpa.JpaSystemException:通过反射持久属性访问字段[private Address.id]时出错[Person#id]:NullObjectAddress @ 3638120f;嵌套异常是org.hibernate.property.access.spi.PropertyAccessException:通过反射持久属性访问字段[private java.lang.Int Person.id]时出错[Person#id]:NullObjectAddress @ 3638120f
答案 0 :(得分:1)
一种简单的方法是使用null
作为字段值并在getter和setter中处理null对象:
@Entity
class Person {
@ManyToOne(targetEntity = Address.class)
IAddress address;
public Person(String name, IAddress address) {
this.name = name;
setAddress(address);
}
public IAddress getAddress() {
return address == null ? NullObjectAddress.INSTANCE : address;
}
public void setAddress(IAddress address) {
this.address = address instanceof NullObjectAddress ? null : address;
}
}
但是,您仍然需要在JPQL / HQL查询中将其视为可空,例如:您需要使用address is (not) null
而不是address = :address
,参数:address
的值为NullObjectAddress
个实例。