Mybatis,Order By排序问题

    曾写过一篇博客,是接触了一段时间的mybatis开发总结的:《Mybatis,怀疑--使用--感悟》。又过去了一段时间,前不久和别人联调接口,遇到了mybatis的排序问题。这篇博客就来总结一下,在mybatis框架下,如何实现排序?
    排序,是个很基础的需求。实现的时候只需要在查询语句后面加上order by 某个字段即可。在mybatis中,用工具可以帮助我们自动生成底层的一套东西,便可以满足我们基本的增删改查需求。那么,怎么样可以在select语句后面加上order by语句呢?下面就结合项目中的实践来分享给大家。
   【方法一 Example中处理排序】
    用mybatis自动生成工具,会生成几个文件,其中包括~Mapper.XML和~Example文件。我们能够实现基本的增删改查,也是建立在这几个文件的基础上。不知道大家有没有注意过~Mapper.XML 文件中SelectByExample中有排序的语句?如下图所示:

    所以说,在我们逻辑层代码中,利用Example进行条件查询的时候,也可以将orderBy条件写上,具体代码如下:
public List<Article> findAllArticles() {
        ArticleExample example = new ArticleExample();
        example.setOrderByClause("`index` ASC,id ASC");
        List<Article> list = articleMapper.selectByExample(example);
        LOG.debug("findArticles with site={} and categoryId={} return: {}",
                list);
        return list;
    }  


   【方法二 PageBounds中处理排序】
    PageBounds,分页,这也是一个很基本的需求。在项目中,直接引入了mybatis封装好的插件。
		
    而你如果看过这里面的源码,你会发现,其中也给我们提供了一个排序的实现。也就是说,若接口中包含分页参数,你完全可以利用分页去实现排序。下面是我单元测试中的代码:
public void findArticlesByCategory1() {
        // 分页中实现排序,利用下面封装好的方法,传参数即可
        /*
         * public PageBounds(int page, int limit, List<SortBy> orders) {
         * this(page, limit, orders, true); }
         */
        PageBounds pb = new PageBounds(1, 3, new SortBy("index",
                Direction.DESC, "`index`"));
        Response<List<ArticleModel>> response = articleService
                .findArticlesByCategory("INFO", "main_app_info", pb);
        Assert.assertTrue(response.getData().size() > 0);// 正常
    } 
    结果可以实现排序吗?答案是,可以实现,但是并没有实现。却报错了:


    但如果,我将排序字段改了,根据id排序,代码如下:
public void findArticlesByCategory1() {
        // 分页中实现排序,利用下面封装好的方法,传参数即可
        PageBounds pb = new PageBounds(1, 3, new SortBy("id", Direction.DESC,
                "id"));
        Response<List<ArticleModel>> response = articleService
                .findArticlesByCategory("INFO", "main_app_info", pb);
        Assert.assertTrue(response.getData().size() > 0);// 正常
        System.out.print(response.getData());
    }  
    测试是可以通过的。再回到出错的截图上, 为什么我框出了order by的语句部分呢。因为出错的原因就在这里了。index属于关键字,写一个简单的'select * from Table order by index DESC',在mysql数据库中都会执行出错,所以,我在代码中给index加了``符号,但生成后的语句,并没有带符号。
    这样看来,就是因为index关键字转换不了的原因,所以没法实现在分页中用该字段去排序。哎,前期的数据表设计的人都没见过,不会让我因为这个又重新生成一套底层文件吧。这都已经上了生产的项目,这样的改动太大了。
     但我想到的是,实际上,自己也实现了在example中去根据index字段排序的。我可以用example去给它排好序,但因为接口是要提供给其它平台的,而调用此接口的人也不是一方,一边需要按'index'字段排序,而另一边又不需要,这样就不能都满足了。
     所以,最后的解决办法就是【方法一 + 方法二 = 方法三】
   【方法三 Example与PageBounds结合排序】
    调用此接口的,根据自己的需要传入对应的参数,如果不需要按某字段排序,只需要传入 int page, int limit即可;如果需要按某字段排序,传入的参数包括 int page, int limit,List<SortBy>.而我的逻辑代码只需要判断一下,如果传入了排序字段,先从List<SortBy>中获取,再写入到Example中,这样,index关键字的问题解决了,排序的灵活性也解决了。
    具体代码如下:
public List<Article> findArticlesByCategoryId(String site, Long catId,
			PageBounds pb) {
		ArticleExample example = new ArticleExample();
		example.createCriteria().andSiteLike("%" + site + "%")
				.andCatIdEqualTo(catId).andIsDeletedEqualTo(false)
				.andStatusEqualTo(article_published)
				.andPublishTimeLessThanOrEqualTo(new Date()); // 添加筛选条件:未删除的,已发布的,且发布时间小于或等于当前时间
		List<SortBy> sortBies = new ArrayList<SortBy>();
		sortBies = pb.getOrders();
		if (sortBies != null && !sortBies.isEmpty()) {
			String orderString = "";
			String orderDirection = "";
			for (SortBy sortBy : sortBies) {
				orderString = sortBy.getOrderExpr();
				Direction direction = sortBy.getDirection();
				orderDirection = direction.toString();
			}

			pb.setOrders(null);
			// 前端需要,按显示顺序字段排序。若传了排序参数,则按参数进行排序
			example.setOrderByClause(orderString + " " + orderDirection);
		}

		List<Article> list = articleMapper.selectByExample(example, pb);
		LOG.debug("findArticles with site:{} and categoryId={} return: {}",
				site, catId, list);
		return list;
	}
【项目总结】
    最开始接触排序的问题是因为我们平台端的需要, 很多东西他们封装好了,我 就在项目中一层层的找代码,同时也上网查了查mybatis中可以如何实现排序。
     第一种方法Example中设置排序就是我从查资料中获取到的。后来遇到了问题,看代码的时候就发现在PageBounds中也有一套排序,而且默认了是按每个表中的create_time字段排序的。猜想是两者发生了冲突,所以直接将PageBounds中的排序给set null值了。我的问题也解决了。
    这一次,通过给其它平台联调,让我接触到了第二种方法,原来mybatis封装好的分页插件可以这样玩。同样,也收获到了1+1>2的效果,两者的结合,更是很简单地解决了我遇到的问题。

  • 24
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 33
    评论
### 回答1: Mybatis中的order by排序可以通过传参来实现。具体方法如下: 1. 在Mapper.xml文件中,定义一个参数,用于接收排序字段和排序方式。 2. 在SQL语句中使用${}占位符,将参数传递给order by子句。 例如: <select id="getUserList" parameterType="map" resultType="User"> select * from user <where> <if test="name != null"> and name like concat('%', #{name}, '%') </if> </where> order by ${orderBy} ${orderType} </select> 3. 在Java代码中,将排序字段和排序方式封装到一个Map中,作为参数传递给Mapper方法。 例如: Map<String, Object> params = new HashMap<>(); params.put("orderBy", "create_time"); params.put("orderType", "desc"); List<User> userList = userMapper.getUserList(params); 这样就可以动态地传递排序字段和排序方式,实现order by排序穿参。 ### 回答2: Mybatis是一款开源的ORM框架,广泛应用于Java项目中。在Mybatis中,可以使用SQL语句进行数据操纵。其中,order by是用于排序的关键字,可以按照指定的字段进行升序或降序排序。当需要在Mybatis中使用order by进行排序时,可以通过传递参数来实现灵活的排序功能。 具体实现如下: 1.在Mapper.xml文件中定义查询语句 例如: ``` <select id="getUserList" parameterType="java.util.Map" resultType="com.example.User"> select * from user <where> <if test="name != null and name != ''"> and name like concat('%',#{name},'%') </if> </where> order by ${orderField} ${orderType} </select> ``` 在查询语句中,使用${}方式传递参数,orderField和orderType是排序字段和排序方式的动态参数。 2.在Mapper接口中定义方法,并传递参数 例如: ``` List<User> getUserList(@Param("name")String name, @Param("orderField")String orderField, @Param("orderType")String orderType); ``` 在接口方法中,使用@Param注解指定传递的参数名,在参数中传递排序字段和排序方式。 3.在Service层中调用Mapper方法,并传递参数 例如: ``` List<User> userList = userMapper.getUserList(name, "age", "desc"); ``` 在Service层中,调用Mapper方法,传递排序字段和排序方式,即按照年龄降序排列查询结果。 通过以上步骤,即可在Mybatis中实现order by排序穿参的功能。根据需要动态传递排序字段和排序方式,实现灵活的排序操作,提高查询结果的精度和准确度。 ### 回答3: MyBatis是一款非常流行的Java持久层框架,在数据库查询时提供了方便的实现和便捷的查询方式。其中,order by是一种常用的数据排序方法,可以通过参数传递的方式实现动态排序。 在MyBatis中,我们可以通过传递参数来动态地设置排序的列和排序的方式,具体步骤如下: 1.在Mapper.xml文件中,设置一个<select>标签,用于查询需要排序的数据。 <select id="queryList" parameterType="map" resultMap="xxxx"> SELECT * FROM table_name WHERE xxxxx <if test="orderBy != null and orderBy != ''"> ORDER BY ${orderBy} ${sortType} </if> </select> 其中,orderBy和sortType都是在Java代码中设置的参数,分别代表排序的列和排序的方式。 2.在Java代码中,需要进行排序的时候,传递参数来设置orderBy和sortType。 Map<String, Object> paramMap = new HashMap<String, Object>(); paramMap.put("orderBy", "column_name"); paramMap.put("sortType", "asc"); List<MyObject> myObjectList = myObjectMapper.queryList(paramMap); 通过这种方式,就可以实现动态排序,方便地查询和展示需要排序的数据了。 需要注意的是,由于orderBy和sortType都是通过变量的方式传递的,可能会存在SQL注入的风险,因此要对参数进行严格的校验和过滤,确保传递的参数合法可靠。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值