是什么会导致org.hibernate.engine.internal.NaturalIdXrefDelegate.validateNaturalId(NaturalIdXrefDelegate.java:166)上的NPE?

时间:2018-08-21 15:15:54

标签: java hibernate

我有一个由3个实体组成的Hibernate模型。以下是我认为是其定义相关部分的摘录:

AddressKeyEntity

@Entity
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = {"address", "city", "state", "zip", "apn"}) })
public class AddressKeyEntity implements AddressKey, Serializable {

    private @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) Integer id;

    private @NaturalId String address;

    ... other stuff ...

AddressEntity

@Entity
@Table(indexes={@Index(columnList="latitude,longitude")})
public class AddressEntity implements Address, Serializable {

    private @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) Integer id;

    private @OneToOne(cascade=CascadeType.ALL) AddressKeyEntity addressKey;

    private Double latitude;

    private Double longitude;

    ...  other stuff ...

ListingDetailDso

@SuppressWarnings("serial")
@Entity
@IdClass(ListingDetailPK.class)
@Table(indexes = { @Index(columnList = "SystemID,ctcValidTo,UpdtDate", name = "SystemID"),
        @Index(columnList = "ctcValidTo,Zip,Status,ListPrice,UpdtDate", name = "Current_Zip"),
        @Index(columnList = "ctcValidTo,addressKey_ID,Status,ListPrice", name = "Current_AddressKey") }
)
@JsonInclude(Include.NON_EMPTY)
public class ListingDetailDso implements Serializable {

    @Id
    private Integer SystemID;

    @Id
    private Integer UpdtDate;

    @ManyToOne(cascade=CascadeType.ALL) @JsonIgnore
    private AddressKeyEntity addressKey = new AddressKeyEntity();

    ... other stuff ...

然后,我尝试存储批处理地理编码过程的结果:

public void sync(List<ListingDetailDso> allItems) throws IOException {

    logger.info("pre-processing");

    Map<AddressKeyEntity, AddressEntity> newValues = geoIndex.geocode(allItems);

    logger.info("persisting addresses");
    newValues.forEach((k,v) -> {
        v.setAddressKey(addressDao.merge(v.getAddressKey()));
    });
    addressDao.merge(newValues.values());

    logger.info("persisting items");
    allItems.forEach(item -> item.reset(addressDao.merge(item.getAddressKey())));
    this.persistAll(allItems);
}

在最后的persistAll()步骤中,我必须查询项目列表才能应用一些交叉引用规则:

public List<ListingDetailDso> load(Collection<Integer> idList) {
    return new PredicateQuery() {
        @Override
        protected Predicate predicate() {
            return builder.or(idList.stream()
                    .map(id -> builder.equal(root.get(ListingDetailDso_.SystemID), id))
                    .collect(Collectors.toList()).toArray(new Predicate[0]));
        }
    }.build().getResultList();
}

在这里它失败并显示:

java.lang.NullPointerException
    at org.hibernate.engine.internal.NaturalIdXrefDelegate.validateNaturalId(NaturalIdXrefDelegate.java:166)
    at org.hibernate.engine.internal.NaturalIdXrefDelegate.cacheNaturalIdCrossReference(NaturalIdXrefDelegate.java:73)
    at org.hibernate.engine.internal.StatefulPersistenceContext$1.cacheNaturalIdCrossReferenceFromLoad(StatefulPersistenceContext.java:1731)
    at org.hibernate.engine.internal.StatefulPersistenceContext.getNaturalIdSnapshot(StatefulPersistenceContext.java:347)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.checkNaturalId(DefaultFlushEntityEventListener.java:101)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:191)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:146)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:235)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:94)
    at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44)
    at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1415)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1501)
    at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1538)
    at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1506)
    at org.hibernate.query.Query.getResultList(Query.java:146)
    at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:73)
    at com.ctc.dao.ListingDetailDao.load(ListingDetailDao.java:138)

是什么原因导致数据库中的实体读取时出现这种奇怪的异常?我可以理解并排除写入时出现的验证错误。但是读取错误完全令人困惑。

0 个答案:

没有答案