JPA和 QueryDSL入门
QueryDSL 使用實戰
引入?Maven?依賴
<!--QueryDSL支持--> <dependency><groupId>com.querydsl</groupId><artifactId>querydsl-apt</artifactId><scope>provided</scope> </dependency> <!--QueryDSL支持--> <dependency><groupId>com.querydsl</groupId><artifactId>querydsl-jpa</artifactId> </dependency>這里無需指定版本號,已在 spring-boot-dependencies 工程中定義。
添加 Maven 插件
添加這個插件是為了讓程序自動生成 query type (查詢實體,命名方式為:“Q”+對應實體名)。
上文引入的依賴中 querydsl-apt 即是為此插件服務的。
注:在使用過程中,如果遇到 query type 無法自動生成的情況,用maven更新一下項目即可解決(右鍵項目 -> Maven -> Update Folders)。
<plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><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>更新和刪除
?
在?JPA?中已經為我們提供了非常簡便的更新和刪除的使用方式,我們完全沒有必要使用 QueryDSL 的更新和刪除,不過這里還是給出用法,供大家參考:
@Override public Long update(String id, String nickName) {QUserModel userModel = QUserModel.userModel;// 更新return queryFactory.update(userModel).set(userModel.nickName, nickName).where(userModel.id.eq(id)).execute(); }@Override public Long delete(String id) {QUserModel userModel = QUserModel.userModel;// 刪除return queryFactory.delete(userModel).where(userModel.id.eq(id)).execute(); }查詢
QueryDSL 在查詢這方面可以說玩的非?;?#xff0c;比如一些有關 select() 和 fetch() 常用的寫法如下:
@Override public List<String> selectAllNameList() {QUserModel userModel = QUserModel.userModel;// 查詢字段return queryFactory.select(userModel.nickName).from(userModel).fetch(); }@Override public List<UserModel> selectAllUserModelList() {QUserModel userModel = QUserModel.userModel;// 查詢實體return queryFactory.selectFrom(userModel).fetch(); }@Override public List<UserDTO> selectAllUserDTOList() {QUserModel userModel = QUserModel.userModel;QLessonModel lessonModel = QLessonModel.lessonModel;// 連表查詢實體并將結果封裝至DTOreturn queryFactory.select(Projections.bean(UserDTO.class, userModel.nickName, userModel.age, lessonModel.startDate, lessonModel.address, lessonModel.name)).from(userModel).leftJoin(lessonModel).on(userModel.id.eq(lessonModel.userId)).fetch(); }@Override public List<String> selectDistinctNameList() {QUserModel userModel = QUserModel.userModel;// 去重查詢return queryFactory.selectDistinct(userModel.nickName).from(userModel).fetch(); }@Override public UserModel selectFirstUser() {QUserModel userModel = QUserModel.userModel;// 查詢首個實體return queryFactory.selectFrom(userModel).fetchFirst(); }@Override public UserModel selectUser(String id) {QUserModel userModel = QUserModel.userModel;// 查詢單個實體,如果結果有多個,會拋`NonUniqueResultException`。return queryFactory.selectFrom(userModel).fetchOne(); }復雜查詢操作
上面列舉了簡單的查詢,但實際我們會遇到相當復雜的操作,比如子查詢,多條件查詢,多表連查,使用示例如下:
@Service public class LessonServiceImpl implements LessonService {@AutowiredJPAQueryFactory queryFactory;@Overridepublic List<LessonModel> findLessonList(String name, Date startDate, String address, String userId) throws ParseException {QLessonModel lessonModel = QLessonModel.lessonModel;SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");// 多條件查詢示例return queryFactory.selectFrom(lessonModel).where(lessonModel.name.like("%" + name + "%").and(lessonModel.address.contains(address)).and(lessonModel.userId.eq(userId)).and(lessonModel.startDate.between(simpleDateFormat.parse("2018-12-31 00:00:00"), new Date()))).fetch();}@Overridepublic List<LessonModel> findLessonDynaList(String name, Date startDate, String address, String userId) throws ParseException {QLessonModel lessonModel = QLessonModel.lessonModel;SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");// 動態查詢示例BooleanBuilder builder = new BooleanBuilder();if (!StringUtils.isEmpty(name)){builder.and(lessonModel.name.like("%" + name + "%"));}if (startDate != null) {builder.and(lessonModel.startDate.between(simpleDateFormat.parse("2018-12-31 00:00:00"), new Date()));}if (!StringUtils.isEmpty(address)) {builder.and(lessonModel.address.contains(address));}if (!StringUtils.isEmpty(userId)) {builder.and(lessonModel.userId.eq(userId));}return queryFactory.selectFrom(lessonModel).where(builder).fetch();}@Overridepublic List<LessonModel> findLessonSubqueryList(String name, String address) {QLessonModel lessonModel = QLessonModel.lessonModel;// 子查詢示例,并無實際意義return queryFactory.selectFrom(lessonModel).where(lessonModel.name.in(JPAExpressions.select(lessonModel.name).from(lessonModel).where(lessonModel.address.eq(address)))).fetch();} }Mysql 聚合函數
QueryDSL 已經內置了一些常用的 Mysql 的聚合函數,如果遇到 QueryDSL 沒有提供的聚合函數也無需慌張, QueryDSL 為我們提供了 Expressions 這個類,我們可以使用這個類手動拼接一個就好,如下示例:
@Override public String mysqlFuncDemo(String id, String nickName, int age) {QUserModel userModel = QUserModel.userModel;// Mysql 聚合函數示例// 聚合函數-avg()Double averageAge = queryFactory.select(userModel.age.avg()).from(userModel).fetchOne();// 聚合函數-sum()Integer sumAge = queryFactory.select(userModel.age.sum()).from(userModel).fetchOne();// 聚合函數-concat()String concat = queryFactory.select(userModel.nickName.concat(nickName)).from(userModel).fetchOne();// 聚合函數-contains()Boolean contains = queryFactory.select(userModel.nickName.contains(nickName)).from(userModel).where(userModel.id.eq(id)).fetchOne();// 聚合函數-DATE_FORMAT()String date = queryFactory.select(Expressions.stringTemplate("DATE_FORMAT({0},'%Y-%m-%d')", userModel.createDate)).from(userModel).fetchOne();return null; }小結
有關 QueryDSL 的介紹到這里就結束了,不知道各位讀者看了上面的示例,有沒有一種直接讀 SQL 的感覺,而且這種 SQL 還是使用 OOM 的思想,將原本 Hibernate 沒有做好的事情給出了一個相當完美的解決方案,上手簡單易操作,而又無需寫 SQL ,實際上我們操作的還是對象類。
?
總結
以上是生活随笔為你收集整理的JPA和 QueryDSL入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: QImage 图像处理
- 下一篇: Java设计模式-外观模式(Facade