使用JPQL將查詢結果封裝為自訂義物件
當我們使用Spring Boot開發程式時,通常使用Spring Data JPA來協助資料庫的存取,相較於Hibernate可大幅降低開發的複雜度,快速建立各種存取資料的方法。關於JPA的介紹可以查詢昕力大學的文章 ── Spring Data JPA簡介 https://www.tpisoftware.com/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資料,相較於傳統Hibernate的HQL,不需再建立class實做查詢方法,在開發上十分方便。
四、 建立自訂義物件
若我們想要的資料並非原本的Users資料,而是我們自訂義物件,例如UserData。
public class UserData {
private String name;
private Integer age;
private String address;
getters and setters……
}
UserData中的name和age來源為Users,而address來源為另外一個實體UserAddress。
@Entity
public class UserAddress {
@Id
private Integer userId;
private String address;
getters and setters……
}
若要改寫UsersRepository ,在JPQL中JOIN兩個實體並且將回傳的資料封裝為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了!是不是非常簡單呢?