欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring JPA整合QueryDSL的示例代碼

 更新時(shí)間:2019年10月25日 09:12:28   作者:Null  
這篇文章主要介紹了Spring JPA整合QueryDSL的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

Spring JPA是目前比較常用的ORM解決方案,但是其對于某些場景并不是特別的方便,例如查詢部分字段,聯(lián)表查詢,子查詢等。

而接下來我會(huì)介紹與JPA形成互補(bǔ),同時(shí)也是與JPA兼容得很好的框架QueryDSL

同時(shí)由于目前主流使用Spring Boot,所以本文也會(huì)基于Spring Boot來進(jìn)行演示

如果對于長文無感,但是又希望了解QueryDSL可以直接查看文章最后的總結(jié)

環(huán)境信息

以下為示例的關(guān)鍵環(huán)境信息

  • JDK 1.8
  • maven 3.6.1
  • SpringBoot 2.2.0.RELEASE
  • IntelliJ IDEA 2019.2.3
  • lombok
  • mysql-5.7

源碼地址

https://github.com/spring-based-solutions/querydsl-jpa-demo

項(xiàng)目整合

pom文件配置

QueryDSL本身定位就是對某些技術(shù)的補(bǔ)充或者說是完善,其提供了對JPA、JDBC、JDO等技術(shù)的支持。這里引入的是QueryDSL-JPA,需要注意一定要引入querydsl代碼生成器插件。

  <properties>
    <java.version>1.8</java.version>
    <querydsl.version>4.2.1</querydsl.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!--使用版本較老的mysql驅(qū)動(dòng)包,用于連接mysql-5.7-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.48</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-configuration-processor</artifactId>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      <exclusions>
        <exclusion>
          <groupId>org.junit.vintage</groupId>
          <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

    <!--引入querydsl-jpa依賴-->
    <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>
      </plugin>
      <!--引入querydsl代碼生成器插件-->
      <plugin>
        <groupId>com.mysema.maven</groupId>
        <artifactId>apt-maven-plugin</artifactId>
        <version>1.1.3</version>
        <dependencies>
          <dependency>
            <groupId>com.querydsl</groupId>
            <artifactId>querydsl-apt</artifactId>
            <version>${querydsl.version}</version>
          </dependency>
        </dependencies>
        <executions>
          <!--設(shè)置插件生效的maven生命周期-->
          <execution>
            <goals>
              <goal>process</goal>
            </goals>
            <configuration>
              <!--配置生成文件的目錄--> 
              <outputDirectory>src/generated-sources/java/</outputDirectory>
              <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

application配置文件

spring:
 datasource:
  ## 數(shù)據(jù)庫相關(guān)配置
  url: jdbc:mysql://127.0.0.1:3306/example?useSSL=false
  username: root
  password: root
  driver-class-name: com.mysql.jdbc.Driver # 指定驅(qū)動(dòng)類
 jpa:
  hibernate:
   ddl-auto: update # 自動(dòng)創(chuàng)建表以及更新表結(jié)構(gòu),生產(chǎn)環(huán)境慎用
  show-sql: true # 打印執(zhí)行的SQL

配置類

由于QueryDSL不提供starter,所以需要自行準(zhǔn)備一個(gè)配置類,代碼如下所示

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);
  }

}

啟動(dòng)類

啟動(dòng)類很簡單,只需要使用@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);
  }
}

實(shí)體類

主要有講師和課程,每個(gè)課程都有一個(gè)講師,每個(gè)講師有多個(gè)課程,即講師與課程的關(guān)系為一對多

課程

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**
 * 課程,一個(gè)課程對應(yīng)一個(gè)講師
 * @author Null
 * @date 2019-10-24
 */
@Data
@Entity
public class Course {
  /**
   * 課程ID
   */
  @Id
  @GeneratedValue(strategy= GenerationType.IDENTITY)
  private Long id;
  /**
   * 課程名稱
   */
  private String name;
  /**
   * 對應(yīng)講師的ID
   */
  private Long lecturerId;
}

講師

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**
 * 講師,一個(gè)講師有多個(gè)課程
 * @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接口。關(guān)鍵示例如下:

課程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<Course, Integer>,
    QuerydslPredicateExecutor<Course> {
}

講師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<Lecturer,Integer>,
    QuerydslPredicateExecutor<Lecturer> {
}

代碼生成

前面配置QueryDSL代碼生成器就是用于這一步,==每次實(shí)體類有變更最好重復(fù)執(zhí)行本步驟重新生成新的代碼==。由于個(gè)人習(xí)慣使用IDEA,所以以IDEA作為演示。

雙擊下圖內(nèi)容即可生成代碼了,

然后就會(huì)在src/generated-sources目錄可以看到生成的代碼,包名與實(shí)體包名一致,但是類名為Q開頭的文件

上一步的截圖我們可以看到其實(shí)生成的代碼被IDEA識(shí)別為普通文件了,所以我們需要標(biāo)記src/generated-sources/java目錄的用途,如下圖所示

標(biāo)記后,效果如下,可以看到代碼被正確識(shí)別了


到了這一步其實(shí)已經(jīng)完成整合了,下面就開始驗(yàn)證是否正確整合以及展示QueryDSL的優(yōu)勢了

驗(yàn)證整合與演示

下面我會(huì)使用單元測試來驗(yàn)證QueryDSL是否正確整合以及演示一下QueryDSL的優(yōu)勢

單元測試類

這里主要是單元測試類的關(guān)鍵內(nèi)容,需要注意@BeforeEachJunit5的注解,表示每個(gè)單元測試用例執(zhí)行前會(huì)執(zhí)行的方法其實(shí)對應(yīng)Junit4@Before

/**
 * @SpringBootTest 默認(rèn)不支持事務(wù)且自動(dòng)回滾
 * 使用@Transactional 開啟事務(wù),
 * 使用@Rollback(false) 關(guān)閉自動(dòng)回滾
 * @author Null
 * @date 2019-10-24
 */
@SpringBootTest
class QuerydslJpaDemoApplicationTests {

  @Autowired
  private CourseRepository courseRepository;

  @Autowired
  private LecturerRepository lecturerRepository;
  
  @Autowired
  private JPAQueryFactory queryFactory;

  /**
   * 初始化數(shù)據(jù)
   */
  @BeforeEach
  public void initData(){
    // 清空數(shù)據(jù)表
    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);
  }
  
  ...省略各個(gè)用例
  
}

單表模糊查詢

  /**
   * 根據(jù)課程名稱模糊查詢課程
   */
  @Test
  public void testSelectCourseByNameLike() {
    // 組裝查詢條件
    QCourse qCourse = QCourse.course;
    // %要自行組裝
    BooleanExpression expression = qCourse.name.like("P%");
    System.out.println(courseRepository.findAll(expression));
  }

聯(lián)表查詢

  /**
   * 根據(jù)講師姓名查課程
   */
  @Test
  public void testSelectCourseByLecturerName(){
    QCourse qCourse = QCourse.course;
    QLecturer qLecturer = QLecturer.lecturer;
    // 這里包含了組裝查詢條件和執(zhí)行查詢的邏輯,組裝好條件后記得執(zhí)行fetch()
    List<Course> courses=queryFactory.select(qCourse)
        .from(qCourse)
        .leftJoin(qLecturer)
        .on(qCourse.lecturerId.eq(qLecturer.id))
        .where(qLecturer.name.eq("Tom"))
        .fetch();
    System.out.println(courses);
  }

更新

  /**
   * 根據(jù)姓名更新講師性別<br/>
   * 使用@Transactional開啟事務(wù)<br/>
   * 使用@Rollback(false)關(guān)閉自動(dòng)回滾<br/>
   */
  @Test
  @Transactional
  @Rollback(false)
  public void testUpdateLecturerSexByName(){
    QLecturer qLecturer = QLecturer.lecturer;
    // 更新Tom的性別為女性,返回的是影響記錄條數(shù)
    long num=queryFactory.update(qLecturer)
        .set(qLecturer.sex,false)
        .where(qLecturer.name.eq("Tom"))
        .execute();
    // 這里輸出被更新的記錄數(shù)
    System.out.println(num);
  }

刪除

  /**
   * 根據(jù)根據(jù)性別刪除講師
   */
  @Test
  @Transactional
  @Rollback(false)
  public void testDeleteLecturerBySex(){
    QLecturer qLecturer = QLecturer.lecturer;
    // 刪除性別為男性的講師
    long num=queryFactory.delete(qLecturer)
        .where(qLecturer.sex.eq(true))
        .execute();
    // 輸出被刪除的記錄數(shù)
    System.out.println(num);
  }

用例分析

從用例中可以看出其實(shí)QueryDSLAPI更加切合原生的SQL,基本上從代碼上就可以看出你希望執(zhí)行的SQL了。

細(xì)心的朋友會(huì)發(fā)現(xiàn)QueryDSL是沒有insert方法,因?yàn)?code>JPA提供的save()方法已經(jīng)足夠處理了。

同時(shí)要記得要組裝好你的SQL后別忘記調(diào)用fetch()或者execute()方法。

總結(jié)

Spring Boot JPA整合QueryDSL的關(guān)鍵步驟

  • 引入依賴和插件
  • 編寫配置類
  • 使用插件生成代碼
  • 標(biāo)記生成文件為代碼
  • Repository繼承QuerydslPredicateExecutor

QueryDSLAPI類似原生SQL,API風(fēng)格類似StringBuilderAPIFluent API風(fēng)格)。但是不提供insert對應(yīng)的操作。

QueryDSL對于復(fù)雜的SQL的支持十分友好,算是對于JPA對這塊需求的補(bǔ)充和完善。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java反射的兩種使用方法(推薦)

    Java反射的兩種使用方法(推薦)

    這篇文章主要介紹了Java反射的兩種使用方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-05-05
  • java遞歸處理單位人員組織機(jī)構(gòu)樹方式

    java遞歸處理單位人員組織機(jī)構(gòu)樹方式

    這篇文章主要介紹了java遞歸處理單位人員組織機(jī)構(gòu)樹方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Java實(shí)現(xiàn)Redis分布式鎖的三種方案匯總

    Java實(shí)現(xiàn)Redis分布式鎖的三種方案匯總

    setnx、Redisson、RedLock?都可以實(shí)現(xiàn)分布式鎖,從易到難得排序?yàn)椋簊etnx?<?Redisson?<?RedLock,本文為大家整理了三種方法的實(shí)現(xiàn),希望對大家有所幫助
    2023-11-11
  • springboot中生成文件路徑的問題及解決方法

    springboot中生成文件路徑的問題及解決方法

    這篇文章主要介紹了springboot中生成文件路徑的問題及解決方法,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • SpringBoot項(xiàng)目中枚舉類型字段與前端和數(shù)據(jù)庫的交互方法

    SpringBoot項(xiàng)目中枚舉類型字段與前端和數(shù)據(jù)庫的交互方法

    最近做的這個(gè)項(xiàng)目中,用到了大量的枚舉類,下面這篇文章主要給大家介紹了關(guān)于SpringBoot項(xiàng)目中枚舉類型字段與前端和數(shù)據(jù)庫的交互方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • JAVA抽象類,接口,內(nèi)部類詳解

    JAVA抽象類,接口,內(nèi)部類詳解

    這篇文章主要給大家介紹了關(guān)于Java中抽象類,接口,內(nèi)部類的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-09-09
  • EL表達(dá)式的隱式對象_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    EL表達(dá)式的隱式對象_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了EL表達(dá)式的隱式對象,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • Java 在生活中的 10 大應(yīng)用

    Java 在生活中的 10 大應(yīng)用

    這篇文章主要給大家分享Java 在生活中的 10 大應(yīng)用,桌面圖形用戶界面、移動(dòng)應(yīng)用、人工智能、網(wǎng)絡(luò)應(yīng)用程序、大數(shù)據(jù)技術(shù)、游戲應(yīng)用、商業(yè)應(yīng)用、嵌入式系統(tǒng)、云應(yīng)用、科學(xué)應(yīng)用,下文來看具體應(yīng)用介紹,需要的朋友可以參考一下
    2021-11-11
  • springBoot整合redis使用案例詳解

    springBoot整合redis使用案例詳解

    這篇文章主要介紹了springBoot整合redis使用案例詳解,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • 淺析java中常用的定時(shí)任務(wù)框架-單體

    淺析java中常用的定時(shí)任務(wù)框架-單體

    這篇文章主要帶大家了解常用的單體應(yīng)用定時(shí)任務(wù)框架以及掌握定時(shí)任務(wù)在單體中如何使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2021-12-12

最新評(píng)論