使用EntityManager在Spring jpa中实现多表查询与动态sql

Spring jpa是Spring家族的一套基于jpa规范标准的查询框架,其实它的内部的是借参考于Hibarnate实现的,只是它更加轻量级。Spring jpa对于单表的增删改查是很方便的,对于多表查询的话也可以使用它的一个注解:@Query实现。@Query可以像Hibrnate那样写hql,也可以写原生sql。担是如果你的查询结果是多个表查询出来的结果,而且你的数据库中的表都是单表的话,用原生sql是查询出来对应不上的,应该用它的hql。@Query可以写增删改查sql语句,担如果是增删改操作还要加上@Modifying注解。
下面进入正题,使用EntityManager实现Spring jpa多表查询与动态sql,不多说,直接上代码:
首先在你的service中引EntityManager :
@PersistenceContext
private final EntityManager entityManager;

这是传参用到的:

/**
     * 给sql参数设置值
     * @param query 查询
     * @param params 参数
     */
    private void setParameters(Query query, Map<String,Object> params){
        for(Map.Entry<String,Object> entry:params.entrySet()){
            query.setParameter(entry.getKey(),entry.getValue());
        }
    }

接下来开始sql:

@Override
    //@Cacheable
    public Map<String, Object> queryAllByPageAndParams(CourseStatisticReqParams reqParams, Pageable pageable) {
        String groupBySql=" group by buc.course_id order by buc.create_date desc";

        StringBuilder countSelectSql = new StringBuilder();
        countSelectSql.append("select count(t.id) from (select buc.id id from bae_user_course buc left join bae_course c on buc.course_id=c.id \n" +
                "where 1=1 ");

        StringBuilder selectSql = new StringBuilder();
        //user_id改成user_phone
        //selectSql.append("select c.course_name,c.course_type,buc.course_id,count(buc.user_id) buy_num,sum(buc.learn_ratio) learn_ratio  from bae_user_course buc left join bae_course c on buc.course_id=c.id where 1=1 ");
        selectSql.append("select c.course_name,c.course_type,buc.course_id,count(buc.user_phone) buy_num,sum(buc.learn_ratio) learn_ratio  from bae_user_course buc left join bae_course c on buc.course_id=c.id where 1=1 ");

        Map<String,Object> params = new HashMap<>();
        StringBuilder whereSql = new StringBuilder();
        if(ObjectUtil.isNotEmpty(reqParams)){
            if(null !=reqParams.getCourseName() && !"".equals(reqParams.getCourseName())){
                whereSql.append(" and c.course_name like concat('%',:course_name,'%')");
                params.put("course_name",reqParams.getCourseName());
            }

            if(null !=reqParams.getStartDate() && !"".equals(reqParams.getStartDate())){
                if(null !=reqParams.getEndDate() && !"".equals(reqParams.getEndDate())){
                    whereSql.append(" and c.create_date >=:start_date and c.create_date <=:end_date");
                    params.put("start_date", DateUtil.toTimestamp(reqParams.getStartDate()));
                    params.put("end_date",DateUtil.toTimestamp(reqParams.getEndDate()));
                }

            }
        }

        String groupBySqlCount=" group by buc.course_id) t";
        String countSql = new StringBuilder().append(countSelectSql).append(whereSql).append(groupBySqlCount).toString();
        Query countQuery = this.entityManager.createNativeQuery(countSql);
        this.setParameters(countQuery,params);
        BigInteger count = (BigInteger)  countQuery.getSingleResult();

        String querySql = new StringBuilder().append(selectSql).append(whereSql).append(groupBySql).toString();
        Query query = this.entityManager.createNativeQuery(querySql);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        this.setParameters(query,params);
        query.setFirstResult(pageable.getPageNumber());
        query.setMaxResults(pageable.getPageSize());

        List<Object[]> content =query.getResultList();
        List<CourseStatisticResParams> list=new ArrayList<CourseStatisticResParams>(content.size());
        for (Object obj : content) {
            Map row = (Map) obj;
            CourseStatisticResParams res=new CourseStatisticResParams();
            res.setCourseName(row.get("course_name")==null?null:row.get("course_name").toString());
            res.setBuyNum(row.get("buyNum")==null?null:Integer.parseInt(row.get("buyNum").toString()));
            res.setCourseId(row.get("course_id")==null?null:Long.parseLong(row.get("course_id").toString()));
            res.setBuyNum(row.get("buy_num")==null?null:Integer.parseInt(row.get("buy_num").toString()));
            res.setCourseType(row.get("course_type")==null?null:Integer.parseInt(row.get("course_type").toString()));
            //未学 在学 学完 考完 人数
            if(null !=res.getCourseId() && !"".equals(res.getCourseId())){
                //未学
                Map<String,Object> no_learn_params = new HashMap<>();
                String no_learn_sql="select count(buc.id) from bae_user_course buc where 1=1 and(buc.learn_ratio is null or buc.learn_ratio=0) and buc.course_id=:course_id";
                no_learn_params.put("course_id",res.getCourseId());
                Query no_learn_countquery = this.entityManager.createNativeQuery(no_learn_sql);
                this.setParameters(no_learn_countquery,no_learn_params);
                BigInteger no_learn_count = (BigInteger)no_learn_countquery.getSingleResult();
                res.setNoLearnNum(no_learn_count==null?0:no_learn_count.intValue());

                //在学
                Map<String,Object> learning_params = new HashMap<>();
                String learning_sql="select count(buc.id) from bae_user_course buc where 1=1 and buc.learn_ratio >0 and buc.learn_ratio<100 and buc.learn_status=0 and buc.course_id=:course_id";
                learning_params.put("course_id",res.getCourseId());
                Query learning_countquery = this.entityManager.createNativeQuery(learning_sql);
                this.setParameters(learning_countquery,learning_params);
                BigInteger learning_count = (BigInteger)learning_countquery.getSingleResult();
                res.setLearningNum(learning_count==null?0:learning_count.intValue());

                //学完
                Map<String,Object> learned_params = new HashMap<>();
                String learned_sql="select count(buc.id) from bae_user_course buc where 1=1 and buc.course_id=:course_id and buc.learn_status=1";
                learned_params.put("course_id",res.getCourseId());
                Query learned_countquery = this.entityManager.createNativeQuery(learned_sql);
                this.setParameters(learned_countquery,learned_params);
                BigInteger learned_count = (BigInteger)learned_countquery.getSingleResult();
                res.setLearnedNum(learned_count==null?0:learned_count.intValue());

                //考完
                Map<String,Object> examed_params = new HashMap<>();
                String examed_sql="select count(buc.id) from bae_user_course buc where 1=1 and buc.course_id=:course_id and buc.learn_status=1 and buc.exam_status=1";
                examed_params.put("course_id",res.getCourseId());
                Query examed_countquery = this.entityManager.createNativeQuery(examed_sql);
                this.setParameters(examed_countquery,examed_params);
                BigInteger examed_count = (BigInteger)examed_countquery.getSingleResult();
                res.setExamedNum(examed_count==null?0:examed_count.intValue());


            }

            list.add(res);


        }

        Page<CourseStatisticResParams> courseStatisticPage = new PageImpl<CourseStatisticResParams>(list, pageable, Long.valueOf(count.toString()));

        return PageUtil.toPage(courseStatisticPage);
    }

其中Query countQuery = this.entityManager.createNativeQuery(countSql);是表示使用原生sql的意思,如果你想用像hql那样,可以用它的createQuery这个方法,然后sql语句改成像hql那样查询即可。

你可能感兴趣的:(sql,jpa,java)