Java Hibernate对每一行使用sql调用来获取关系,而不是在子句中聚合为一行
我有一个Java Hibernate对每一行使用sql调用来获取关系,而不是在子句中聚合为一行,java,hibernate,Java,Hibernate,我有一个用户对象,其地址设置为地址。现在让我们假设我需要获取1000000个用户,并在一些报告中显示他们的地址 执行此操作的Hibernate方法是为User表创建一个sql调用,然后为每个用户创建另一个Address表调用。结果是总计100000次调用和很长的查询时间 另一方面,如果您聚合所有外键(例如User\u Id),并在sql调用中运行 FROM Address where User_Id IN (,,,,,,,,) 您将呼叫数减少到2个-一个呼叫用户表,一个呼叫地址表,以便在一次呼
用户
对象,其地址
设置为地址
。现在让我们假设我需要获取1000000个用户,并在一些报告中显示他们的地址
执行此操作的Hibernate
方法是为User
表创建一个sql
调用,然后为每个用户创建另一个Address
表调用。结果是总计100000次调用和很长的查询时间
另一方面,如果您聚合所有外键(例如User\u Id
),并在
sql调用中运行
FROM Address where User_Id IN (,,,,,,,,)
您将呼叫数减少到2个-一个呼叫用户表,一个呼叫地址表,以便在一次呼叫中获得所有1000000个所需地址
但这需要在应用程序方面做一些工作。不是很多工作,只是一个循环的,但是仍然。有没有可能让Hibernate以高效的方式来做呢
请注意,LAZY fetching
与此无关。对于我的用例,我需要一个快速抓取
我建议您进行两次查询。我使用Java8流
Query query = session.createQuery("from User").setMaxResult(BATCH);
List<User> users = query.list();
final List<Integer> userIds = users.stream()
.map(u -> u.getUserId()).collect(Collectors.toList());
query = session.createQuery("FROM Address where User_Id IN (:ids)").setListParametrs(userIds);
final List<Address> result = query.list();
Query Query=session.createQuery(“来自用户”).setMaxResult(批处理);
List users=query.List();
最终列表userid=users.stream()
.map(u->u.getUserId()).collect(Collectors.toList());
query=session.createQuery(“从用户Id所在的地址(:Id)”).setListParameters(用户Id);
最终列表结果=query.List();
我还想建议不要在一个查询中获得1000000行,使用批处理 我建议您提出两个问题。我使用Java8流
Query query = session.createQuery("from User").setMaxResult(BATCH);
List<User> users = query.list();
final List<Integer> userIds = users.stream()
.map(u -> u.getUserId()).collect(Collectors.toList());
query = session.createQuery("FROM Address where User_Id IN (:ids)").setListParametrs(userIds);
final List<Address> result = query.list();
Query Query=session.createQuery(“来自用户”).setMaxResult(批处理);
List users=query.List();
最终列表userid=users.stream()
.map(u->u.getUserId()).collect(Collectors.toList());
query=session.createQuery(“从用户Id所在的地址(:Id)”).setListParameters(用户Id);
最终列表结果=query.List();
我还想建议不要在一个查询中获得1000000行,使用批处理 Hibernate将使用连接生成单个查询。我不知道您正在使用哪种配置。从用户u LEFT JOIN FETCH u.address中选择u。
将通过连接提供u地址。单个查询Hibernate将使用连接生成单个查询
。我不知道您正在使用哪种配置。从用户u LEFT JOIN FETCH u.address中选择u。
将通过连接提供u地址。单查询是的,这是我刚才提到的两个查询。但是您仍然需要收集用户ID,然后将每个地址与其用户进行匹配。再说一次,不是很多工作,但仍然。(感谢没有for循环的收集用户ID的酷新方法。)不,我不会一次获取一百万个对象。这只是一个例子。是的,这是我刚才提到的两个问题。但是您仍然需要收集用户ID,然后将每个地址与其用户进行匹配。再说一次,不是很多工作,但仍然。(感谢没有for循环的收集用户ID的酷新方法。)不,我不会一次获取一百万个对象。这只是一个例子。Andy为什么不直接获取所需的地址字段?@Antoniossss,因为这正是问题所在。在这种情况下,Hibernate将执行1000001个查询。设置true
并亲自查看。Hibernate将使用连接生成单个查询。我不知道您使用的是哪种配置。从用户u LEFT JOIN FETCH u中选择u。address
将通过连接提供uaddress
。单身queryYes,太好了。这应该是对这个问题的回答,我很乐意接受。你的愿望实现了:)安迪,你为什么不直接获取所需的地址字段?@antoniosss,因为这正是问题所在。在这种情况下,Hibernate将执行1000001个查询。设置true
并亲自查看。Hibernate将使用连接生成单个查询。我不知道您使用的是哪种配置。从用户u LEFT JOIN FETCH u中选择u。address
将通过连接提供uaddress
。单身queryYes,太好了。这应该是这个问题的答案,我很乐意接受。你的愿望实现了:)实际上,如果你不在用户和地址之间使用hibernate关系,这只是一个查询。但是当你这样做时,一个急切的获取会做一个额外的查询,如果你使用一个懒惰的获取,你以后在检索地址时就必须使用这个额外的查询。实际上,如果你不在用户和地址之间使用hibernate关系,这是一个单独的查询。但是当你这样做的时候,一个急切的抓取会做一个额外的查询,如果你使用一个懒惰的抓取,那么你以后在检索地址时必须使用额外的查询。