JPA - 多对多集合的分页查询返回错误数量的实体
Posted
技术标签:
【中文标题】JPA - 多对多集合的分页查询返回错误数量的实体【英文标题】:JPA - Paginated query with ManyToMany collection returns wrong number of entities 【发布时间】:2013-12-14 09:37:07 【问题描述】:我有这两个实体(这里是简化版本):
主题:
@Entity
public class Topic implements Serializable
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
private Long id;
@ManyToMany
@JoinTable(
name = "topic_member",
joinColumns = @JoinColumn( name = "topic" ),
inverseJoinColumns = @JoinColumn( name = "member" ) )
@JoinFetch
private List<Member> participants = new ArrayList<Member>();
...
会员:
@Entity
public class Member implements Serializable
@Id
@GeneratedValue( strategy = GenerationType.IDENTITY )
private Long id;
...
这些通过连接表 topic_member(member, topic)
关联,通过单向 @ManyToMany 关系。
当我插入东西时一切正常,这里没问题。
但是当我想选择东西时,它变得更加棘手。假设我想选择与特定成员相关的所有主题。我编写了以下 JPQL 查询:
SELECT t FROM Topic t WHERE :member MEMBER OF t.participants ORDER BY t.id DESC
然后我写了这个:
TypedQuery<Topic> query = em.createQuery( MY_JPQL_REQUEST, Topic.class );
query.setParameter( PARAM_MEMBER, member );
return query.getResultList();
而且效果很好。
但是有些奇怪的错误:似乎我不能在这个查询上使用分页! 例如,当我尝试这个时:
TypedQuery<Topic> query = em.createQuery( MY_JPQL_REQUEST, Topic.class );
query.setParameter( PARAM_MEMBER, member );
query.setFirstResult( 0 );
query.setMaxResults( 5 );
return query.getResultList();
它返回错误的实体数量。比如前一个返回5的时候,就只返回3...
我在这里缺少什么?我不明白会出什么问题。
我读过this page,我认为这里可能有些东西,但我不知道是什么。
[编辑] 如果有帮助,这是我在数据库中的连接表中的内容:
+-------------+-------------+ |会员 |话题 | +-------------+-------------+ | 1 | 1 | | 1 | 2 | | 1 | 3 | | 1 | 4 | | 1 | 5 | | 2 | 1 | | 2 | 2 | | 2 | 3 | | 2 | 4 | | 2 | 5 | +-------------+-------------+[解决方案] 感谢 Chris,我得到了它的工作。我不得不在@ManyToMany
字段上用@BatchFetch( BatchFetchType.JOIN )
替换@JoinFetch
,并查询SELECT DISTINCT(t) FROM ...
而不是SELECT t FROM ...
。
【问题讨论】:
【参考方案1】:这是设计使然。分页在数据库级别工作以过滤返回的行数。在集合上使用 fetch 连接时,它需要多行来构建单个实体,因此返回的实体数将与最大结果不匹配。最重要的是,为确保返回 Bly 完整实体,可能会丢弃第一个和最后一个实体,因为无法验证它们是否完整。
尝试使用带有 IN 策略的批量获取。
【讨论】:
感谢您的信息。就我而言,我应该如何使用 IN 策略来选择与特定成员相关的所有主题?我试过了,但我从来没有让它正常工作。 eclipse.org/eclipselink/documentation/2.4/jpa/extensions/… 是我所指的,而不是 join fetch 注释。您显示的映射从主题到成员,因此类似于“select m from topic t join t.participants m where t = :t” 不幸的是,这个请求似乎是错误的。在我的简单设计中,每个主题都有一个成员列表,并且我想要给定成员的所有主题(= 给定成员在其参与者列表中的每个主题)。我一定遗漏了一些明显的东西,但如果没有 MEMBER OF...,我看不到如何做到这一点 批量提取适用于您的原始查询。正是使用 join fetch 导致了分页问题。如果仍然有问题,请尝试使用 DISTINCT。 好的,非常感谢!最后,JPQL 查询中@ManyToMany
字段 + DISTINCT
上的 @BatchFetch
(IN 或 JOIN 类型,两者都可以正常工作)成功了。以上是关于JPA - 多对多集合的分页查询返回错误数量的实体的主要内容,如果未能解决你的问题,请参考以下文章