QueryDSL如何在SpringJPA中使用
这篇文章将为大家详细讲解有关QueryDSL如何在Spring JPA中使用,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
员工经过长期磨合与沉淀,具备了协作精神,得以通过团队的力量开发出优质的产品。创新互联建站坚持“专注、创新、易用”的产品理念,因为“专注所以专业、创新互联网站所以易用所以简单”。公司专注于为企业提供成都做网站、网站制作、微信公众号开发、电商网站开发,小程序开发,软件按需设计等一站式互联网企业服务。
pom文件配置
QueryDSL
本身定位就是对某些技术的补充或者说是完善,其提供了对JPA
、JDBC
、JDO
等技术的支持。这里引入的是QueryDSL-JPA
,需要注意一定要引入querydsl代码生成器插件。
1.8 4.2.1 org.springframework.boot spring-boot-starter-data-jpa mysql mysql-connector-java 5.1.48 org.springframework.boot spring-boot-configuration-processor true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.junit.vintage junit-vintage-engine com.querydsl querydsl-jpa ${querydsl.version} org.springframework.boot spring-boot-maven-plugin com.mysema.maven apt-maven-plugin 1.1.3 com.querydsl querydsl-apt ${querydsl.version} process src/generated-sources/java/ com.querydsl.apt.jpa.JPAAnnotationProcessor
application配置文件
spring: datasource: ## 数据库相关配置 url: jdbc:mysql://127.0.0.1:3306/example?useSSL=false username: root password: root driver-class-name: com.mysql.jdbc.Driver # 指定驱动类 jpa: hibernate: ddl-auto: update # 自动创建表以及更新表结构,生产环境慎用 show-sql: true # 打印执行的SQL
配置类
由于QueryDSL
不提供starter
,所以需要自行准备一个配置类,代码如下所示
import com.querydsl.jpa.impl.JPAQueryFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; /** * QueryDSL配置类 * @author Null * @date 2019-10-24 */ @Configuration public class QuerydslConfig { @Autowired @PersistenceContext private EntityManager entityManager; @Bean public JPAQueryFactory queryFactory(){ return new JPAQueryFactory(entityManager); } }
启动类
启动类很简单,只需要使用@SpringBootApplication
即可
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class QuerydslJpaDemoApplication { public static void main(String[] args) { SpringApplication.run(QuerydslJpaDemoApplication.class, args); } }
实体类
主要有讲师和课程,每个课程都有一个讲师,每个讲师有多个课程,即讲师与课程的关系为一对多
课程
import lombok.Data; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; /** * 课程,一个课程对应一个讲师 * @author Null * @date 2019-10-24 */ @Data @Entity public class Course { /** * 课程ID */ @Id @GeneratedValue(strategy= GenerationType.IDENTITY) private Long id; /** * 课程名称 */ private String name; /** * 对应讲师的ID */ private Long lecturerId; }
讲师
import lombok.Data; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; /** * 讲师,一个讲师有多个课程 * @author Null * @date 2019-10-24 */ @Data @Entity public class Lecturer { /** * 讲师ID */ @Id @GeneratedValue(strategy= GenerationType.IDENTITY) private Long id; /** * 讲师名字 */ private String name; /** * 性别,true(1)为男性,false(0)为女性 */ private Boolean sex; }
Repository接口
如果要使用QuerDSL
需要Repository
接口除了继承JpaRepository
接口(此接口为Spring-JPA
提供的接口)外,还需要继承QuerydslPredicateExecutor
接口。关键示例如下:
课程Repository
import com.example.querydsl.jpa.entity.Course; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.querydsl.QuerydslPredicateExecutor; /** * 课程Repository * * @author Null * @date 2019-10-24 */ public interface CourseRepository extends JpaRepository, QuerydslPredicateExecutor { }
讲师Repository
import com.example.querydsl.jpa.entity.Lecturer; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.querydsl.QuerydslPredicateExecutor; /** * 讲师Repository * @author Null * @date 2019-10-24 */ public interface LecturerRepository extends JpaRepository, QuerydslPredicateExecutor { }
代码生成
前面配置QueryDSL
代码生成器就是用于这一步,==每次实体类有变更最好重复执行本步骤重新生成新的代码==。由于个人习惯使用IDEA
,所以以IDEA
作为演示。
双击下图内容即可生成代码了,
然后就会在src/generated-sources
目录可以看到生成的代码,包名与实体包名一致,但是类名为Q
开头的文件
上一步的截图我们可以看到其实生成的代码被IDEA
识别为普通文件了,所以我们需要标记src/generated-sources/java
目录的用途,如下图所示
标记后,效果如下,可以看到代码被正确识别了
到了这一步其实已经完成整合了,下面就开始验证是否正确整合以及展示QueryDSL
的优势了
验证整合与演示
下面我会使用单元测试来验证QueryDSL
是否正确整合以及演示一下QueryDSL
的优势
单元测试类
这里主要是单元测试类的关键内容,需要注意@BeforeEach
是Junit5
的注解,表示每个单元测试用例执行前会执行的方法其实对应Junit4
的@Before
/** * @SpringBootTest 默认不支持事务且自动回滚 * 使用@Transactional 开启事务, * 使用@Rollback(false) 关闭自动回滚 * @author Null * @date 2019-10-24 */ @SpringBootTest class QuerydslJpaDemoApplicationTests { @Autowired private CourseRepository courseRepository; @Autowired private LecturerRepository lecturerRepository; @Autowired private JPAQueryFactory queryFactory; /** * 初始化数据 */ @BeforeEach public void initData(){ // 清空数据表 courseRepository.deleteAll(); lecturerRepository.deleteAll(); // 初始化讲师 Lecturer tom=new Lecturer(); tom.setName("Tom"); tom.setSex(true); lecturerRepository.save(tom); Lecturer marry=new Lecturer(); marry.setName("Marry"); marry.setSex(false); lecturerRepository.save(marry); // 初始化课程 Course chinese=new Course(); chinese.setName("Chinese"); chinese.setLecturerId(tom.getId()); courseRepository.save(chinese); Course physics=new Course(); physics.setName("Physics"); physics.setLecturerId(tom.getId()); courseRepository.save(physics); Course english=new Course(); english.setName("English"); english.setLecturerId(marry.getId()); courseRepository.save(english); } ...省略各个用例 }
单表模糊查询
/** * 根据课程名称模糊查询课程 */ @Test public void testSelectCourseByNameLike() { // 组装查询条件 QCourse qCourse = QCourse.course; // %要自行组装 BooleanExpression expression = qCourse.name.like("P%"); System.out.println(courseRepository.findAll(expression)); }
联表查询
/** * 根据讲师姓名查课程 */ @Test public void testSelectCourseByLecturerName(){ QCourse qCourse = QCourse.course; QLecturer qLecturer = QLecturer.lecturer; // 这里包含了组装查询条件和执行查询的逻辑,组装好条件后记得执行fetch() Listcourses=queryFactory.select(qCourse) .from(qCourse) .leftJoin(qLecturer) .on(qCourse.lecturerId.eq(qLecturer.id)) .where(qLecturer.name.eq("Tom")) .fetch(); System.out.println(courses); }
更新
/** * 根据姓名更新讲师性别
* 使用@Transactional开启事务
* 使用@Rollback(false)关闭自动回滚
*/ @Test @Transactional @Rollback(false) public void testUpdateLecturerSexByName(){ QLecturer qLecturer = QLecturer.lecturer; // 更新Tom的性别为女性,返回的是影响记录条数 long num=queryFactory.update(qLecturer) .set(qLecturer.sex,false) .where(qLecturer.name.eq("Tom")) .execute(); // 这里输出被更新的记录数 System.out.println(num); }
删除
/** * 根据根据性别删除讲师 */ @Test @Transactional @Rollback(false) public void testDeleteLecturerBySex(){ QLecturer qLecturer = QLecturer.lecturer; // 删除性别为男性的讲师 long num=queryFactory.delete(qLecturer) .where(qLecturer.sex.eq(true)) .execute(); // 输出被删除的记录数 System.out.println(num); }
用例分析
从用例中可以看出其实QueryDSL
的API
更加切合原生的SQL
,基本上从代码上就可以看出你希望执行的SQL
了。
细心的朋友会发现QueryDSL
是没有insert
方法,因为JPA
提供的save()
方法已经足够处理了。
同时要记得要组装好你的SQL
后别忘记调用fetch()
或者execute()
方法。
总结
Spring Boot JPA
整合QueryDSL
的关键步骤
引入依赖和插件
编写配置类
使用插件生成代码
标记生成文件为代码
Repository继承QuerydslPredicateExecutor
QueryDSL
的API
类似原生SQL
,API
风格类似StringBuilder
的API
(Fluent API
风格)。但是不提供insert
对应的操作。
关于QueryDSL如何在Spring JPA中使用就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
本文标题:QueryDSL如何在SpringJPA中使用
文章链接:http://scyanting.com/article/pecjep.html