Spring Data JPA 二:实现多表关联分页查询

最近在对JPA的使用过程中发现对于单表的操作很是方便,但是当设计到多表联查的时候就需要有一些特殊的操作了。

项目中有一个场景是后台需要做一个分页的列表查询,所需要的数据分散在两张表中,如果是用mybatis的话直接定义resultMap,然后手写SQL就可以了。而在JPA中就需要用到JPQL了。

首先定义一下各个对象之间的关系

实体 GxOrderDO :订单。

实体 GxOrderDetailDO:订单详情。

实体 GxOrderInfoRsp:分装的分页返回对象。

其中的GxOrderDO和GxOrderDetailDO通过orderId字段做两张表的关联。

创建一个对象用来封装返回的结果集:

GxOrderInfoRsp.java:

public class GxOrderInfoRsp implements Serializable{
    /**
     * 订单ID
     */
    private String orderId;
    /**
     * 订单状态
     */
    private Integer orderStatus;
    /**
     * 订单类型
     */
    private Integer orderType;
    /**
     * 订单支付金额
     */
    private BigDecimal orderAmount;
    /**
     * 订单渠道(设备)类型 
     */
    private Integer orderChannel;

    public GxOrderInfoRsp(String orderId, Integer orderStatus, Integer orderType,         
                          BigDecimal orderAmount, Integer orderChannel) {
        this.orderId = orderId;
        this.orderStatus = orderStatus;
        this.orderType = orderType;
        this.orderAmount = orderAmount;
        this.orderChannel = orderChannel;
        
    }

Repository:

  @Query("SELECT new com.app.domain.GxOrderInfoRsp(r.orderId, r.orderStatus, r.orderType, rd.orderAmount, rd.orderChannel) FROM GxOrderDO r, GxOrderDetailDO rd WHERE r.orderId = rd.orderId and ( r.orderId=:#{#customer.orderId} or :#{#customer.orderId} is null or :#{#customer.orderId} = '')   ")
    Page<GxOrderInfoRsp>  findOrderPage(@Param("customer") GxOrderDO customer,Pageable pageable);

注意:@Query中new的对象的参数顺序要和构造方法的参数顺序一致

r.orderId=:#{#customer.orderId} or :#{#customer.orderId} is null) 
这种是做个非空判断,如果是空,就跳过这个条件,不执行。
这里面用到了Spring Data JPA @Query定义中的SpEL特性

Service:

Pageable pageable = new PageRequest(0,3, Sort.Direction.DESC,"createTime");

另一种原生动态SQL的写法:

@Query(value = "select * from table_name where if(?1!=null or ?1!='',key=?1,1=1) and if(?2!=null or ?2!='',key2=?2,1=1),nativeQuery = true)
public List<User> findList(String key,String key2);

使用条件:当有多个查询条参数且有时参数会为空时,为了避免写多个参数不同的查询函数,可以使用该方法。

理解:if(?1!=null or ?1!='',key=?1,1=1)

如果?1!=null or ?1 !=''成立,则返回key=?1,否则返回1=1

 

SELECT ( key = ?1 OR ?1 IS NULL OR ?1 = '' );
SELECT ( ?1 IS NULL OR key = ?1 OR ?1 = '' );
SELECT ( ?1 = '' OR ?1 IS NULL OR key = ?1 );

执行的结果相同----顺序无关。

'' = '' 和 null IS NULL 的结果和 1 = 1是一样的。

MySQL使用OR运算符进行短路评估(求值计算)。 换句话说,当MySQL可以确定结果时,MySQL会停止评估(求值计算)语句的其余部分,这样的记录就会被查询出来。

 

文章参考:

https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions

https://blog.csdn.net/moshowgame/article/details/80672617

https://blog.csdn.net/hzkcsdnmm/article/details/100522436?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-1&spm=1001.2101.3001.4242

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值