关于 QueryDSL 配置和使用(详细)
關(guān)于 QueryDSL?
? ? 最近寫項(xiàng)目,使用到了 Jpa 這個(gè) ORM 規(guī)范支持,使用注解的方式實(shí)現(xiàn) Sql ,但是用過 Jpa 的同學(xué)都知道 Jpa 對(duì)于單表操作很靈活,但是對(duì)于復(fù)雜一些的 SQL 就是很不友好了,所以這個(gè)地方我們就用到了 QueryDSL 來實(shí)現(xiàn)復(fù)雜的 Sql(另外強(qiáng)行安利一波 Tk-MyBatis)
什么是 QueryDSL ??
? ??QueryDSL僅僅是一個(gè)通用的查詢框架,專注于通過 JavaAPI 構(gòu)建類型安全的 Sql 查詢,也可以說 QueryDSL 是基于各種 ORM 框架以及 Sql 之上的一個(gè)通用的查詢框架,QueryDSL 的查詢,類是于 SQL 查詢,很全面只不過一個(gè)是用 SQL 一個(gè)是用代碼來代替 SQL?--?不多了解 QueryDSL 的其他方面了,直接進(jìn)入看配置和代碼吧,畢竟博主也是剛剛接觸這個(gè)查詢框架,就不做過多的誤導(dǎo)了
說一下,下面示例的環(huán)境 -- MyBatis + IDEA + JPA + QueryDSL
---------------------------------------------------- 手動(dòng)分界線?----------------------------------------------------
以下為項(xiàng)目操作(創(chuàng)建項(xiàng)目的操作就先省略掉了,這個(gè)應(yīng)該都會(huì),不會(huì)的可以去看博主的其他博客):
首先配置 pom.xml 更古不變的定律? T_T!!? 對(duì)了在安利一個(gè)插件 lombok,配合 QueryDSL 可能會(huì)更好
<!-- QueryDSL 相關(guān)依賴 --> <dependency><groupId>com.querydsl</groupId><artifactId>querydsl-jpa</artifactId> </dependency> <dependency><groupId>com.querydsl</groupId><artifactId>querydsl-apt</artifactId><scope>provided</scope> </dependency> <!-- lombok 相關(guān)依賴 --> <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version><scope>provided</scope> </dependency>Ps:lombok 可以已注解的方式來對(duì)代碼進(jìn)行簡(jiǎn)化,省去了 get 和 set 方法,至于怎么使用 lombok ,先看本文示例吧
配置?application.properties 文件
server.port=8080 server.servlet.context-path=/ server.tomcat.uri-encoding=utf-8 ###添加 MySQL 數(shù)據(jù)庫配置 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/boot_test?serverTimezone=UTC&characterEncoding=UTF-8&useUnicode=true ###用戶名 spring.datasource.username=xxx ###密碼 spring.datasource.password=xxx ###驅(qū)動(dòng) spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #是否自動(dòng)生/更新成表,根據(jù)什么策略 spring.jpa.hibernate.ddl-auto=update #JPA配置 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect spring.jpa.properties.hibernate.legacy_limit_handler=true #是否展示sql spring.jpa.show-sql= true創(chuàng)建 entiy?層,因?yàn)橐葎?chuàng)建完實(shí)體類才可以去生成 QueryDSL
package com.cs.querydsl.model;import lombok.Data; import org.hibernate.annotations.GenericGenerator;import javax.persistence.*;/*** @ClassName:User* @Description:TODO User 實(shí)體類* @Author LinLuoChen* @Date 2019/7/10/14:02* @Version V1.0**/@Data // lombok 工具省去了 GET SET 方法 @Entity // 聲明這個(gè)是一個(gè)實(shí)體類 @Table(name="user") // 對(duì)應(yīng)的數(shù)據(jù)庫的那個(gè)表 public class User {/*** @Description ID* @Author LinLuoChen* @Date 10:44**/@Id@GenericGenerator(name="id", strategy="uuid") // 這里我們的 ID 用的是 UUID@GeneratedValue(generator="id")private Integer id;/*** @Description 姓名* @Author LinLuoChen* @Date 10:44**/@Column(name = "name")private String name;/*** @Description 密碼* @Author LinLuoChen* @Date 10:44**/@Column(name = "password")private String password; }然后生成我們的 Q實(shí)體類,第一步點(diǎn)擊右側(cè) Maven 然后選擇第一個(gè)文件夾,雙擊 compile 它會(huì)自動(dòng)運(yùn)行,運(yùn)行成功后會(huì)生成一個(gè) QUser 的實(shí)體類 ,因?yàn)槲覀兊膶?shí)體類叫做 User 他是根據(jù)我們實(shí)體類來生成的
開始編寫 Dao 層,引入JPA 的接口 -- !!重要 !!!
package com.cs.querydsl.dao;import com.cs.querydsl.model.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.PagingAndSortingRepository;/*** @ClassName:UserDao* @Description:TODO 用來繼承 Jpa 接口* @Author LinLuoChen* @Date 2019/7/10/14:06* @Version V1.0**/ public interface UserDao extends JpaRepository<User, String>, JpaSpecificationExecutor<User>, PagingAndSortingRepository<User, String> {// ----- }這里我們省略 Service 層 直接看 Impl 接口實(shí)現(xiàn)類,這里就先寫一個(gè)單表查詢進(jìn)行測(cè)試
package com.cs.querydsl.service.impl;import com.cs.querydsl.dao.UserDao; import com.cs.querydsl.model.QUser; import com.cs.querydsl.model.User; import com.cs.querydsl.service.UserService; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thymeleaf.util.StringUtils;import javax.annotation.PostConstruct; import javax.persistence.EntityManager; import java.util.List;/*** @ClassName:UserServiceImpl* @Description:TODO 接口實(shí)現(xiàn)類* @Author LinLuoChen* @Date 2019/7/10/14:09* @Version V1.0**/ @Service public class UserServiceImpl implements UserService {@AutowiredUserDao userDao;@Autowiredprivate EntityManager entityManager;//查詢工廠實(shí)體private JPAQueryFactory queryFactory;//實(shí)例化控制器完成后執(zhí)行該方法實(shí)例化JPAQueryFactory@PostConstructpublic void initFactory(){queryFactory = new JPAQueryFactory(entityManager);}/*** @Description 查詢?nèi)? @Author LinLuoChen* @Date 10:53* @return java.util.List<com.cs.querydsl.model.User>**/@Overridepublic List<User> findAll(User user) {// 使用 QueryDSL 進(jìn)行查詢QUser qUser = QUser.user;// 定于獲取條件BooleanBuilder booleanBuilder = new BooleanBuilder();// 要查詢的條件if(!StringUtils.isEmpty(user.getName())){// 放入要查詢的條件信息booleanBuilder.and(qUser.name.contains(user.getName()));}// queryFactory 是上方定義的工廠實(shí)體 // select(生成的實(shí)體類的字段).from(生成實(shí)體類的名稱).where(上方要查詢的條件).orderBy(排序).fetch()進(jìn)行查詢r(jià)eturn queryFactory.select(qUser).from(qUser).where(booleanBuilder).orderBy(qUser.name.desc()).fetch();} }我們直接寫一個(gè)測(cè)試類進(jìn)行測(cè)試
package com.cs.querydsl;import com.cs.querydsl.model.User; import com.cs.querydsl.service.UserService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner;import java.util.List;@RunWith(SpringRunner.class) @SpringBootTest public class QuerydslApplicationTests {@AutowiredUserService userService;@Testpublic void contextLoads() {}/*** @Description 測(cè)試查詢?nèi)糠椒? @Author LinLuoChen* @Date 11:22**/@Testpublic void QueryDSLTest(){User user = new User();List<User> list = userService.findAll(user);System.out.println(list);}}測(cè)試結(jié)果,可以運(yùn)行 ~~
雖然說 QueryDSL 也可以做增刪改查,但是個(gè)人不建議使用(僅限單表),因?yàn)閱伪聿僮?#xff0c;其實(shí)使用?Jpa 就可以了,包括 Jpa 的動(dòng)態(tài)查詢,都是很適合單表的,不管是代碼量還是效率個(gè)人感覺都比 QueryDSL 要快,尤其是代碼量,少了不止一點(diǎn)半點(diǎn),但是連表操作的話,就比較偏向于 QueryDSL 了,特別好用!!下邊是連表操作的 QueryDSL ,另外說一下上邊只是演示一下 QueryDSL 的使用方法,單表還是建議用 Jpa 比較快!
---------------------------------------------------- 手動(dòng)分界線?----------------------------------------------------?
package com.cs.querydsl.service.impl;import com.cs.querydsl.dao.LocDao; import com.cs.querydsl.model.Loc; import com.cs.querydsl.model.QLoc; import com.cs.querydsl.model.QUser; import com.cs.querydsl.service.LocService; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.QueryResults; import com.querydsl.core.Tuple; import com.querydsl.jpa.impl.JPAQueryFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.thymeleaf.util.StringUtils;import javax.annotation.PostConstruct; import javax.persistence.EntityManager; import java.util.List; import java.util.stream.Collectors;/*** @ClassName:LocServiceImpl* @Description:TODO 接口實(shí)現(xiàn)類* @Author LinLuoChen* @Date 2019/7/10/14:09* @Version V1.0**/ @Service public class LocServiceImpl implements LocService {@AutowiredLocDao locDao;@Autowiredprivate EntityManager entityManager;//查詢工廠實(shí)體private JPAQueryFactory queryFactory;//實(shí)例化控制器完成后執(zhí)行該方法實(shí)例化JPAQueryFactory@PostConstructpublic void initFactory(){queryFactory = new JPAQueryFactory(entityManager);}/*** @Description 查詢?nèi)? @Author LinLuoChen* @Date 10:53* @return java.util.List<com.cs.querydsl.model.Loc>**/@Overridepublic List<Loc> findAll(Loc loc) {// 使用 QueryDSL 進(jìn)行查詢QLoc qLoc = QLoc.loc1;QUser qUser = QUser.user;// 定于獲取條件BooleanBuilder booleanBuilder = new BooleanBuilder();// 要查詢的條件if(!StringUtils.isEmpty(loc.getLoc())){// 放入要查詢的條件信息booleanBuilder.and(qLoc.loc.contains(loc.getLoc()));}//連接查詢條件(Loc.id = User.id )booleanBuilder.and(qLoc.id.eq(qUser.id));// 使用 QueryDSL 進(jìn)行多表聯(lián)合查詢QueryResults<Tuple> listResult = queryFactory.select(QLoc.loc1,QUser.user).from(qLoc, qUser)//查詢兩表.where(booleanBuilder).fetchResults();//遍歷 java8 自帶流轉(zhuǎn)換成集合List<Loc> collect = listResult.getResults().stream().map(tuple -> {Loc lcs = tuple.get(qLoc);return lcs;}).collect(Collectors.toList());return collect;} }查看結(jié)果
源碼示例地址:https://download.csdn.net/download/qq_36537546/11356940
總結(jié)
以上是生活随笔為你收集整理的关于 QueryDSL 配置和使用(详细)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。