EAGER and Pagination : Spring MVC + JPA Repository + Hiberna



我有一个实体A,它与实体B(fetch mode = EAGER)@OneToMany关系。实体 A在 LAZY 中与其他实体也有其他关系,但对于这个问题并不重要。

实体 B也与实体 A@ManyToOne关系(fech 模式 = EAGER)。实体性 B与其他实体LAZY也有其他关系,但对于此问题并不重要。

稍后,我有一个实现 JpaRepository 类的接口,其中我定义了一个@Query,其中包含其他实体之间的一些内部连接,以便使用 Page 和 Pageable 元素获得包含 10 个项目的实体 A的集合,并计算出分数。

这个过程在这里失败了。为什么?

我在数据库中的实体 A 表有 +1000 个条件为@query的寄存器。但是在 Hibernate 或 JPA 返回我 10 个实体 A 之前,在内部,执行 1000+ 选择以获取实体 B 数据(EAGER 实现)和 explote。

为什么不获取 10 个实体A,而执行 10 个"选择"仅获取 10 个实体 B?

独特的解决方案是将我的关系从渴望更改为懒惰?? 无法与 EAGER 合作?

为什么会这样?有什么解决办法吗?

编辑:声明: +1000 实体A +1000 实体 B(在我的示例中,一个实体 A 只有一个实体 B,但实体 A 可以有多个实体 B)

@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) 在 org.hibernate.engine.load.internal.CollectionLoadContext.endLoadCollection(CollectionLoadContext.java:234) 在 org.hibernate.engine.load.internal.CollectionLoadContext.endLoadCollections(CollectionLoadContext.java:221) 在 org.hibernate.engine.load.internal.CollectionLoadContext.endLoadCollections(CollectionLoadContext.java:194) 在 org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoad(CollectionReferenceInitializerImpl.java:154) 在 org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadCollections(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:123) 在 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:3956) 在 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) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129) 在 org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:997) 在 org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:157) 在 org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:266) 在 org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68) 在 com.treebuk.model.Fragment_$$_jvsta55_10.hashCode(Fragment_$$_jvsta55_10.java) at com.treebuk.model.Fragment.hashCode(Fragment.java:210) at sun.reflect.Generated MethodAccessor111.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) 在 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) atorg.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:327) 在 org.hibernate.engine.load.internal.CollectionLoadContext.endLoadCollection(CollectionLoadContext.java:234) 在 org.hibernate.engine.load.internal.CollectionLoadContext.endLoadCollections(CollectionLoadContext.java:221) 在 org.hibernate.engine.load.internal.CollectionLoadContext.endLoadCollections(CollectionLoadContext.java:194) 在 org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoad(CollectionReferenceInitializerImpl.java:154) 在 org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadCollections(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:123) 在 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:3956) 在 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) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1129) 在 org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:997) 在 org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:157) 在 org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:266) 在 org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68) 在 com.treebuk.model.Fragment_$$_jvsta55_10.hashCode(Fragment_$$_jvsta55_10.java) at com.treebuk.model.Fragment.hashCode(Fragment.java:210) at sun.reflect.Generated MethodAccessor111.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) 在 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(未知来源)

Finnaly,我发现了问题。问题是实体 B hasCode() 方法,此方法与实体 A 有比较,然后当 Spring 尝试获取元素时,执行 hascode 方法,并进入无限循环。我更改了 hascode() 和 equal() 方法来删除这些比较(在我的情况下不是必需的)。

最新更新