JPA 之 QueryDSL-JPA 使用指南
Posted 墨鸦_Cormorant
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JPA 之 QueryDSL-JPA 使用指南相关的知识,希望对你有一定的参考价值。
Querydsl-JPA 框架(推荐)
官网:传送门
参考:
概述及依赖、插件、生成查询实体
1.Querydsl支持代码自动完成,因为是纯Java API编写查询,因此主流Java IDE对起的代码自动完成功能支持几乎可以发挥到极致(因为是纯Java代码,所以支持很好)
2.Querydsl几乎可以避免所有的SQL语法错误(当然用错了Querydsl API除外,因为不写SQL了,因此想用错也难)
3.Querydsl采用Domain类型的对象和属性来构建查询,因此查询绝对是类型安全的,不会因为条件类型而出现问题
4.Querydsl采用纯Java API的作为SQL构建的实现可以让代码重构发挥到另一个高度
5.Querydsl的领一个优势就是可以更轻松的进行增量查询的定义
使用
在Spring环境下,可以通过两种风格来使用QueryDSL。
一种是使用JPAQueryFactory
的原生QueryDSL风格, 另一种是基于Spring Data提供的QueryDslPredicateExecutor<T>
的Spring-data风格。
使用QueryDslPredicateExecutor<T>
可以简化一些代码,使得查询更加优雅。 而JPAQueryFactory
的优势则体现在其功能的强大,支持更复杂的查询业务。甚至可以用来进行更新和删除操作。
依赖
<dependencies>
<!-- QueryDSL框架依赖 -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
</dependencies>
添加maven插件(pom.xml)
添加这个插件是为了让程序自动生成query type(查询实体,命名方式为:“Q”+对应实体名)。
上文引入的依赖中querydsl-apt
即是为此插件服务的。
注:在使用过程中,如果遇到query type无法自动生成的情况,用maven更新一下项目即可解决(右键项目->Maven->Update Project)。
<project>
<build>
<plugins>
<plugin>
<!--因为QueryDsl是类型安全的,所以还需要加上Maven APT plugin,使用 APT 自动生成Q类:-->
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
补充:
QueryDSL默认使用HQL发出查询语句。但也支持原生SQL查询。
若要使用原生SQL查询,你需要使用下面这个maven插件生成相应的query type。
<project>
<build>
<plugins>
<plugin>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-maven-plugin</artifactId>
<version>$querydsl.version</version>
<executions>
<execution>
<goals>
<goal>export</goal>
</goals>
</execution>
</executions>
<configuration>
<jdbcDriver>org.apache.derby.jdbc.EmbeddedDriver</jdbcDriver>
<jdbcUrl>jdbc:derby:target/demoDB;create=true</jdbcUrl>
<packageName>com.mycompany.mydomain</packageName>
<targetFolder>$project.basedir/target/generated-sources/java</targetFolder>
</configuration>
<dependencies>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>$derby.version</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
生成查询实体
idea 工具 为maven project 自动添加了对应的功能。添加好依赖和 plugin 插件后,就可以生成查询实体了。
打开右侧的 Maven Projects,如下图所示:
双击 clean 清除已编译的 target
双击 compile 命令执行,执行完成后会在 pom.xml 配置文件内配置生成目录内生成对应实体的 QueryDSL 查询实体。
生成的查询实体如下图所示:
JPAQueryFactory 风格
QueryDSL 在支持JPA的同时,也提供了对 Hibernate 的支持。可以通过 HibernateQueryFactory
来使用。
装配 与 注入
SpringBoot注解方式装配
/**
* 方式一。使用Spring的@Configuration注解注册实例进行容器托管
*/
@Configuration
public class QueryDslConfig
@Bean
public JPAQueryFactory jpaQueryFactory(EntityManager em)
return new JPAQueryFactory(em);
/**
* 方式二。在Dao类中初始化
*/
// 实体管理
@Autowired
private EntityManager entityManager;
// 查询工厂
private JPAQueryFactory queryFactory;
// 初始化JPA查询工厂
@PostConstruct // Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
public void init()
queryFactory = new JPAQueryFactory(entityManager);
注入
@Autowired
private JPAQueryFactory queryFactory;
更新、删除
JPAQueryFactory 更新
在Querydsl JPA中,更新语句是简单的 update-set/where-execute
形式。
execute()执行后返回的是被更新的实体的数量。
注意:使用QueryDsl更新实体时需要添加事务
@Test
@Transactional
public void testUpdate()
QStudent qStudent = QStudent.student;
Long result = queryFactory.update(qStudent)
.set(qStudent.name, "haha") // 可以用if条件判断更新值来确定字段是否.set()
.setnull(qStudent.age) // 设置null值
.where(qStudent.id.eq(111L)).execute();
assertThat(result, equalTo(1L));
JPAQueryFactory 删除
删除语句是简单的 delete-where-execute
形式。
注意:使用QueryDsl删除实体时需要添加事务
@Test
@Transactional
public void testDelete()
QStudent qStudent = QStudent.student;
//删除指定条件的记录
Long result = queryFactory.delete(qStudent)
.where(qStudent.id.eq(111L))
.execute();
assertThat(result, equalTo(1L));
//删除所有记录。即不加where条件
Long totalResult = queryFactory.delete(qStudent).execute();
System.out.println(totalResult);
查询
表达式工具类
Expressions 表达式工具类
// when-then 条件表达式函数。when传参必须为名为eqTrue或eqFalse的Predicate
T cases().when(Predicate).then(T a).otherwise(T b)
DateExpression<Date> currentDate() // 返回当前日历(年-月-日)的 DateExpression
TimeExpression<Time> currentTime() // 返回当前时刻(时:分:秒)的 TimeExpression
DateTimeExpression<Date> currentTimestamp() // 返回当前时间(年-月-日 时:分:秒)的 DateTimeExpression
// exprs 均为名为eqTrue的Predicate ,则返回名为eqTrue的Predicate,否则返回eqFalse的Predicate
BooleanExpression allOf(BooleanExpression... exprs)
// exprs 至少存在一个名为eqTrue的Predicate,则返回名为eqTrue的Predicate,否则返回eqFalse的Predicate
BooleanExpression anyOf(BooleanExpression... exprs)
// 转类型为 BooleanExpression。特别注意:asBoolean(Boolean).isTrue() 才是可用Predicate
BooleanExpression asBoolean(Boolean) // asBoolean(true) <==等价==> booleanPath("true")
NumberExpression asNumber(T)
StringrExpression asString(T)
DateExpression asDate(T)
TimeExpression asTime(T)
DateTimeExpression asDateTime(T)
// 自定义语法
StringTemplate stringTemplate(String template, Object... args)
NumberTemplate<T> numberTemplate(Class<? extends T> cl, String template, Object... args)
BooleanTemplate booleanTemplate(String template, ImmutableList<?> args)
MathExpressions 数学表达式工具类
NumberExpression<A> round(Expression<A> num) // 四舍五入取整
NumberExpression<A> round(Expression<A> num, int s) // 四舍五入保留 s 位小数
NumberExpression<Double> asin(Expression<A> num) // 返回num的反正弦值。-1 <= num <= 1,否则返回null
NumberExpression<Double> acos(Expression<A> num) // 返回num的反余弦值。-1 <= num <= 1,否则返回null
// 慎用!qdsl-jpa底层是调用random()函数,mysql没有该函数,只有rand()函数,会报错,解决方案为使用QDSL-SQL查询
NumberExpression<Double> random() // 返回0到1内的随机值
NumberExpression<Double> random(int seed) // 返回一个指定的0到1内的随机值
表达式方法
注意:在select()中查询出的结果使用表达式方法处理过后,若要封装到实体类中,则都需要使用 .as(alias) 起别名指定封装到实体类中的哪个字段。
SimpleExpression 简单表达式 extends DslExpression extends Expression
// 给查询字段取别名
T as(alias)
BooleanExpression eq(T right) // 等于 equal
BooleanExpression eqAll(T... right)
BooleanExpression eqAny(T... right)
BooleanExpression ne(T right) // 不等于 not equal
BooleanExpression neAll(T... right)
BooleanExpression neAny(T... right)
BooleanExpression in(T... right)
BooleanExpression notIn(T... right)
BooleanExpression isNotNull()
BooleanExpression isNull()
// 相当于java中的switch语句。两种写法
T when(A).then(B).otherwise(C)
// 该字段的查询结果等于参数则返回null,不等于则返回查询结果。Field == A ? null : Field
SimpleExpression<T> nullif(A)
// 符合过滤条件的的总条数。 select count(table.id) from table
NumberExpression<Long> count()
ComparableExpressionBase extends SimpleExpression
// 设置默认值。返回 Field, A, B ... 顺序中第一个非null的值,若都为null则返回null
// 注意:使用该方法兜底Oracle数据库的null为空字符串时会失效,因为Oracle会把空字符串当作null
T coalesce(A, B ...)
NumberExpression 数值表达式 extends ComparableExpressionBase
NumberExpression<T> add(A) // 加
NumberExpression<T> subtract(A) // 减
NumberExpression<T> multiply(A) // 乘
NumberExpression<T> divide(A) // 除
NumberExpression<T> mod(A) // 返回余数
NumberExpression<T> floor() // 向下取整
NumberExpression<T> ceil() // 向上取整
NumberExpression<T> round() // 四舍五入取整
NumberExpression<T> max() // 返回指定数值列的最大值
NumberExpression<T> min() // 返回指定数值列的最小值
NumberExpression<T> sqrt() // 返回指定数值列的平方根
NumberExpression<T> sum() // 返回指定数值列(或分组相同数值列)的总数
NumberExpression<T> avg() // 返回指定数值列(或分组相同数值列)的平均数
NumberExpression<T> abs() // 返回指定数值列的绝对值
NumberExpression<T> negate() // 返回指定数值列的相反数
StringExpression stringValue() // 返回字符串表达式
// 数据类型转换为数字类型。type为数字基本类型的包装类.class。实体类接收字段需与type的类型一致。
NumberExpression<T> castToNum(Class<A> type)
ComparableExpression extends ComparableExpressionBase
BooleanExpression lt(T right) // 小于 less than
BooleanExpression ltAll(T... right)
BooleanExpression ltAny(T... right)
BooleanExpression gt(T right) // 大于 greater than
BooleanExpression gtAll(T... right)
BooleanExpression gtAny(T... right)
BooleanExpression loe(T right) // 小于等于 less than or equal
BooleanExpression loeAll(T... right)
BooleanExpression loeAny(T... right)
BooleanExpression goe(T right) // 大于等于 greater than or equal
BooleanExpression goeAll(T... right)
BooleanExpression goeAny(T... right)
BooleanExpression between(from, to) // from和to之间 [from, to]
BooleanExpression notBetween(from, to)
BooleanExpression 布尔表达式 extends LiteralExpression (extends ComparableExpression) implements Predicate
BooleanExpression isTrue() // 计算结果若为true,则返回名为eqTrue的Predicate,否则返回名为eqFalse的Predicate
BooleanExpression isFalse() // 计算结果若为false,则返回名为eqTrue的Predicate,否则返回名为eqFalse的Predicate
BooleanExpression not() // 返回相反的结果
BooleanExpression eq(Boolean right)
BooleanExpression and(Predicate right)
BooleanExpression andAnyOf(Predicate... predicates)
BooleanExpression or(Predicate right)
BooleanExpression orAllOf(Predicate... predicates)
StringExpressions 字符串表达式 extends LiteralExpression extends ComparableExpression
StringExpression contains(String str) // 包含参数字符串
BooleanExpression isEmpty() // 判断是否为空
BooleanExpression isNotEmpty()
// 正则匹配查询
BooleanExpression matches(Expression<String> regex)
// 模糊查询。% 为通配符,_ 表一个字符,可以传参escape指定转义字符
BooleanExpression like(String str)
BooleanExpression like(String str, char escape)
BooleanExpression endsWith(str) // 判断字符串的后缀是否为str。注意:必须使用boolean数据类型的字段接收
BooleanExpression startsWith(str) // 判断字符串的前缀是否为str。注意:必须使用boolean数据类型的字段接收
// 将字母转换大小写
StringExpression toLowerCase()
StringExpression toUpperCase()
StringExpression lower()
StringExpression upper()
StringExpression trim() // 去掉字符串两端的空格
StringExpression substring(int beginIndex) // 截取子字符串从索引位置至末尾
StringExpression concat(str) // 拼接 str
StringExpression append(str) // 在末尾添加 str
StringExpression prepend(str) // 在前面添加 str
NumberExpression<Integer> length() // 返回字符串长度
NumberExpression<Integer> locate(str) // 返回 str 的位置(从1开始),没有返回0
NumberExpression<Integer&g以上是关于JPA 之 QueryDSL-JPA 使用指南的主要内容,如果未能解决你的问题,请参考以下文章
QueryDSL 4 与 RowNumber Window 功能