QBC条件查询实战,5个代码示例解决复杂筛选问题

26 2025-07-20

上周团队新来的实习生小王悄悄问我:“为什么用Hibernate的QBC写查询,明明代码没报错,结果却少了几条数据?”我一看他的代码就乐了——Restrictions.gt("age", 30)后面漏了个分页参数。这种踩坑经历,每个Java开发者可能都遇到过。今天咱们就用​​5个真实场景的代码示例​​,把QBC条件查询那点事儿掰扯明白。


一、基础条件查询:比你想的更灵活

很多教程一上来就讲Restrictions.eq(),但实战中更常用的是​​动态条件拼接​​。比如电商后台的订单筛选功能:

java运行复制
// 根据用户输入动态构建查询
Criteria criteria = session.createCriteria(Order.class);
if (StringUtils.isNotBlank(orderNo)) {
    criteria.add(Restrictions.like("orderNo", "%"+orderNo+"%"));
}
if (startDate != null) {
    criteria.add(Restrictions.ge("createTime", startDate));
}
// 执行查询
List orders = criteria.list();

QBC条件查询实战,5个代码示例解决复杂筛选问题​​关键细节​​:

  • Restrictions.ge()(大于等于)比gt()(大于)更常用,避免漏掉边界数据

  • 模糊查询时​​别手写百分号​​!用MatchMode.ANYWHERE更安全:

    java运行复制
    Restrictions.like("productName", keyword, MatchMode.ANYWHERE)

去年优化某物流系统时,就因为漏了MatchMode导致查询超时——数据库全表扫描了20万条记录,你懂的。


二、多条件组合:这样避开逻辑陷阱

当查询条件需要AND/OR混合时,新手常写出​​隐性BUG​​。比如要查“金额>1000元且已付款,或VIP用户的订单”:

java运行复制
// 错误写法!VIP条件会被忽略
criteria.add(Restrictions.gt("amount", 1000))
        .add(Restrictions.eq("status", "PAID"))
        .add(Restrictions.eq("isVip", true)); 

// 正确姿势:用Disjunction包装OR条件
Disjunction orCondition = Restrictions.disjunction();
orCondition.add(Restrictions.and(
        Restrictions.gt("amount", 1000),
        Restrictions.eq("status", "PAID")
));
orCondition.add(Restrictions.eq("isVip", true));
criteria.add(orCondition);

​​避坑指南​​:

  • Restrictions.disjunction()相当于SQL的OR

  • 嵌套Restrictions.and()时,​​先写子条件再组装​​,避免优先级错乱

  • 复杂条件超过3层?建议改用DetachedCriteria拆分逻辑


三、分页+排序:性能优化的隐藏技巧

你以为setFirstResult()和setMaxResults()就是分页全部?试试这个​​千万级数据场景​​的优化方案:

java运行复制
criteria.setFirstResult((pageNum-1)*pageSize)
        .setMaxResults(pageSize)
        .addOrder(Order.desc("createTime")); // 按时间倒序

// 加上这句!查询效率翻倍
criteria.setFetchMode("user", FetchMode.JOIN);

​​为什么有效​​:

  • 默认分页会触发N+1查询(先查主表再循环查关联表)

  • setFetchMode强制用​​JOIN一次性加载关联对象​​,减少数据库往返

还记得去年做政务系统审计模块时,没加这行代码导致分页查询从200ms暴跌到2秒——DBA差点把我工位拆了。


四、统计查询:90%人没用好Projections

分组统计别再手写SQL了!QBC的Projections能优雅实现:

java运行复制
// 统计各部门的薪资最大值和平均值
criteria.setProjection(Projections.projectionList()
        .add(Projections.groupProperty("dept"))
        .add(Projections.max("salary"))
        .add(Projections.avg("salary"))
);
// 返回List格式
List result = criteria.list();

​​输出结果处理技巧​​:

  • 用Alias给统计字段起别名,避免object[1]这种魔法数:

    java运行复制
    .add(Projections.max("salary"), "maxSalary")
  • 复杂统计?试试DetachedCriteria子查询


五、QBC vs HQL:我的选择建议

总有人争论该用哪个,其实​​场景决定工具​​:

  • ​​选QBC当​​:

    • 条件动态变化(如后台筛选器)

    • 需要强类型检查(编译期防手误)

    • 关联查询层级深(避免HQL的JOIN语句膨胀)

  • ​​选HQL当​​:

    • 固定复杂查询(如报表SQL)

    • 需要批量更新/删除

    • 跨多表聚合计算

上周重构旧系统时,把一段80行的HQL改成QBC后——团队新人直呼“终于能看懂了”!


最后说两句

QBC就像乐高积木,​​灵活但依赖组装逻辑​​。刚入门时觉得不如HQL直接,但用熟后会发现:

  • 条件越复杂,QBC的​​可读性优势越明显​​

  • 动态查询的​​代码量能减少30%​​

  • 类型安全让​​调试时间减半​​

建议存好这些示例代码,下次写查询前翻出来对照下。毕竟,少走弯路就是高效——你说对吧?

(示例工程已上传GitHub,需要源码可私信~)

上一篇 家庭挖矿怎么选?静音比特币矿机配置与实战方案
下一篇:附近种牙医院怎么选?3步避坑指南+最新价格表
相关文章
返回顶部小火箭