Grails 6迁移:替代已弃用的Hibernate Criteria .list()与.scroll()
Grails 6 中高效迭代大数据集的替代方案
方案一:通过GORM查询结合Hibernate Session获取ScrollableResults
GORM的where查询返回的AbstractDetachedCriteria没有直接的scroll()方法,但可以借助Hibernate Session来创建可滚动结果集:
import org.hibernate.ScrollableResults import org.hibernate.Session // 构建查询条件 def query = Toto.where { exemple == XXX } // 获取当前Hibernate Session Session session = Toto.sessionFactory.currentSession // 将GORM查询转换为JPA CriteriaQuery,再创建ScrollableResults ScrollableResults scrollableResults = session.createScrollableResults(query.createCriteriaQuery()) try { while (scrollableResults.next()) { Toto toto = scrollableResults.get(0) as Toto // 执行你的数据处理逻辑 } } finally { // 务必关闭资源,避免连接泄漏 scrollableResults.close() }
方案二:分页迭代处理大数据集
如果不需要逐行滚动,分页批量处理是更简洁的方式,同样能避免一次性加载所有数据到内存:
final int BATCH_SIZE = 1000 // 可根据系统内存调整每页数量 int offset = 0 List<Toto> batch do { batch = Toto.where { exemple == XXX }.list(max: BATCH_SIZE, offset: offset) batch.each { Toto toto -> // 处理单条数据逻辑 } offset += BATCH_SIZE } while (!batch.isEmpty())
方案三:直接使用Hibernate JPA Criteria API构建滚动查询
如果需要完全脱离旧的Criteria API,直接使用JPA标准API结合Hibernate的滚动能力:
Toto.withSession { session -> def criteriaBuilder = session.criteriaBuilder def criteriaQuery = criteriaBuilder.createQuery(Toto) def root = criteriaQuery.from(Toto) // 构建查询条件 criteriaQuery.where(criteriaBuilder.equal(root.get("exemple"), XXX)) // 创建可滚动结果集 ScrollableResults scrollable = session.createScrollableResults(criteriaQuery) try { while (scrollable.next()) { Toto toto = scrollable.get(0) as Toto // 数据处理逻辑 } } finally { scrollable.close() } }
注意事项
- 使用
ScrollableResults时必须确保在事务范围内操作,避免Session提前关闭 - 分页方案中,
BATCH_SIZE的取值需要平衡内存占用和数据库查询次数,建议根据实际数据大小和系统性能调整 - 无论哪种方式,处理完数据后都要及时关闭相关资源,防止数据库连接泄漏
内容的提问来源于stack exchange,提问作者Yoann Basquin
相关产品推荐
相关产品推荐

