如何使用Hibernate保存具有相关Null对象的实体

时间:2017-04-04 13:03:53

标签: java spring hibernate jpa spring-data

我想为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

1 个答案:

答案 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个实例。