实体:
得分[id,user_id,value]
用户[id,name]
我想加入加入用户
的十大分数(由user_id加入)原生查询有效,但是休眠无法将用户分级(再次延迟加载),
我尝试编写JPQL查询,但它生成了错误的查询
工作自然查询:
select *
from scores
join users
on scores.user_id = users.id and
user_id in (
select distinct user_id
from scores order by value desc
)
order by value desc limit 10
答案 0 :(得分:1)
轻松自在!
现在,您的查询选择了Scores并且只加入了一些用户,但并没有真正加入Score.users
或user.score
关联的FETCH。如果您想急切加载Score和相关用户,您需要这样的内容:
正如我在this article中所解释的那样,您可以使用窗函数。 MySQL 8 supports Windows Functions所以只需运行以下SQL查询:
List<Score> scores = entityManager.createNativeQuery(
"select u_s_r.* " +
"from ( " +
" select *, dense_rank() OVER (ORDER BY value DESC) rank " +
" from ( " +
" select s.*, u.* " +
" from scores s " +
" join users u s.user_id = u.id " +
" order by u.id " +
" ) u_s " +
") u_s_r " +
"where u_s_r.rank <= :rank", Score.class)
.setParameter("rank", 10)
.unwrap( NativeQuery.class )
.addEntity( "s", Score.class )
.addEntity( "u", User.class )
.setResultTransformer( DistinctScoreResultTransformer.INSTANCE )
.getResultList();
DistinctScoreResultTransformer
可能如下所示:
public class DistinctScoreResultTransformer
extends BasicTransformerAdapter {
private static final DistinctScoreResultTransformer INSTANCE =
new DistinctScoreResultTransformer();
@Override
public List transformList(List list) {
Map<Serializable, Identifiable> identifiableMap =
new LinkedHashMap<>( list.size() );
for ( Object entityArray : list ) {
if ( Object[].class.isAssignableFrom(
entityArray.getClass() ) ) {
Score score = null;
User user = null;
Object[] tuples = (Object[]) entityArray;
for ( Object tuple : tuples ) {
if(tuple instanceof Score) {
score = (Score) tuple;
}
else if(tuple instanceof User) {
user = (User) tuple;
}
else {
throw new UnsupportedOperationException(
"Tuple " + tuple.getClass() + " is not supported!"
);
}
}
Objects.requireNonNull(score);
Objects.requireNonNull(user);
if ( !identifiableMap.containsKey( score.getId() ) ) {
identifiableMap.put( score.getId(), score );
score.setUsers( new ArrayList<>() );
}
score.addUser( user );
}
}
return new ArrayList<>( identifiableMap.values() );
}
}
如果您想知道是否可以通过JPQL完成,那么您应该知道这是不可能的。但是,您不必通过JPQL运行每个查询。数据访问层工具箱中的Native SQL is the Magic Wand。