我有一个由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)
是什么原因导致数据库中的实体读取时出现这种奇怪的异常?我可以理解并排除写入时出现的验证错误。但是读取错误完全令人困惑。