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

目录
  • Spring JPA使用CriteriaBuilder动态构造查询
  • JPA CriteriaBuilder中一些运算的使用

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方法里可以直接传方法名进去

/**
name: 方法名
returnType: 返回类型
arguments:表达式
**/
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);

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

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

(0)

相关推荐

  • JPA CriteriaBuilder子查询方式

    目录 JPA CriteriaBuilder子查询 Jpa在CriteriaBuilder中添加where条件NotIn子查询 JPA CriteriaBuilder子查询 给自己做个备忘 /** 检索关键字 */ if (keyWord != null && !keyWord.trim().equals("")) { // 创建子查询对象 Subquery<Store> subquery = criteriaQuery.subquery(Store.cla

  • JPA 使用criteria简单查询工具类方式

    目录 打包JPA动态查询(CriteriaQuery) eq.ge.gt 封装JPA动态查询(CriteriaQuery) EntityManager管理器,通过spring管理 Page分页和结果封装类 IBaseDao接口实现了BaseDaoImpl IBaseDao接口 以前用jpa写了一个条件筛选的查询数据如下,才知道那么渣渣,就是一个表,根据前端来筛选数据,写的如下 首先就是判断前端传来的参数就写了那么多,现在才发现是渣渣中的渣渣,而且还费时,用criteria很快就搞定 首先创建类并

  • 在JPA中criteriabuilder使用or拼接多个like语句

    目录 JPA criteriabuilder使用or拼接多个like语句 sql语句类似于 sql语句如下 java-jpa-criteriabuilder使用 一个复杂的查询例子 JPA criteriabuilder使用or拼接多个like语句 项目中有两张表,一张角色和机构的关系表role_work_site_relation,存放的是机构的id和角色的id,另一张表member_info表中存放用户相关信息. 机构为树形结构,role_work_site_relation中存放的是当前角

  • Spingboot JPA CriteriaBuilder 如何获取指定字段

    目录 Spingboot JPA CriteriaBuilder获取指定字段 Java JPA CriteriaBuilder使用 一个复杂的查询例子 Spingboot JPA CriteriaBuilder获取指定字段 废话不说直接贴代码 public class ActivityVO implements Serializable { private static final long serialVersionUID = 1L; private int id; private Strin

  • 使用JPA进行CriteriaQuery进行查询的注意事项

    目录 使用JPA CriteriaQuery查询的注意事项 1.pojo类 service层 查询方法 封装JPA动态查询(CriteriaQuery) EntityManager管理器,通过spring管理 Page分页和结果封装类 IBaseDao接口实现了BaseDaoImpl IBaseDao接口 使用JPA CriteriaQuery查询的注意事项 1.pojo类 @Entity @Table(name = "report_workload") @JsonIgnoreProp

  • 使用Spring Data Jpa的CriteriaQuery一个陷阱

    使用Spring Data Jpa的CriteriaQuery进行动态条件查询时,可能会遇到一个陷阱,当条件为空时,查询不到任何结果,并不是期望的返回所有结果.这是为什么呢? 例如下述代码,当predicates为空时,返回结果总是为空. public Page<VmhostWithRelationPO> listVmhostSpecWithRelationByPage(String name) { Specification<VmhostWithRelationPO> spec

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

    目录 Spring JPA使用CriteriaBuilder动态构造查询 JPA CriteriaBuilder中一些运算的使用 Spring JPA使用CriteriaBuilder动态构造查询 在使用Spring JPA提供的方法只能进行简单的CRUD,如果遇到复杂的情况就需要我们动态来构建查询条件了.这里我们来看使用CriteriaBuilder如何来构造查询. 核心代码: CriteriaBuilder criteriaBuilder = entityManager.getCriteri

  • spring jpa 审计功能自定义填充字段方式

    目录 spring jpa 审计功能自定义填充字段 有两种方式 具体步骤 启用Spring Data JPA审计功能 JPA Audit 说明 如何使用审计功能 1.编写AuditorAware 2.在实体类中声明@EntityListeners和相应的注解 3.在Application 中启用审计@EnableJpaAuditing spring jpa 审计功能自定义填充字段 spring data jpa 通过@CreateBy等注解实现了审计功能(在新建或者修改的时候自动填充某些字段)

  • Spring Data JPA中的动态查询实例

    spring Data JPA大大的简化了我们持久层的开发,但是实际应用中,我们还是需要动态查询的. 比如,前端有多个条件,这些条件很多都是可选的,那么后端的SQL,就应该是可以定制的,在使用hibernate的时候,可以通过判断条件来拼接SQL(HQL),当然,Spring Data JPA在简化我们开发的同时,也是提供了支持的. 通过实现Criteria二实现的动态查询,需要我们的Repo接口继承JpaSpecificationExecutor接口,这是个泛型接口. 然后查询的时候,传入动态

  • Spring Data Jpa的四种查询方式详解

    这篇文章主要介绍了Spring Data Jpa的四种查询方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.调用接口的方式 1.基本介绍 通过调用接口里的方法查询,需要我们自定义的接口继承Spring Data Jpa规定的接口 public interface UserDao extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> 使用这

  • Spring Data JPA查询方式及方法名查询规则介绍

    目录 Spring Data JPA查询方式及方法名查询规则 一.通过解析方法名创建查询 二.使用 @Query 创建查询 JPA 常用查询方法记录 CrudRepository 默认带的查询方法 简单的扩展-以字段为关键字进行查询 使用@Query 进行复杂查询 使用 Specification 进行复杂查询 Predicate CriteriaBuilder Root Spring Data JPA查询方式及方法名查询规则 Spring Data JPA 一.通过解析方法名创建查询 在执行查

  • JPA CriteriaBuilder子查询方式

    目录 JPA CriteriaBuilder子查询 Jpa 在CriteriaBuilder中添加where条件NotIn子查询 JPA CriteriaBuilder子查询 给自己做个备忘 /** 检索关键字 */ if (keyWord != null && !keyWord.trim().equals("")) { // 创建子查询对象 Subquery<Store> subquery = criteriaQuery.subquery(Store.cl

  • JPA多条件复杂SQL动态分页查询功能

    概述 ORM映射为我们带来便利的同时,也失去了较大灵活性,如果SQL较复杂,要进行动态查询,那必定是一件头疼的事情(也可能是lz还没发现好的方法),记录下自己用的三种复杂查询方式. 环境 springBoot IDEA2017.3.4 JDK8 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0&q

  • 详解Spring Data JPA中Repository的接口查询方法

    目录 1.查询方法定义详解 2.搜索查询策略 3.查询创建 4.属性表达式 5.特殊参数处理 6.限制查询结果 7. repository方法返回Collections or Iterables 8.repository方法处理Null 9.查询结果流 10.异步查询结果 1.查询方法定义详解 repository代理有两种方式从方法名中派生出特定存储查询. 通过直接从方法名派生查询. 通过使用一个手动定义的查询. 可用的选项取决于实际的商店.然而,必须有一个策略来决定创建什么实际的查询. 2.

  • Spring JPA联表查询之OneToOne源码详解

    目录 前言 源码 注解属性 单向联表 user 实体类 car 实体类 查询结果 双向联表 user 实体 car 实体 查询结果 延迟加载(懒加载) user 实体 查询结果: 查询完会发现,控制台又打印了一个 JPQL: 最后结论 前言 前面几篇我们学习的都是单表查询,就是对一张表中的数据进行查询.而实际项目中,基本都会有多张表联合查询的情况,今天我们就来了解下JPA的联表查询是如做的. 源码 @OneToOne 注解实现一对一关系映射.比如用户跟车辆的关系(这里假设一个人只能有一辆车),一

随机推荐