ManyToOne关系中的Jpa ***异常
Posted
技术标签:
【中文标题】ManyToOne关系中的Jpa ***异常【英文标题】:Jpa *** exception in ManyToOne relation 【发布时间】:2021-01-12 18:40:16 【问题描述】:我有部分,我可以在其中包含子部分,在其中我可以有更深层次的部分,甚至更远。实体:
@Data
@Table(name = "section")
@Entity
@NoArgsConstructor
public class Section
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Long id;
@Column private String title;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
private Section parent;
@JsonIgnore
@OneToMany(fetch = FetchType.EAGER, mappedBy = "parent")
private Set<Section> children;
public Section(Long id, String title, Section parent)
this.id = id;
this.title = title;
this.parent = parent;
出于测试目的,我将所有数据保存在 h2 数据库中。存储库类:
@Repository
public interface SectionRepository extends JpaRepository<Section, Long>
List<Section> findAllByParentId(Long parentId);
我在 h2 中有什么:
我只想找到这些没有父级的部分(前两个在 parent_id 列中为空)。我是如何做到的:
Section about = new Section(null, "about", null);
Section production = new Section(null, "production", null);
sectionRepository.save(about);
sectionRepository.save(production);
Section subsectionOne = new Section(null, "subsectionOne", production); // without adding
Section subsectionTwo = new Section(null, "subsectionTwo", production); // these two subsections
sectionRepository.save(subsectionOne); // and saving them to db
sectionRepository.save(subsectionTwo); // I don't receive any error on findAllByParentId(null) method call
sectionRepository.findAllByParentId(null); // action
java.lang.***Error: null
at org.h2.util.ParserUtil.getSaveTokenType(ParserUtil.java:592) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.read(Parser.java:5092) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.readIf(Parser.java:5011) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.readTerm(Parser.java:4306) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.readFactor(Parser.java:3343) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.readSum(Parser.java:3330) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.readConcat(Parser.java:3305) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.readCondition(Parser.java:3108) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.readExpression(Parser.java:3059) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.parseSelectExpressions(Parser.java:2931) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.parseSelect(Parser.java:2952) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.parseQuerySub(Parser.java:2817) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.parseSelectUnion(Parser.java:2649) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.parseQuery(Parser.java:2620) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.parsePrepared(Parser.java:868) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.parse(Parser.java:843) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.parse(Parser.java:815) ~[h2-1.4.200.jar:1.4.200]
at org.h2.command.Parser.prepareCommand(Parser.java:738) ~[h2-1.4.200.jar:1.4.200]
at org.h2.engine.Session.prepareLocal(Session.java:657) ~[h2-1.4.200.jar:1.4.200]
at org.h2.engine.Session.prepareCommand(Session.java:595) ~[h2-1.4.200.jar:1.4.200]
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1235) ~[h2-1.4.200.jar:1.4.200]
at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:76) ~[h2-1.4.200.jar:1.4.200]
at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:352) ~[h2-1.4.200.jar:1.4.200]
at com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:337) ~[HikariCP-3.4.5.jar:na]
at com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java) ~[HikariCP-3.4.5.jar:na]
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:149) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:176) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:151) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.prepareQueryStatement(AbstractLoadPlanBasedLoader.java:198) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeQueryStatement(AbstractLoadPlanBasedLoader.java:162) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:104) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:87) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:710) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:76) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:2163) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:589) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:264) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:458) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at lv.sawex.core.sections.Section.hashCode(Section.java:10) ~[classes/:na]
at lv.sawex.core.sections.Section.hashCode(Section.java:10) ~[classes/:na]
at java.base/java.util.HashMap.hash(HashMap.java:339) ~[na:na]
at java.base/java.util.HashMap.put(HashMap.java:607) ~[na:na]
at java.base/java.util.HashSet.add(HashSet.java:220) ~[na:na]
at java.base/java.util.AbstractCollection.addAll(AbstractCollection.java:352) ~[na:na]
at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:355) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:239) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:224) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:198) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:260) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:211) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:96) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:105) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:87) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:710) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:76) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:2163) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:589) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:264) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:458) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at lv.sawex.core.sections.Section.hashCode(Section.java:10) ~[classes/:na]
at lv.sawex.core.sections.Section.hashCode(Section.java:10) ~[classes/:na]
at java.base/java.util.HashMap.hash(HashMap.java:339) ~[na:na]
at java.base/java.util.HashMap.put(HashMap.java:607) ~[na:na]
at java.base/java.util.HashSet.add(HashSet.java:220) ~[na:na]
at java.base/java.util.AbstractCollection.addAll(AbstractCollection.java:352) ~[na:na]
at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:355) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:239) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:224) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:198) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:260) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:211) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:96) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:105) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:87) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:710) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:76) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:2163) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:589) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:264) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:458) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
at lv.sawex.core.sections.Section.hashCode(Section.java:10) ~[classes/:na]
at lv.sawex.core.sections.Section.hashCode(Section.java:10) ~[classes/:na]
at java.base/java.util.HashMap.hash(HashMap.java:339) ~[na:na]
at java.base/java.util.HashMap.put(HashMap.java:607) ~[na:na]
at java.base/java.util.HashSet.add(HashSet.java:220) ~[na:na]
spring.jpa.show-sql=true
sql结果:最后一个sql查询递归重复。
Hibernate: select section0_.id as id1_1_, section0_.parent_id as parent_i4_1_, section0_.title as title2_1_, section0_.titlelv as titlelv3_1_ from section section0_ left outer join section section1_ on section0_.parent_id=section1_.id where section1_.id is null
Hibernate: select children0_.parent_id as parent_i4_1_0_, children0_.id as id1_1_0_, children0_.id as id1_1_1_, children0_.parent_id as parent_i4_1_1_, children0_.title as title2_1_1_, children0_.titlelv as titlelv3_1_1_ from section children0_ where children0_.parent_id=?
Hibernate: select children0_.parent_id as parent_i4_1_0_, children0_.id as id1_1_0_, children0_.id as id1_1_1_, children0_.parent_id as parent_i4_1_1_, children0_.title as title2_1_1_, children0_.titlelv as titlelv3_1_1_ from section children0_ where children0_.parent_id=?
问题出在哪里?
【问题讨论】:
【参考方案1】:从堆栈跟踪和使用的 Lombok 注释判断,问题可能与递归调用 hashCode()
有关。 Lombok 的@Data
将为equals
和hashCode
方法生成实现,默认情况下,这些实现将使用所有声明的字段,包括parent
和children
。这意味着尝试计算“production”条目的哈希码将触发“subsectionOne”/“subsectionTwo”的计算,通过parent
属性返回“production”。
通过将@EqualsAndHashCode.Exclude
添加到children
字段从hashCode
实现中排除集合应该可以解决问题
【讨论】:
好的,谢谢。但我通过重写equals
和 hashCode
方法来仅检查 id
字段而不是类的所有字段。以上是关于ManyToOne关系中的Jpa ***异常的主要内容,如果未能解决你的问题,请参考以下文章
为啥 JPA 默认使用 FetchType EAGER 来处理 @ManyToOne 关系
使用连接表将 JPA 双向 @ManyToOne 关系映射到多个表
Hibernate JPA - 没有填充ManyToOne关系