MyBatis第N+1种分页方式,全新的MyBatis分页
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                MyBatis第N+1种分页方式,全新的MyBatis分页
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                在MyBatis的世界里,原生的分頁基于RowBounds,雖然能達到分頁的目的,但是使用起來還是不那么方便.后面開發者又添加了流式查詢方式,雖然可以解決部分問題,但感覺還是不是想要的分頁方式.另一方面,Java界程序員大佬給出了很多優秀的分頁方案,比如Mybatis-PageHelper. 世界因不一樣而精彩,今天帶來一種新的分頁方式.希望帶給使用者一種新的API使用方式.
mybatis-nosugar
特點
- 全新的通用分頁不基于傳統MyBatis插件接口,所有的原本普通查詢也能夠得到支持
- 得益于JDK1.8的函數式接口,新的分頁方式才得以使用.使用方式更加簡單
- 如果使用NoSugar內置API,操作將更加簡單
支持數據庫
- MYSQL
- ORACLE
- SQLSERVER
- SQLSERVER2012
- POSTGRESQL
- DB2
- HSQL
如果數據庫不在上面的列表,配置mybatis.no-sugar.sql-build.dialect-class即可支持新的數據庫類型.
通用分頁Api
- NoSugar內置分頁Api定義了最多支持5個參數,多于5個的可以使用類型強制轉換.或者自己擴展.
- 支持原Mapper已定義的查詢方法.
分頁方法
Page<T> page = mapper.selectPagePX(Page<T>, mapper::原查詢方法的lambda引用, 原查詢方法參數列表...);簡單示例
Page<Movie> page = mapper.selectPageP2(new PageImpl<>(2, 5), mapper::findByLocationAndScoreGreaterThan, "US", 9.0);使用方式
示例數據
實體類
@Table(name = "movie") public class Movie implements Serializable {private static final long serialVersionUID = -8793166370987026047L;/** 主鍵 */@Id@Column(name = "id", nullable = false)@GeneratedValue(strategy = GenerationType.IDENTITY)private Integer id;/** 名稱 */@Column(name = "name", nullable = false)private String name;/** 地區 */@Column(name = "location", nullable = false)private String location;/** 時長 */@Column(name = "length", nullable = false)private Integer length;/** 發行日期 */@Column(name = "release_date", nullable = false)private LocalDate releaseDate;/** 名次 */@Column(name = "ordinal", nullable = false)private Integer ordinal;/** 評分 */@Column(name = "score", nullable = false)private Double score;/** 類別 */@Column(name = "category", nullable = false)private String category;... }Mapper接口
public interface MovieMapper extends BaseMapper<Movie, Integer> {List<Movie> findByCategoryIsNotNull();List<Movie> findByLocation(String location);List<Movie> findByLocationAndScoreGreaterThan(String location, Double score);List<Movie> findByLocationAndScoreGreaterThanAndCategoryContains(String location, Double score, String category);}數據庫初始化SQL
DROP TABLE movie IF EXISTS; CREATE TABLE movie (id INTEGER GENERATED BY DEFAULT AS IDENTITY,name VARCHAR(100) NOT NULL,location VARCHAR(100) NOT NULL,length INTEGER NOT NULL,release_date DATE NOT NULL,ordinal INTEGER NOT NULL,score DOUBLE NOT NULL,category VARCHAR(20) NULL,PRIMARY KEY (id) );INSERT INTO movie VALUES (0, '肖申克的救贖', 'US', 142, '1994-09-23', 1, 9.7, '劇情'); INSERT INTO movie VALUES (1, '霸王別姬', 'CHN', 171, '1993-07-26', 2, 9.6, '劇情'); INSERT INTO movie VALUES (2, '阿甘正傳 ', 'US', 142, '1994-06-23', 3, 9.5, '劇情'); INSERT INTO movie VALUES (3, '美麗人生 ', 'IT', 116, '1997-12-20', 4, 9.6, ''); INSERT INTO movie VALUES (4, '千與千尋 ', 'JP', 125, '2001-07-20', 5, 9.4, '奇幻'); INSERT INTO movie VALUES (5, '泰坦尼克號 ', 'US', 194, '1997-12-19', 6, 9.4, '愛情'); INSERT INTO movie VALUES (6, '這個殺手不太冷', 'FR', 133, '1994-09-14', 7, 9.4, '犯罪'); INSERT INTO movie VALUES (7, '星際穿越', 'US', 169, '2014-11-12', 8, 9.4, '科幻'); INSERT INTO movie VALUES (8, '無間道', 'CHN', 101, '2003-09-05', 9, 9.3, '犯罪'); INSERT INTO movie VALUES (9, '瘋狂動物城', 'US', 109, '2016-03-04', 10, 9.2, '喜劇'); INSERT INTO movie VALUES (10, '機器人總動員', 'US', 98, '2008-06-27', 11, 9.3, '動畫'); INSERT INTO movie VALUES (11, '羅馬假日', 'US', 118, '1953-08-20', 12, 9.1, '愛情'); INSERT INTO movie VALUES (12, '大話西游之大圣娶親', 'CHN', 95, '1995-02-04', 13, 9.2, '劇情'); INSERT INTO movie VALUES (13, '大話西游之月光寶盒', 'CHN', 87, '1995-01-21', 14, 9.0, '喜劇'); INSERT INTO movie VALUES (14, '指環王3', 'US', 201, '2003-12-17', 15, 9.3, null);基于0個參數的分頁示例
Page<Movie> page = mapper.selectPageP0(new PageImpl<>(2, 5), mapper::findByCategoryIsNotNull); MovieMapper.adapterCount : ==> Preparing: SELECT COUNT(*) FROM movie WHERE category IS NOT NULL MovieMapper.adapterCount : ==> Parameters: MovieMapper.adapterCount : <== Total: 1 MovieMapper.adapterPage : ==> Preparing: SELECT id AS "id", name AS "name", location AS "location", length AS "length", release_date AS "releaseDate", ordinal AS "ordinal", score AS "score", category AS "category" FROM movie WHERE category IS NOT NULL OFFSET 5 LIMIT 5 MovieMapper.adapterPage : ==> Parameters: MovieMapper.adapterPage : <== Total: 5基于三個參數的分頁示例
Page<Movie> page = mapper.selectPageP3(new PageImpl<>(2, 2), mapper::findByLocationAndScoreGreaterThanAndCategoryContains, "US", 9.0, "情"); MovieMapper.adapterCount : ==> Preparing: SELECT COUNT(*) FROM movie WHERE location = ? AND score > ? AND category LIKE ? MovieMapper.adapterCount : ==> Parameters: US(String), 9.0(Double), %情%(String) MovieMapper.adapterCount : <== Total: 1 MovieMapper.adapterPage : ==> Preparing: SELECT id AS "id", name AS "name", location AS "location", length AS "length", release_date AS "releaseDate", ordinal AS "ordinal", score AS "score", category AS "category" FROM movie WHERE location = ? AND score > ? AND category LIKE ? OFFSET 2 LIMIT 2 MovieMapper.adapterPage : ==> Parameters: US(String), 9.0(Double), %情%(String) MovieMapper.adapterPage : <== Total: 2全新Count查詢
基于SelectMapper#adapterCount
在原查詢方法上開啟Count查詢.
示例
long count=mapper.countP3(mapper::findByLocationAndScoreGreaterThanAndCategoryContains, "US", 9.0, "情");注意
調用的方法除第一個方法引用參數外其他的參數類型要和原方法對應.
全新exists查詢
基于SelectMapper#adapterExists
在原查詢方法上開啟Exists查詢.
示例
Optional<Integer> optional = mapper.existsP3(mapper::findByLocationAndScoreGreaterThanAndCategoryContains, "US", 9.0, "情"); Assertions.assertTrue(optional.isPresent());基于NoSugar內置Api的分頁方式
如果Mapper接口繼承NoSugar的內置通用Mapper,分頁將更加簡單
/*** 分頁查詢** @param entity 實體參數* @param page 分頁參數* @return 分頁數據*/ default Page<T> selectPage(T entity, Page<T> page) {return selectPageX(entity, page, this::count, (tEntity, tPage) -> selectList(EntityToCriterion.getInstance().entityToSimpleCriteriaQuery(tEntity).limit(tPage))); }/*** 分頁查詢** @param criteria 查詢參數* @param page 分頁參數* @return 分頁數據*/ default <C> Page<T> selectPage(CriteriaQuery<T, C> criteria, Page<T> page) {return selectPageX(criteria, page, this::count, (tCriteriaQuery, tPage) -> selectList(tCriteriaQuery.limit(tPage))); }不足
分頁語句的SQl優化只是簡單處理,沒有做過多的優化,使用者可以引入其他庫解析SQL分析語義優化Count語句.實現Dialect#optimizationCountSql即可優化.這塊因為交給使用者.
NoSugar不僅于此
- 無糖配方
- 開放大量接口給與開發者很大的自由度,讓開發者根據自己的程序適配.不必千篇一律
- 性能非常絲滑,大部分功能超越動態標簽,參數越多性能提升越明顯
- 使用簡單,不影響原有項目,無需修改原Mybatis類聲明,沒有重構任何Mybatis基礎配置類,只需增加一個屬性配置即可開啟
- 無縫增強現有Mybatis項目(+功能),即使現在的項目在使用其他Mybatis框架依舊可增強
- 部分功能如分頁,Count查詢,JPA方式的根據方法名查詢,可以單獨選用
- 基礎的增刪改查
- 條件構造
- 插入時主鍵策略
- 批處理增強模式
- 全新的通用分頁方式,無需插件
- 全新的通用Count查詢方法
- 軟刪除
- 樂觀鎖
- 動態表名
- 更易用的值處理器
- Jpa式根據方法名查詢,刪除
總結
以上是生活随笔為你收集整理的MyBatis第N+1种分页方式,全新的MyBatis分页的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: JAVA国际化教程【转载】
- 下一篇: 5.4.7 延迟的心跳
