我在服务器日志中得到一个警告“firstresult/maxresults specified with collection fetch;正在内存中应用!“。不过,一切正常。但我不想要这个警告。
我的密码是
public employee find(int id) {
return (employee) getEntityManager().createQuery(QUERY).setParameter("id", id).getSingleResult();
}
我的问题是
QUERY = "from employee as emp left join fetch emp.salary left join fetch emp.department where emp.id = :id"
6条答案
按热度按时间aurhwmvo1#
我猜emp有很多部门,这是一对多的关系。hibernate将为此查询获取许多行,其中包含已获取的部门记录。因此,只有当结果集真正返回到内存中时,才能确定结果集的顺序。所以分页将在内存中完成。
如果您不想使用emp获取部门,但仍然希望根据部门进行查询,则可以在不发出警告的情况下(不在内存中进行排序)获得结果。为此,您必须删除“fetch”子句。大致如下:
query=“from employee as emp left join emp.salary sal left join emp.department dep where emp.id=:id and dep.name='testing'and sal.salary>5000”
tktrz96b2#
要避免此警告,您必须更改呼叫
getSingleResult
至getResultList().get(0)
exdqitrt3#
尽管您得到的是有效的结果,但sql查询获取所有数据,效率并不如预期的那么高。
所以,你有两个选择。
使用两个可以以读写模式获取实体的sql查询修复了此问题
解决此问题的最简单方法是执行两个查询:
. 第一个查询将获取与提供的筛选条件匹配的根实体标识符。第二个查询将使用先前提取的根实体标识符来获取父实体和子实体。
这种方法很容易实现,如下所示:
修复了一个只能以只读模式获取实体的sql查询的问题
第二种方法是对符合筛选条件的父实体和子实体的结果集使用sdense\u rank,并仅限制前n个post条目的输出。
sql查询可以如下所示:
这个
@NamedNativeQuery
获取与提供的标题匹配的所有post实体及其关联的PostComment
子实体。这个DENSE_RANK
窗口函数用于分配每个职位和职位的排名PostComment
合并的记录,以便我们以后可以过滤我们感兴趣的post记录的数量。这个
SqlResultSetMapping
提供sql级列别名与需要填充的jpa实体属性之间的Map。现在,我们可以执行
PostWithCommentByRank
@NamedNativeQuery
这样地:现在,默认情况下,本机sql查询
PostWithCommentByRank
有人会去拿邮递和信件PostComment
在同一个jdbc行中,因此我们将以Object[]
包含两个实体。但是,我们要转换表格
Object[]
数组变成一棵父子实体树,为此,我们需要使用hibernateResultTransformer
.这个
DistinctPostResultTransformer
如下所示:这个
DistinctPostResultTransformer
必须分离正在获取的实体,因为我们正在覆盖子集合,并且不希望将其传播为实体状态转换:ct2axkht4#
出现此警告的原因是,使用fetch join时,结果集中的顺序仅由选定实体的id定义(而不是由fetch join定义)。
如果内存中的这种排序导致了问题,请不要将firsresult/maxresults与join fetch一起使用。
m4pnthwp5#
此警告告诉您hibernate正在内存中执行java分页。这会导致jvm内存消耗过高。因为开发人员可能会错过这个警告,所以我为hibernate添加了一个允许抛出异常的标志,而不是记录警告(https://hibernate.atlassian.net/browse/hhh-9965).
标志是hibernate.query.fail\u on \u pagination\u over \u collection\u fetch。
我建议大家启用它。
该标志在org.hibernate.cfg.availablesettings中定义:
5anewei66#
问题是你会得到笛卡尔积做连接。如果您仍在同一根标识类上,则偏移量将剪切记录集而不查看