1. 程式人生 > >Spring-Data-Jpa projection用法

Spring-Data-Jpa projection用法

進行資料查詢時,有時候並不需要把全部欄位查詢出來,只要查詢部分的欄位即可。那麼就需要使用到Sping-Data-Jpa中的projection功能了。

前提:有使用者表和訂單表,使用者與訂單的關係是1對多關係。訂單表的模型bean:

@Entity
@Table(name = "t_order")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(targetEntity = User.class)
    @JoinColumn
(name = "user_id") private User user; private String orderName; private String orderNumber; @Convert(converter = DateToDateTimeConverter.class) private DateTime createTime; @Convert(converter = DateToDateTimeConverter.class) private DateTime updateTime; get/set方法略... }

1、使用介面定義需要獲取的欄位,如獲取訂單名稱和對應的使用者id和使用者名稱稱,定義好需要獲取的欄位對應的get方法:

public interface OrderQueryDTO {

    public Long getUserId();

    public String getOrderName();

    public String getUsername();

}
db查詢:
    @Query("select  orderName , user.userId ,user.username  from Order where id = ?1")
    <T> T findOrderWithUserNameByOrderId(Long id, Class<T> target);

使用:

    OrderQueryDTO order2 = orderReadRepository.findOrderWithUserNameByOrderId(1L, OrderQueryDTO.class);
        log.info("2=====使用介面作為projection===" + order2 + "," + order2.getClass().getName());

執行後對應的log:

select order0_.order_name as col_0_0_, order0_.user_id as col_1_0_, user1_.username as col_2_0_ from t_order order0_, t_user user1_ where order0_.user_id=user1_.user_id and order0_.id=?
 2=====使用介面作為projection==={userId=1, orderName=orderName, username=user0},com.sun.proxy.$Proxy105

2、使用Bean作為DTO,如只需要查詢訂單名稱欄位,則定義如下bean,注意需要使用構造方法。

public class OrderQueryDTO2 {

    private String orderName;

    public OrderQueryDTO2(String orderName) {
        super();
        this.orderName = orderName;
    }
    get/set方法
    }

    db方法定義:
    OrderQueryDTO2 findOrderNameById(Long id);

使用:

    OrderQueryDTO2 order5 = orderReadRepository.findOrderNameById(1L);
        log.info("5=====findOrderNameById 跟方法名無關,而是根據返回的bean的欄位來的===" + order5.getOrderName());

查詢結果:

Hibernate: select order0_.order_name as col_0_0_ from t_order order0_ where order0_.id=?
5=====findOrderNameById 跟方法名無關,而是根據返回的bean的欄位來的===orderName

根據sql可以看出只查詢了訂單名稱這一個欄位

3、查詢單個欄位,如查詢使用者id,需要使用@Query設定sql

/**
     * 自定義查詢欄位,注意這裡查詢使用的是bean對應的屬性欄位而不是資料庫欄位
     * @param username
     * @return
     */
    @Query("select userId from User where username = ?1")
    Long findUserIdByUsername(String username);

總結:projection方式有如下三種

  1. 使用構造方法進行設定的bean
  2. 使用介面定義,自定義get方法
  3. 自定義sql,返回需要的欄位