Jpa Repository接口方法实现+自定义SQL返回map对象

Jpa Repository接口方法实现+自定义SQL返回map对象


Spring Data Jpa 业务Repository接口实现

有时查询数据的时候需要连表或动态查询时,就需要自定义原生SQL去查询,一般有两种方法

1.在Service中新建一个方法去查询
2.在Repository定义一个接口,用方法去实现这个接口

第一个方法,Service中处理SQL数据库相关的业务,我个人觉得不太规范;这里主要讲第二种方法,步骤如下

1.在Repository定义一个接口
2.在接口类的同包下新建一个类,新建一个方法和接口中的方法名字,参数,返回数据 保存一致
3.在实现类中编写业务代码


自定义SQL查询结果返回map对象,或自定义对象

一般来说Query.getResultList()如果不做处理,返回的List中的对象是一个数组,这一般不是我们想要的;我们需要List中是对象,参考代码如下


示例代码

ProjectImgRepository.java - 业务Repository接口类


package com.itop.take_picture.repository;

@Repository
public interface ProjectImgRepository extends extends JpaRepository<ProjectImg, Long>, JpaSpecificationExecutor<ProjectImg> {

    List<Map<String, Object>> statisticsCountByType(String startDate, String endDate, String projectId);
}


ProjectImgRepositoryImpl.java - 业务Repository接口实现类


package com.itop.take_picture.repository;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class ProjectImgRepositoryImpl {

    @PersistenceContext
    private EntityManager entityManager;

    public List<Map<String, Object>> statisticsCountByType(String startDate, String endDate, String projectId) {
        int i = 0;
        Map<Integer, Object> param = new LinkedHashMap<>();
        //组装sql语句
        StringBuilder sql = new StringBuilder("SELECT count(1) FROM project_img b WHERE b.project_img_type_id = a.id");
        if (StringUtils.isNotBlank(startDate)) {
            sql.append(" AND b.create_time >= ?");
            param.put(++i, startDate);
        }
        if (StringUtils.isNotBlank(endDate)) {
            sql.append(" AND b.create_time <= ?");
            param.put(++i, endDate);
        }
        if (StringUtils.isNotBlank(projectId)) {
            sql.append(" AND b.project_id = ?");
            param.put(++i, projectId);
        }
        sql.insert(0, "SELECT a.id, a.name, a.node_path, (");
        sql.append(") as count FROM project_img_type a WHERE a.flag = 1");

        //创建本地sql查询实例
        Query dataQuery = entityManager.createNativeQuery(sql.toString());

        //动态设置参数
        for (Map.Entry<Integer, Object> entry : param.entrySet()) {
            dataQuery.setParameter(entry.getKey(), entry.getValue());
        }

        // 将结果转化成map或自定义对象
        // dataQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(ProjectImgStatisticsDTO.class));
        dataQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);

        List<Map<String, Object>> resultList = dataQuery.getResultList();
        return resultList;
    }

}


注意事项

  1. 接口类和实现类名称务必统一规范,必须在同一个包下面,无需用implements与上面的接口产生正式的实现关系,但是还是要规范的实现上面的接口的方法;

  2. dataQuery.setParameter(int var1, Object var2); 第一参数是从1开始,不是0开始,所以使用param.put(++i, xxx)

  3. 可以通过 dataQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);将数组转化成map对象

  4. dataQuery.unwrap(NativeQuery.class)dataQuery.unwrap(SQLQuery.class)在Hibernaterv5.2之后已经作废,新版本的使用NativeQueryImpl.class

  5. 如果希望查询的结果是一个dto对象,可以这样写dataQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.aliasToBean(ProjectImgStatisticsDTO.class));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值