如何在CriteriaQuery中实现Restrictions.sqlRestriction?
在JPA CriteriaQuery中实现类似Restrictions.sqlRestriction的原生SQL限制
当然可以实现,结合你使用的Hibernate环境(从getSession()调用判断),以下是两种实用方案:
方案1:直接使用Hibernate专属API(最贴合旧版用法)
这是替代旧Restrictions.sqlRestriction()的最优方式,支持参数绑定避免SQL注入:
CriteriaBuilder builder = getSession().getCriteriaBuilder(); CriteriaQuery<Test> query = builder.createQuery(Test.class); Root<Test> root = query.from(Test.class); // 示例1:添加带位置参数的原生SQL条件 Predicate sqlPredicate = builder.sqlRestriction("test_column > ?1", 100, Integer.class); // 示例2:添加带命名参数的原生SQL条件(更易读) // Predicate sqlPredicate = builder.sqlRestriction( // "status = :activeStatus AND create_time > :startTime", // Map.of("activeStatus", "ACTIVE", "startTime", LocalDate.now().minusDays(7)) // ); query.where(sqlPredicate); // 执行查询 List<Test> results = getSession().createQuery(query).getResultList();
方案2:通用JPA兼容方案(不依赖Hibernate特性)
如果需要保持JPA标准兼容性,可通过自定义表达式实现原生SQL条件:
CriteriaBuilder builder = getSession().getCriteriaBuilder(); CriteriaQuery<Test> query = builder.createQuery(Test.class); Root<Test> root = query.from(Test.class); // 构建包含原生SQL片段的布尔表达式 Expression<Boolean> sqlCondition = builder.function( "BOOLEAN", Boolean.class, builder.literal("test_column LIKE '%keyword%'") ); query.where(sqlCondition); List<Test> results = getSession().createQuery(query).getResultList();
关键注意点
- 始终使用参数绑定(位置参数
?1或命名参数),禁止直接拼接字符串,避免SQL注入 - 原生SQL中的表/列名要与数据库实际映射一致,若Hibernate配置了表名/列名映射,需使用映射后的名称
- 方案1是Hibernate特有的实现,写法简洁;方案2兼容所有JPA实现,但灵活性稍弱
内容的提问来源于stack exchange,提问作者Navneet Singh
相关产品推荐
相关产品推荐

