EAGER 和分页:Spring MVC + JPA 存储库 + Hibernate
EAGER and Pagination : Spring MVC + JPA Repository + Hibernate
我有一个 实体 A,它与 实体 B (fetch mode = EAGER)
有关系 @OneToMany
。 实体 A 在 LAZY 中也与其他实体有其他关系,但对于这个问题并不重要。
实体 B 与 实体 A 也有关系 @ManyToOne
(fech 模式 = EAGER)。 实体 B 在 LAZY
中也与其他实体有其他关系,但对于这个问题并不重要。
稍后,我有一个实现 JpaRepository class 的接口,我在其中定义了一个 @Query
与其他实体之间的一些内部连接以获得 Entities A[=51 的集合=] 使用 Page 和 Pageable 元素计算得分的 10 个项目。
这里这个过程失败了。为什么?
我的数据库中实体 A 的 table 有 +1000 个满足 @query
条件的寄存器。但是在 Hibernate 或 JPA 之前 return 我有 10 个实体 A,在内部,exect 1000+ 选择获取实体 B 数据(EAGER 关系)和 explote。
为什么不获取 10 个实体 A 并执行 10 "selects" 只获取 10 个实体 B?
唯一的解决办法是将我的关系从 EAGER 更改为 LAZY??不能使用 EAGER 进行分页?
为什么会这样?有什么解决办法吗?
编辑:
声明:+1000 entityA +1000 entityB(在我的例子中,一个entityA只有一个entityB,但entityA可以有多个entityB)
@Entity
@Table(name="EntityA")
public class EntityA implements Serializable{
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(columnDefinition = "BINARY(16)")
private UUID id;
@OneToMany(mappedBy="entityA", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@OrderBy("updatedDate DESC")
private Set<EntityB> entitiesB = new HashSet<EntityB>();
...
}
@Entity
@Table(name="EntityB")
public class EntityB implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(columnDefinition = "BINARY(16)")
private UUID id;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "idEntityA", nullable = false)
private EntityA entityA;
...
}
public interface EntityA_DAO extends JpaRepository<EntityA, UUID>{
@Query("SELECT DISTINCT a FROM EntityA a INNER JOIN a.entityB b LEFT JOIN b.scoreEntityB s INNER JOIN a.user u INNER JOIN a.properties p INNER JOIN p.category c " +
"WHERE c.cod IN (:codcats) AND a.user <> :user AND b.codState = '001' AND a.codState NOT IN ('002','004','005') AND p.deleted <> 1 " +
"GROUP BY b ORDER BY a.createdDate DESC, COUNT(s) DESC")
public Page<EntityA> findAllByCategories(@Param("user") User user, @Param("codcats") List<Integer> lstCodCats, Pageable pageable);
}
编辑 2
这是我的跟踪错误的片段,重复并重复相同的内容:
at java.util.HashMap.put(Unknown Source) at
java.util.HashSet.add(Unknown Source) at
java.util.AbstractCollection.addAll(Unknown Source) at
org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:327)
at
org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:234)
at
org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:221)
at
org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:194)
at
org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154)
at
org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:249)
at
org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:212)
at
org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:123)
at
org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122)
at
org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
at
org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167)
at
org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3956)
at
org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
at
org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
at
org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
at
org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:116)
at
org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129)
at
org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:997)
at
org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:157)
at
org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:266)
at
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68)
at
com.treebuk.model.Fragment_$$_jvsta55_10.hashCode(Fragment_$$_jvsta55_10.java)
at com.treebuk.model.Fragment.hashCode(Fragment.java:210) at
sun.reflect.GeneratedMethodAccessor111.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at
java.lang.reflect.Method.invoke(Unknown Source) at
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:79)
at
com.treebuk.model.Fragment_$$_jvsta55_10.hashCode(Fragment_$$_jvsta55_10.java)
at com.treebuk.model.TextFragment.hashCode(TextFragment.java:340) at
java.util.HashMap.hash(Unknown Source) at
java.util.HashMap.put(Unknown Source) at
java.util.HashSet.add(Unknown Source) at
java.util.AbstractCollection.addAll(Unknown Source) at
org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:327)
at
org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:234)
at
org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:221)
at
org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:194)
at
org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154)
at
org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:249)
at
org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:212)
at
org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:123)
at
org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122)
at
org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86)
at
org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167)
at
org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3956)
at
org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508)
at
org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478)
at
org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
at
org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:116)
at
org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129)
at
org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:997)
at
org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:157)
at
org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:266)
at
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68)
at
com.treebuk.model.Fragment_$$_jvsta55_10.hashCode(Fragment_$$_jvsta55_10.java)
at com.treebuk.model.Fragment.hashCode(Fragment.java:210) at
sun.reflect.GeneratedMethodAccessor111.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at
java.lang.reflect.Method.invoke(Unknown Source) at
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:79)
at
com.treebuk.model.Fragment_$$_jvsta55_10.hashCode(Fragment_$$_jvsta55_10.java)
at com.treebuk.model.TextFragment.hashCode(TextFragment.java:340) at
java.util.HashMap.hash(Unknown Source)
终于找到问题了。问题出在Entity B的方法hasCode(),这个方法和Entity A进行了比较,然后当Spring尝试获取元素,执行hascode方法,进入死循环。我更改了 hascode() 和 equal() 方法以删除这些比较(在我的情况下不需要)。
我有一个 实体 A,它与 实体 B (fetch mode = EAGER)
有关系 @OneToMany
。 实体 A 在 LAZY 中也与其他实体有其他关系,但对于这个问题并不重要。
实体 B 与 实体 A 也有关系 @ManyToOne
(fech 模式 = EAGER)。 实体 B 在 LAZY
中也与其他实体有其他关系,但对于这个问题并不重要。
稍后,我有一个实现 JpaRepository class 的接口,我在其中定义了一个 @Query
与其他实体之间的一些内部连接以获得 Entities A[=51 的集合=] 使用 Page 和 Pageable 元素计算得分的 10 个项目。
这里这个过程失败了。为什么?
我的数据库中实体 A 的 table 有 +1000 个满足 @query
条件的寄存器。但是在 Hibernate 或 JPA 之前 return 我有 10 个实体 A,在内部,exect 1000+ 选择获取实体 B 数据(EAGER 关系)和 explote。
为什么不获取 10 个实体 A 并执行 10 "selects" 只获取 10 个实体 B?
唯一的解决办法是将我的关系从 EAGER 更改为 LAZY??不能使用 EAGER 进行分页?
为什么会这样?有什么解决办法吗?
编辑: 声明:+1000 entityA +1000 entityB(在我的例子中,一个entityA只有一个entityB,但entityA可以有多个entityB)
@Entity
@Table(name="EntityA")
public class EntityA implements Serializable{
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(columnDefinition = "BINARY(16)")
private UUID id;
@OneToMany(mappedBy="entityA", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@OrderBy("updatedDate DESC")
private Set<EntityB> entitiesB = new HashSet<EntityB>();
...
}
@Entity
@Table(name="EntityB")
public class EntityB implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(columnDefinition = "BINARY(16)")
private UUID id;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "idEntityA", nullable = false)
private EntityA entityA;
...
}
public interface EntityA_DAO extends JpaRepository<EntityA, UUID>{
@Query("SELECT DISTINCT a FROM EntityA a INNER JOIN a.entityB b LEFT JOIN b.scoreEntityB s INNER JOIN a.user u INNER JOIN a.properties p INNER JOIN p.category c " +
"WHERE c.cod IN (:codcats) AND a.user <> :user AND b.codState = '001' AND a.codState NOT IN ('002','004','005') AND p.deleted <> 1 " +
"GROUP BY b ORDER BY a.createdDate DESC, COUNT(s) DESC")
public Page<EntityA> findAllByCategories(@Param("user") User user, @Param("codcats") List<Integer> lstCodCats, Pageable pageable);
}
编辑 2
这是我的跟踪错误的片段,重复并重复相同的内容:
at java.util.HashMap.put(Unknown Source) at java.util.HashSet.add(Unknown Source) at java.util.AbstractCollection.addAll(Unknown Source) at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:327) at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:234) at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:221) at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:194) at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154) at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:249) at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:212) at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:123) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86) at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3956) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478) at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219) at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:116) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129) at org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:997) at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:157) at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:266) at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68) at com.treebuk.model.Fragment_$$_jvsta55_10.hashCode(Fragment_$$_jvsta55_10.java) at com.treebuk.model.Fragment.hashCode(Fragment.java:210) at sun.reflect.GeneratedMethodAccessor111.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:79) at com.treebuk.model.Fragment_$$_jvsta55_10.hashCode(Fragment_$$_jvsta55_10.java) at com.treebuk.model.TextFragment.hashCode(TextFragment.java:340) at java.util.HashMap.hash(Unknown Source) at java.util.HashMap.put(Unknown Source) at java.util.HashSet.add(Unknown Source) at java.util.AbstractCollection.addAll(Unknown Source) at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:327) at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:234) at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:221) at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:194) at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:154) at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:249) at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:212) at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:123) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:122) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:86) at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:167) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3956) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478) at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219) at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:116) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129) at org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:997) at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:157) at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:266) at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68) at com.treebuk.model.Fragment_$$_jvsta55_10.hashCode(Fragment_$$_jvsta55_10.java) at com.treebuk.model.Fragment.hashCode(Fragment.java:210) at sun.reflect.GeneratedMethodAccessor111.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:79) at com.treebuk.model.Fragment_$$_jvsta55_10.hashCode(Fragment_$$_jvsta55_10.java) at com.treebuk.model.TextFragment.hashCode(TextFragment.java:340) at java.util.HashMap.hash(Unknown Source)
终于找到问题了。问题出在Entity B的方法hasCode(),这个方法和Entity A进行了比较,然后当Spring尝试获取元素,执行hascode方法,进入死循环。我更改了 hascode() 和 equal() 方法以删除这些比较(在我的情况下不需要)。