使用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那样查询即可。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我了解了。下面是一个有效的示例: 假设我们有一个实体类Student和对应的Dto类StudentDto,其Student类有一个set类型的属性courses,表示学生所选的课程。我们现在需要查询所有选修某一门特定课程的学生,返回的结果是一个List<StudentDto>集合,每个StudentDto对象包含学生的基本信息和选修的课程列表。 首先,我们需要编写一个JPQL查询语句,如下: ``` SELECT s FROM Student s JOIN s.courses c WHERE c.name = :courseName ``` 这条语句表示查询所有选修名为courseName的课程的学生。 然后,在我们的代码,我们使用EntityManager对象来执行这个查询,代码如下: ``` public List<StudentDto> getStudentsByCourse(String courseName) { TypedQuery<Student> query = entityManager.createQuery( "SELECT s FROM Student s JOIN s.courses c WHERE c.name = :courseName", Student.class); query.setParameter("courseName", courseName); List<Student> students = query.getResultList(); List<StudentDto> dtos = new ArrayList<>(); for (Student s : students) { StudentDto dto = new StudentDto(); // 将学生的属性复制到Dto BeanUtils.copyProperties(s, dto); dtos.add(dto); } return dtos; } ``` 在上述代码,我们使用EntityManager对象的createQuery方法创建了一个TypedQuery对象,并传入JPQL查询语句和返回结果的类型(Student类)。然后,我们通过setParameter方法设置查询的参数,这里是课程名称。接着,我们调用getResultList方法执行查询,返回一个List<Student>集合。 最后,我们将每个Student对象的属性复制到对应的StudentDto对象,并把所有Dto对象放入一个List<StudentDto>返回。这里我们使用Spring框架的BeanUtils类来快速复制对象属性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值