jpa使用原生sql查询,或者使用Specification

最近有一个需求:
在这里插入图片描述
有三个查询条件,如果适用 JPA 最常见的形式
则需要加很多判断条件
如果采用最原生的 sql 哪一个筛选条件传值了
那么就拼接一下 sql 会方便很多

例如:
if(type!=null){
拼接 where type = xxx
}
if(mobile!=“”){
拼接 where mobile=“xxxxxx”
}
if(startTime!=null){
拼接 where endTime xxxxxx
}

三个判断条件写出来就解决了,所以这里记录一下如何适用 JPA 的原生 SQL

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class StaffGetNewCouponListV2ApiProcesser extends BaseApiProcesser {

    @Autowired
    private EntityManager entityManager;

    private final static String WHERE = " where ";
    private final static String AND = " and ";

    @Override
    public Map<String, Object> processRequest() throws InvalidParameterException, FailException {
    
        Integer type = checkIntegerParameter("type", null);
        Date startTime = checkDateParameter("startTime", null);
        Date endTime = checkDateParameter("endTime", null);


        String endTimeString = "";
        String startTimeString = "";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (endTime != null) {
            endTimeString = simpleDateFormat.format(endTime);
        }
        if (startTime != null) {
            startTimeString = simpleDateFormat.format(startTime);
        }

        boolean whereFlag = false;

        String sql = "select * from new_coupon_detail";

        if (type != null) {
            if (whereFlag == false) {
                whereFlag = true;
                sql += WHERE;
            } else {
                sql += AND;
            }
            sql += "range_of_application= " + type;
        }

        if (startTime != null) {
            if (whereFlag == false) {
                whereFlag = true;
                sql += WHERE;
            } else {
                sql += AND;
            }
            sql += "start_time <=" + "'" + startTimeString + "'";
        }

        if (endTime != null) {
            if (whereFlag == false) {
                whereFlag = true;
                sql += WHERE;
            } else {
                sql += AND;
            }
            sql += "end_time>=" + "'" + endTimeString + "'";
        }

        Query nativeQuery = entityManager.createNativeQuery(sql,NewCouponDetail.class);

        List<NewCouponDetail> resultList = nativeQuery.getResultList();

        for (NewCouponDetail newCouponDetail : resultList) {
            System.out.println(newCouponDetail);
        }

        return null;
    }

}

这样写出来的 原生SQL 是可以的

但是在 JPA 中,还提供了一种方法 那就是 Specification
使用这个的前提是: repository 继承 JpaSpecificationExecutor

@Repository
public interface XXXXXRepository extends JpaRepository<XXXXXX, Integer>, JpaSpecificationExecutor<XXXXX> {
}
    public void findBySpection(Integer type, Date startTime, Date endTime) {

        /*分页参数*/
        Pageable pageable = PageRequest.of(0, 20, Sort.Direction.ASC, "startTime");

        newCouponDetailRepository.findAll(new Specification<NewCouponDetail>() {

            @Override
            public Predicate toPredicate(Root<NewCouponDetail> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                /*条件的集合*/
                ArrayList<Predicate> predicateList = new ArrayList<>();

                if (type != null) {
                    /*实体类的某个字段并将其指定为Integer类型  equal  传入的参数*/
                    Predicate rangeOfApplication = criteriaBuilder.equal(root.get("rangeOfApplication").as(Integer.class), type);
                    predicateList.add(rangeOfApplication);
                }
                if (startTime != null) {
                    /*实体类的 startTime <= 传入的参数*/
                    Predicate startTime1 = criteriaBuilder.lessThanOrEqualTo(root.get("startTime").as(Date.class), startTime);
                    predicateList.add(startTime1);
                }
                if (endTime != null) {
                    /*实体类的 endTime >= 传入的参数*/
                    Predicate endTime1 = criteriaBuilder.greaterThanOrEqualTo(root.get("endTime").as(Date.class), endTime);
                    predicateList.add(endTime1);
                }

                //使用数组作为最终返回值的条件
                Predicate[] predicates = new Predicate[predicateList.size()];
                //将集合转换成数组
                predicates = predicateList.toArray(predicates);
                //合并条件
                return criteriaBuilder.and(predicates);
            }
        }, pageable);

    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用JPA进行原生SQL查询时,可以借助Spring Data JPA的`@Query`注解和`nativeQuery=true`属性来实现。`@Query`注解是用来声明查询语句的,而`nativeQuery=true`则表示使用原生SQL查询。具体步骤如下: 1. 在Repository接口中定义一个方法,并使用`@Query`注解来声明原生SQL查询语句。例如:`@Query(value = "SELECT * FROM table_name WHERE condition", nativeQuery = true)` 2. 在方法中使用JPA的命名参数或占位符来传递参数。例如:`@Query(value = "SELECT * FROM table_name WHERE column_name = :param", nativeQuery = true)` 3. 如果需要返回实体对象,可以在Repository接口中定义一个与查询结果对应的构造函数,并在查询语句中使用`NEW`关键字来创建实体对象。例如:`@Query(value = "SELECT NEW com.example.EntityName(column1, column2) FROM table_name WHERE condition", nativeQuery = true)` 4. 调用Repository接口中定义的方法来执行原生SQL查询并获取结果。 需要注意的是,使用原生SQL查询可能会降低代码的可移植性,并且需要仔细处理SQL注入等安全问题。因此,在使用原生SQL查询时,建议谨慎使用,并遵循安全编码规范。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [spring boot jpa写原生sql报Cannot resolve table错误解决方法](https://download.csdn.net/download/weixin_38622149/12744996)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [JPA用法与原声SQL](https://blog.csdn.net/qq_40206199/article/details/84860945)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值