1. 程式人生 > >Mybatis,Order By排序問題

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的效果,兩者的結合,更是很簡單地解決了我遇到的問題。