【发布时间】:2020-11-22 02:03:32
【问题描述】:
我有一个谜题要给你。
我正在制作一个药草商店网络应用程序,这是我的数据库:
- 商店可以有很多产品
- 一个产品可以包含许多草药
这些是我的 JPA 课程:
public class StoreJPA {
...
@OneToMany(mappedBy="storeJpa", cascade = CascadeType.ALL, orphanRemoval=true, fetch=FetchType.EAGER)
private Set<ProductJPA> specialOffers = new HashSet<ProductJPA>();
...
}
public class ProductJPA {
@ManyToOne
@JoinColumn(name="store_id")
private StoreJPA storeJpa;
@OneToMany(mappedBy="productJpa", cascade = CascadeType.ALL, orphanRemoval=true, fetch=FetchType.EAGER)
private Set<ContainsJPA> contains = new HashSet<ContainsJPA>();
...
private Set<HerbJPA> getHerbs(){
return contains.stream().map(h -> h.getHerbJpa()).collect(Collectors.toSet());
}
@Override
public int hashCode(){
long h = 1125899906842597L; // prime
for(ProductHasHerbJPA phh : contains){
h = 31*h + phh.getHerbJpa().getId();
}
return (int)(31*h + storeJpa.getId());
}
@Override
public boolean equals(Object o){
if(o!=null && o instanceof ProductJPA){
if(o==this)
return true;
return ((ProductJPA)o).getStoreJpa().getId()==storeJpa.getId() &&
((ProductJPA)o).getHerbs().equals(getHerbs()) // compare herbs they contain
}
return false;
}
...
}
public class ContainsJPA {
@Id
private Long id;
@ManyToOne
@JoinColumn(name="product_id")
private ProductJPA productJpa;
@ManyToOne
@JoinColumn(name="herb_id")
private HerbJPA herbJpa;
...
@Override
public int hashCode(){
long h = 1125899906842597L + productJpa.getId(); // <-- nullpointer exception
return (int)(31*h + herbJpa.getId());
}
@Override
public boolean equals(Object o){
if( o != null && o instanceof HerbLocaleJPA) {
if(o==this) {
return true;
}
return ((ProductHasHerbJPA)o).getHerbJpa().getId()==herbJpa.getId() &&
((ProductHasHerbJPA)o).getProductJpa().getId()==productJpa.getId();
}
return false;
}
...
}
添加带有草药列表的新产品效果很好。 但是当我运行它并尝试在商店中获取产品时,我得到一个 NullPointerException :
java.lang.NullPointerException 在 com.green.store.entities.ContainsJPA.hashCode(ContainsJPA.java:64) 在 java.util.HashMap.hash(HashMap.java:339) 在 java.util.HashMap.put(HashMap.java:612) 在 java.util.HashSet.add(HashSet.java:220) 在 java.util.AbstractCollection.addAll(AbstractCollection.java:344) 在 org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:327) 在 org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:234) 在 org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:221) 在 org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:194) 在 org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154) 在 org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:249) 在 org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:212) 在 org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:133) 在 org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122) 在 org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86) 在 org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167) 在 org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4087) 在 org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508) 在 org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478) 在 org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219) 在 org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278) 在 org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121) 在 org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89) 在 org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1239) 在 org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1122) 在 org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:672) 在 org.hibernate.type.EntityType.resolve(EntityType.java:457) 在 org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:165) 在 org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:125) 在 org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.performTwoPhaseLoad(AbstractRowReader.java:238) 在 org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:209) 在 org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:133) 在 org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122) 在 org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86) 在 org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167) 在 org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4087) 在 org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508) 在 org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478) 在 org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219) 在 org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:116) 在 org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89) 在 org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1239) 在 org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:1097) ...
ContainsJPA 的 hashCode 函数在获取产品的 id 时会抛出此异常。考虑到数据库中的“包含”表具有此 ID,为什么要这样做? 我无法弄清楚为什么会这样。请帮忙。
【问题讨论】:
标签: java mysql spring rest spring-data-jpa