JPQL

使用JPQL將查詢結果封裝為自訂義物件

黃東俞 Tungyu Huang 2019/10/23 17:20:49
77

當我們使用Spring Boot開發程式時,通常使用Spring Data JPA來協助資料庫的存取,相較於Hibernate可大幅降低開發的複雜度,快速建立各種存取資料的方法。關於JPA的介紹可以查詢昕力大學的文章 ── Spring Data JPA簡介 https://tpu.thinkpower.com.tw/tpu/articleDetails/842

JPA基本的功能通常只會返回我們預先設定好的實體物件,因此以下將示範使用JPQL做簡單的查詢,並說明如何使用JPQL直接將查詢結果封裝為自訂義物件。

一、 添加依賴

1. pom.xml

<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

2. gradle

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

二、 建立實體

假設我們要查詢users資料表,需先建立實體。

@Entity
public class Users {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;

    private Integer age;
    
    getters and setters……
}

三、 建立UsersReppository繼承JpaRepository並撰寫JPQL

@Repository
public interface UsersRepository extends JpaRepository<Users, Integer> {
    @Query("SELECT u FROM Users u")
    List<Users> getAllUser(); 
}

雖然JPQL結構與SQL極為相似,但是JPQL針對的是實體物件與其變量的名稱,而非資料表和欄位的名稱,這點與HQL相同。接下來調用getAllUser()就能快速得到Uers資料,相較於傳統HibernateHQL,不需再建立class實做查詢方法,在開發上十分方便。

四、 建立自訂義物件

若我們想要的資料並非原本的Users資料,而是我們自訂義物件,例如UserData

public class UserData {
    private String name;
    private Integer age;
    private String address;

    getters and setters……
}

UserData中的nameage來源為Users,而address來源為另外一個實體UserAddress

@Entity
public class UserAddress {
    @Id
    private Integer userId;
    private String address;
    
    getters and setters……
}

若要改寫UsersRepository ,在JPQLJOIN兩個實體並且將回傳的資料封裝為UserData,此時要先在UserData中加入建構子。

public class UserData {
    private String name;
    private Integer age;
    private String address;

    public UserData(String name, Integer age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    getters and setters……
}

五、 使用JPQL將查詢結果封裝

UsersRepository中加入新的查詢方法getUserData(),並使用@Query寫入JPQL

@Repository
public interface UsersRepository extends JpaRepository<Users, Integer> {

    @Query("SELECT u FROM Users u")
    List<Users> getAllUser();

    @Query("SELECT NEW com.tung.demo.model.UserData(u.name, u.age, ua.address)"
            + " FROM Users u"
            + " LEFT JOIN UserAddress ua ON u.id = ua.userId")
    List<UserData> getUserData();
}

其中的com.tung.demo.model.UserData要和package一致,u.name, u.age, u.address等參數排列與型態務必和建構子相符,如此一來只要調用getUserData()即可快速得到封裝好的UserData了!是不是非常簡單呢?

黃東俞 Tungyu Huang