1 QueryDSL介绍
1.1 背景
QueryDSL的诞生解决了HQL查询类型安全方面的缺陷;HQL查询的扩展需要用字符串拼接的方式进行,这往往会导致代码的阅读困难;通过字符串对域类型和属性的不安全引用又是HQL面临的问题。
随着类型安全的域模型给软件开发带来的巨大好处,域的更改可以直接反应在查询上,而且随着域的更改查询也会自动随着改变。(即:同一套查询,只需要通过改变域就可以实现不同的查询)
针对Hibernate的HQL是Querydsl的第一个目标语言,但现在它支持JPA,JDO,JDBC,Lucene,Hibernate Search,MongoDB,Collections和RDFBean作为后端。
1.2 原则
1.2.1 类型安全
查询是根据生成的查询类型进行构建的,这些生成的查询类型反映了你域类型的属性。调用相关查询方法来构建查询时也是完全以一种类型安全的方式进行
1.2.2 一致性
查询的路径和操作在所有的实例中都是一样使用,查询接口也有一个通用的接口
1.3 JPA
Querydsl定义了用于在持久化域模型数据之上查询的一般静态类型语法,JPA是QueryDSL的主要集成技术之一
jpa -> 点击前往
2 在springBoot项目中集成QueryDSL
2.1 软件版本说明
2.2 创建SpringBoot项目
利用IDEA创建一个SpringBoot项目,并添加web、jpa、mysql依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.test.demo</groupId> <artifactId>query_demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>query_demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2.2.1 修改maven配置
将maven配置成自己的
2.2.2 配置数据连接
坑01:如果现在直接启动项目的会回报错,报错信息如下,报错的原因是我们导入了JPA和mysql这两个和数据库相关的依赖,但是我们并没有在项目中配置先关的连接信息
server: servlet: context-path: /dev port: 9998 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/springboot?useUnicode=true&characterEncoding=UTF-8&&useSSL=false driver-class-name: com.mysql.jdbc.Driver username: root password: 182838 # jpa: # database: mysql # properties: # hibernate: # show-sql: true # format-sql: true jpa: database: mysql show-sql: true
2.2.3 编写一个控制类,启动项目
package cn.test.demo.query_demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author 王杨帅 * @create 2018-03-29 21:25 * @desc 测试控制类 **/ @RestController @RequestMapping(value = "/test") public class TestController { @GetMapping(value = "connect") public String connect() { String resp = "测试类连接成功"; System.out.println(resp); return resp; } }
到这里,整个SpringBoot项目就已经搭建成功啦,下面就开始在SpringBoot项目中集成QueryDSL框架
2.3 配置项目热部署
参考博文:点击前往
2.3.1 引入lombok
lombok提供了一些简化代码的方式,例如:get/set直接利用注解实现、提供了self4j日志
参考博文:点击前往
2.4 集成QueryDSL
2.4.1 引入QueryDSL相关依赖
<dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <version>${querydsl.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> <version>${querydsl.version}</version> </dependency>
2.4.2 配置Maven APT插件
QueryDSL框架会利用maven的插件来根据标注了@Entity的实体类生成该实体类对应的查询类型
<!--添加QueryDSL插件支持--> <plugin> <groupId>com.mysema.maven</groupId> <artifactId>apt-maven-plugin</artifactId> <version>1.1.3</version> <executions> <execution> <goals> <goal>process</goal> </goals> <configuration> <outputDirectory>target/generated-sources/java</outputDirectory> <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor> </configuration> </execution> </executions> </plugin>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.test.demo</groupId> <artifactId>query_demo</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>query_demo</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--lombok相关--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--热部署相关--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <!--QueryDSL相关--> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <version>${querydsl.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> <version>${querydsl.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin> <!--添加QueryDSL插件支持--> <plugin> <groupId>com.mysema.maven</groupId> <artifactId>apt-maven-plugin</artifactId> <version>1.1.3</version> <executions> <execution> <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>
2.4.3 在数据库创建一个测试表
DROP TABLE IF EXISTS `querydsl_demo_student`; CREATE TABLE `querydsl_demo_student` ( `id` int(36) NOT NULL, `name` varchar(10) NOT NULL, `age` int(3) NOT NULL, `address` varchar(24) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/* Navicat MySQL Data Transfer Source Server : mysql5.4 Source Server Version : 50540 Source Host : localhost:3306 Source Database : springboot Target Server Type : MYSQL Target Server Version : 50540 File Encoding : 65001 Date: 2018-03-29 22:01:47 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `querydsl_demo_student` -- ---------------------------- DROP TABLE IF EXISTS `querydsl_demo_student`; CREATE TABLE `querydsl_demo_student` ( `id` int(36) NOT NULL, `name` varchar(10) NOT NULL, `age` int(3) NOT NULL, `address` varchar(24) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of querydsl_demo_student -- ---------------------------- INSERT INTO `querydsl_demo_student` VALUES ('1', 'warrior', '12', '渝足'); INSERT INTO `querydsl_demo_student` VALUES ('2', 'fury', '24', '广工');
2.4.4 根据数据库表创建对应的实体类
package cn.test.demo.query_demo.model.javaModel; import lombok.Data; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import java.io.Serializable; /** * @author 王杨帅 * @create 2018-03-29 21:52 * @desc 学生实体类 **/ @Entity @Data @Table(name = "querydsl_demo_student") public class Student implements Serializable { @Id private Long id; private String name; private Integer age; private String address; }
2.4.5 创建JPA基本接口
所有其它的持久层JPA接口都通过集成该接口
技巧01:@NoRepositoryBean 注解是排除该基础接口被实例化
坑01:如果不添加@NoRepositoryBean 注解会报错
package cn.test.demo.query_demo.dao; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.data.repository.NoRepositoryBean; /** * @author 王杨帅 * @create 2018-03-29 21:5 * @desc jpa基础接口 **/ @NoRepositoryBean public interface BaseJPA<T> extends JpaRepository<T,Long>, JpaSpecificationExecutor<T>, QuerydslPredicateExecutor<T> { }
2.4.6 创建逻辑JPA
技巧01:这里和原生的JPA写法大致相同,只不过我们在这里利用基本JPA做了已成封装而已
package cn.test.demo.query_demo.dao; import cn.test.demo.query_demo.model.javaModel.Student; /** * @author 王杨帅 * @create 2018-03-29 22:07 * @desc **/ public interface StudentJPA extends BaseJPA<Student> { }
2.4.7 利用IDEA生成查询实体
坑01:如果导入了QueryDSL相关依赖,而且在项目中有@Entity标注的实体类,在没有实现实体类对应的查询类型时启动项目时会报错,报错信息为:找不到XX查询实体
3 利用QueryDSL实现单标的CRUD
3.1 查询所有的数据
3.1.1 直接利用SpringDataJPA提供的方法实现
》编写一个Student控制层类
package cn.test.demo.query_demo.controller; import cn.test.demo.query_demo.dao.StudentJPA; import cn.test.demo.query_demo.model.javaModel.Student; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.List; /** * @author 王杨帅 * @create 2018-03-29 21:25 * @desc 测试控制类 **/ @RestController @RequestMapping(value = "/test") @Slf4j public class TestController { @Resource private StudentJPA studentJPA; @GetMapping(value = "/connect") public String connect() { String resp = "测试类连接成功H ELLO "; log.error("测试Error"); System.out.println(resp); return resp; } @GetMapping(value = "/findAll") public List<Student> findAll() { return studentJPA.findAll(); } }
》依赖注入Student持久层JPA
@Resource private StudentJPA studentJPA;
》利用StudentJPA实现查询所有客户信息
@GetMapping(value = "/findAll") public List<StudentModel> findAll() { List<StudentModel> studentModelList = studentJPA.findAll(); if(studentModelList.isEmpty()) { // TODO: 抛出自定义异常 -> 无任何学生数据 return null; } else { return studentModelList; } }
package cn.test.demo.query_demo.controller; import cn.test.demo.query_demo.dao.StudentJPA; import cn.test.demo.query_demo.model.javaModel.StudentModel; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.List; /** * @author 王杨帅 * @create 2018-03-30 8:19 * @desc 学生控制层 **/ @RestController @RequestMapping(value = "/student") @Slf4j public class StudentController { @Resource private StudentJPA studentJPA; @GetMapping(value = "/connect") public String connect() { String resp = "Student控制层连接测试"; log.info(resp); return resp; } @GetMapping(value = "/findAll") public List<StudentModel> findAll() { List<StudentModel> studentModelList = studentJPA.findAll(); if(studentModelList.isEmpty()) { // TODO: 抛出自定义异常 -> 无任何学生数据 return null; } else { return studentModelList; } } }
3.1.2 利用QueryDSL实现
》依赖注入实体管理者
@Autowired private EntityManager entityManager;
》声明JPA查询工厂
private JPAQueryFactory jpaQueryFactory;
》实例化JPA查询工厂
技巧01:@PostConstruct 注解的功能是在类初始化时执行相关的方法,此处是为了在类初始化时就完成JPA查询对象的实例化
@PostConstruct public void initFactory() { jpaQueryFactory = new JPAQueryFactory(entityManager); log.info("初始化JPA查询工厂成功"); }
》引入inject依赖
如果不引入inject依赖,那么在初始化JPA实例化工厂时会出错,错误信息为“找不到相关class文件”
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency>
》编写QueryDSL查询
技巧01:利用和实体类StudentModel对应的查询实体类QStudentModel实例化出一个和实体类StudentModel对应的查询实体对象_Q_StudentModel
技巧02:在QueryDSL中用到的东西大部分都是和查询实体对象相关的
技巧03:selectFrom() 方法时指明需要查询的字段以及从个表查询,只不过这里的查询字段以及表都是利用查询实体对象来代替的,而且selectFrom()是select()和from()的结合版本,仅仅限于单表这样使用
技巧04:fetch() 方法是执行查询并返回查询到的数据集合
坑01:fetch() 查询到的数据集合和selectFrom() 中指定的查询实体对象对应的数据库实体类型一致;在本案例中fetch() 返回的就是 StudentModel 对象组成的集合
@GetMapping(value = "/queryAll") public List<StudentModel> queryAll() { // 01 使用queryDSL查询 QStudentModel _Q_StudentModel = QStudentModel.studentModel; // 02 查询并返回结果 return jpaQueryFactory .selectFrom(_Q_StudentModel) .orderBy(_Q_StudentModel.id.asc()) .fetch(); }
3.2 根据ID查询数据
3.2.1 利用SpringDataJPA提供的方法实现
》依赖注入 StudnetJPA
@Autowired private StudentJPA studentJPA;
》调用 SpringJPA 提供的方法
@GetMapping(value = "/queryDetail") public StudentModel queryDetail( @RequestParam("id") Long id ) { System.out.println(studentJPA.findById(id).get()); return studentJPA.findById(id).get(); }
》效果展示
3.2.2 利用QueryDSL实现
》依赖注入管理实体
@Autowired private EntityManager entityManager;
》声明JPA查询工厂
private JPAQueryFactory jpaQueryFactory;
》实例化JPA查询工厂
@PostConstruct public void initFactory() { jpaQueryFactory = new JPAQueryFactory(entityManager); log.info("初始化JPA查询工厂成功"); }
》实例化查询对象并调用QueryDSL提供的方法完成查询操作
技巧01:where() 方法是设定条件的方法
技巧02:fetchOne() 方法时执行查询并返回一条查询到的第一条记录
@GetMapping(value = "/queryDetail") public StudentModel queryDetail( @RequestParam("id") Long id ) { log.info("获取到的ID参数为:{}", id); QStudentModel _Q_studentModel = new QStudentModel("hello"); StudentModel studentModel = jpaQueryFactory .select(_Q_studentModel) .from(_Q_studentModel) .where(_Q_studentModel.id.eq(id)) .fetchOne(); log.info("获取到的数据为:{}", studentModel); return studentModel; }
》效果展示
3.3 更新数据
3.3.1 利用SpringDataJPA提供的方法实现
坑01:利用SpringDataJPA提供的save() 方法更新数据时,是根据主键去更新的;需要传入一个对象到save() 方法中去,如果该对象的ID在数据库中不存在就会在数据库中新增一条记录,只用当这个对象的ID在数据库中存在时才会进行数据的更新操作;故:SpringDataJPA提供的save() 方法既可以实现更新操作又可以实现新增操作
》依赖注入StudnetJPA
@Autowired private StudentJPA studentJPA;
》调用SpringDataJPA的save() 方法
@PutMapping(value = "/update") public StudentModel update( @RequestBody StudentModel studentModel ) { log.info("获取到的ID参数为:{}", studentModel); StudentModel result = studentJPA.save(studentModel); log.info("更新后的返回数据为:{}", result); return result; }
》效果展示
3.3.2 利用QueryDSL实现
》依赖注入实体管理对象
@Autowired private EntityManager entityManager;
》声明JPA查询工厂
private JPAQueryFactory jpaQueryFactory;
》初始化JPA查询工厂
@PostConstruct public void initFactory() { jpaQueryFactory = new JPAQueryFactory(entityManager); log.info("初始化JPA查询工厂成功"); }
》实例化查询对象并利用QueryDSL相关方法实现
坑01:利用QueryDSL进行处查询操作外的所有操作都必须添加事物控制注解,否则会报错;如果利用SpringDataJPA的先关方法在不添加事物注解的情况下时不会报错的,由此可见QueryDSL还是比较安全的
技巧01:update() 方法是指定更新那个数据表,只不过这里是利用查询实体类对象来代替表名
技巧02:set() 方法是设定更新字段和更新值,参数一是待更新的字段名称,参数2是更新值;只不过更新字段是利用查询实体对象的属性代替
技巧03:where() 方法是添加条件限制
技巧04:execute() 方法是执行更新操作,该方法的返回值是一个Long类型,代表更新的记录数
@Transactional @PutMapping(value = "/update") public Long update( @RequestBody StudentModel studentModel ) { log.info("获取到的ID参数为:{}", studentModel); QStudentModel _Q_studentModel = QStudentModel.studentModel; Long result = jpaQueryFactory.update(_Q_studentModel) .set(_Q_studentModel.name, studentModel.getName()) .set(_Q_studentModel.address, studentModel.getAddress()) .where(_Q_studentModel.id.eq(studentModel.getId())) .execute(); log.info("更新的记录数为:{}", result); return result; }
package cn.test.demo.query_demo.controller; import cn.test.demo.query_demo.dao.StudentJPA; import cn.test.demo.query_demo.model.javaModel.QStudentModel; import cn.test.demo.query_demo.model.javaModel.StudentModel; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.persistence.EntityManager; import java.util.List; import java.util.Optional; /** * @author 王杨帅 * @create 2018-03-30 8:19 * @desc 学生控制层 **/ @RestController @RequestMapping(value = "/student") @Slf4j public class StudentController { @Autowired private StudentJPA studentJPA; @Autowired private EntityManager entityManager; private JPAQueryFactory jpaQueryFactory; @PostConstruct public void initFactory() { jpaQueryFactory = new JPAQueryFactory(entityManager); log.info("初始化JPA查询工厂成功"); } @GetMapping(value = "/queryAll") public List<StudentModel> queryAll() { // 01 使用queryDSL查询 QStudentModel _Q_StudentModel = QStudentModel.studentModel; // 02 查询并返回结果 return jpaQueryFactory .selectFrom(_Q_StudentModel) .orderBy(_Q_StudentModel.id.asc()) .fetch(); } @Transactional @PutMapping(value = "/update") public Long update( @RequestBody StudentModel studentModel ) { log.info("获取到的ID参数为:{}", studentModel); QStudentModel _Q_studentModel = QStudentModel.studentModel; Long result = jpaQueryFactory.update(_Q_studentModel) .set(_Q_studentModel.name, studentModel.getName()) .set(_Q_studentModel.address, studentModel.getAddress()) .where(_Q_studentModel.address.eq(studentModel.getAddress())) .execute(); log.info("更新的记录数为:{}", result); return result; } }
3.4 删除数据
3.4.1 利用SpringDataJPA提供的方法实现
》SpringDataJPA提供了多种删除方法,常用的有下面三种方法
deleteById() -> 根据ID删除 -> 需要传入一个ID作为参数
delete() -> 根据实体类对象删除 -> 需要传入一个实体对象作为参数
deleteAll() -> 删除所有数据 -> 不需要传入任何参数
》依赖注入StudnetJPA
@Autowired private StudentJPA studentJPA;
》调用SpringDataJPA的deleteById方法
@DeleteMapping(value = "/delete") public void delete(@RequestParam("id") Long id) { log.info("获取到的参数为:{}", id); studentJPA.deleteById(id); }
3.4.2 利用QueryDSL提供的方法实现
》前面三个步骤照旧
》实例化查询实体对象并调用QueryDSL提供的方法实现删除操作
@Transactional @DeleteMapping(value = "/delete") public Long delete(@RequestParam("age") Long age) { log.info("获取到的参数为:{}", age); QStudentModel _Q_studentModel = QStudentModel.studentModel; Long result = jpaQueryFactory.delete(_Q_studentModel) .where(_Q_studentModel.age.lt(age)) .execute(); log.info("删除的记录数为:{}", result); return result; }
package cn.test.demo.query_demo.controller; import cn.test.demo.query_demo.dao.StudentJPA; import cn.test.demo.query_demo.model.javaModel.QStudentModel; import cn.test.demo.query_demo.model.javaModel.StudentModel; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.persistence.EntityManager; import java.util.List; import java.util.Optional; /** * @author 王杨帅 * @create 2018-03-30 8:19 * @desc 学生控制层 **/ @RestController @RequestMapping(value = "/student") @Slf4j public class StudentController { @Autowired private StudentJPA studentJPA; @Autowired private EntityManager entityManager; private JPAQueryFactory jpaQueryFactory; @PostConstruct public void initFactory() { jpaQueryFactory = new JPAQueryFactory(entityManager); log.info("初始化JPA查询工厂成功"); } @GetMapping(value = "/queryAll") public List<StudentModel> queryAll() { // 01 使用queryDSL查询 QStudentModel _Q_StudentModel = QStudentModel.studentModel; // 02 查询并返回结果 return jpaQueryFactory .selectFrom(_Q_StudentModel) .orderBy(_Q_StudentModel.id.asc()) .fetch(); } @Transactional @PutMapping(value = "/update") public Long update( @RequestBody StudentModel studentModel ) { log.info("获取到的ID参数为:{}", studentModel); QStudentModel _Q_studentModel = QStudentModel.studentModel; Long result = jpaQueryFactory.update(_Q_studentModel) .set(_Q_studentModel.name, studentModel.getName()) .set(_Q_studentModel.address, studentModel.getAddress()) .where(_Q_studentModel.address.eq(studentModel.getAddress())) .execute(); log.info("更新的记录数为:{}", result); return result; } @Transactional @DeleteMapping(value = "/delete") public Long delete(@RequestParam("age") Long age) { log.info("获取到的参数为:{}", age); QStudentModel _Q_studentModel = QStudentModel.studentModel; Long result = jpaQueryFactory.delete(_Q_studentModel) .where(_Q_studentModel.age.lt(age)) .execute(); log.info("删除的记录数为:{}", result); return result; } }