文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring JPA使用CriteriaBuilder动态构造查询方式

2024-04-02 19:55

关注

Spring JPA使用CriteriaBuilder动态构造查询

在使用Spring JPA提供的方法只能进行简单的CRUD,如果遇到复杂的情况就需要我们动态来构建查询条件了。这里我们来看使用CriteriaBuilder如何来构造查询。

核心代码:


 CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
 CriteriaQuery<Long> query = criteriaBuilder.createQuery(Long.class);
 Root<Order> root = query.from(Order.class);
 query.select(criteriaBuilder.count(root.get("id")));
 Predicate predicate = criteriaBuilder.equal(root.get("id"), 1);
 query.where(predicate);
 Long singleResult = entityManager.createQuery(query).getSingleResult();

调用entityManager.getCriteriaBuilder()来获取CriteriaBuilder。CriteriaBuilder可以用于创建CriteriaQuery、CriteriaUpdate和CriteriaDelete。除此之外类似count、max等函数也是由CriteriaBuilder来创建的。其中Entitymanager可以使用@PersistenceContext注解来进行注入。

调用criteriaBuilder.createQuery来创建CriteriaQuery。其中createQuery的参数是Query返回值类型。

调用query.from(Order.class)。参数是对应于order表的实体类,query.from类似于sql中的from语句,该方法的执行等价于sql中的from order。

调用 query.select创建映射。 query.select(criteriaBuilder.count(root.get(“id”)))等价于select count(id)。如果执行query.select(root)则等价于select *。

使用CriteriaBuilder构造查询条件Predicate,该predicate也就是在where后面的条件子句。

将Predicate放在 query.where中。

最后执行查询获取数据。

JPA CriteriaBuilder中一些运算的使用

最近使用jpa时,需要使用订单中的金额除以单价算出每个订单的数量,然后求和。找了好多资料才解决,在此整理一下。

首先了解一下CriteriaBuilder的一些运算


// Create path and parameter expressions:
  Expression<Integer> path = country.get("population");
  Expression<Integer> param = cb.parameter(Integer.class);
  // Addition (+)
  Expression<Integer> sum1 = cb.sum(path, param); // expression + expression
  Expression<Integer> sum2 = cb.sum(path, 1000); // expression + number
  Expression<Integer> sum3 = cb.sum(1000, path); // number + expression
  // Subtraction (-)
  Expression<Integer> diff1 = cb.diff(path, param); // expression - expression
  Expression<Integer> diff2 = cb.diff(path, 1000); // expression - number
  Expression<Integer> diff3 = cb.diff(1000, path); // number - expression
  // Multiplication (*)
  Expression<Integer> prod1 = cb.prod(path, param); // expression * expression
  Expression<Integer> prod2 = cb.prod(path, 1000); // expression * number
  Expression<Integer> prod3 = cb.prod(1000, path); // number * expression
  // Division (/)
  Expression<Integer> quot1 = cb.quot(path, param); // expression / expression
  Expression<Integer> quot2 = cb.quot(path, 1000); // expression / number
  Expression<Integer> quot3 = cb.quot(1000, path); // number / expression
  // Modulo (%)
  Expression<Integer> mod1 = cb.mod(path, param); // expression % expression
  Expression<Integer> mod2 = cb.mod(path, 1000); // expression % number
  Expression<Integer> mod3 = cb.mod(1000, path); // number % expression
  // Math(abs, exp, sqrt)
  Expression<Integer> abs = cb.abs(param); // 求绝对值ABS(expression)
  Expression<Integer> neg = cb.neg(path); // 求相反数 -expression
  Expression<Integer> sqrt = cb.sqrt(cb.literal(100)); //求平方根 SQRT(expression)

由于CriteriaBuilder提供的加减乘除方法的名字和平常使用的不太一样,所以用了好久才找出来。

单字段求和可以直接使用


CriteriaBuilder cb = em.getCriteriaBuilder();
Expression<Number> sum = cb.sum(root.get(字段名)).alias(别名)

前边也说了需求是用金额(amount)除以单价(unitPrice),然后求和,所以这时需要先用amount除以unitPrice


Expression<Number> quot = cb.quot(root.get("amount"), root.get("unitPrice"));

算出数量后就可以使用sum求和了。


cb.sum(quot)

完事之后,还需要对数据四舍五入,需要用到mysql的round方法

在CriteriaBuilder没有找到round方法,那怎么办呢?没关系,CriteriaBuilder还提供了function方法,在function方法里可以直接传方法名进去



public <T> Expression<T> function(String name, Class<T> returnType, Expression... arguments) {
        return new ParameterizedFunctionExpression(this, returnType, name, arguments);
    }

调用代码如下


Expression<BigDecimal> round = cb.function("round", BigDecimal.class, quot);

到这一步发现,还需要保留两位小数。可是,Expression里 没有相关的方法。天无绝人之路,在看了cb.function()后发现,这个方法的最后一个参数是可变参数,所以上边的代码改成了如下


List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
Expression<Integer> size = cb.size(list);
Expression<BigDecimal> round = cb.function("round", BigDecimal.class, quot,size);

至此,完成了先求两列的商,然后对商求和的功能。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯