MyBatisPlus多表自定義分頁查詢
問題:
我需要對一個文章信息+類型名稱,它們分別屬於不同的表,所以需要進行多表關聯,再其次我需要查詢的數據進行分頁,所以我們還需要加入分頁的相關條件。
兩個實體類:
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="ArticleInfo對象", description="文章信息")
public class ArticleInfo implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "主鍵ID")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "文章類型ID")
private Integer categoryId;
@ApiModelProperty(value = "文章標題")
private String title;
@ApiModelProperty(value = "文章簡介,默認100個漢字以內")
private String summary;
@ApiModelProperty(value = "文章是否置頂,0為否,1為是")
private Integer isTop;
@ApiModelProperty(value = "圖片地址")
private String pictureUrl;
@ApiModelProperty(value = "文章訪問量")
private Integer traffic;
@ApiModelProperty(value = "創建時間")
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "Asia/Shanghai")
private Date createdDate;
@ApiModelProperty(value = "修改日期")
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "Asia/Shanghai")
private Date updatedDate;
@TableField(select = false)
private Category category;
}
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="Category對象", description="類型")
public class Category implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "主鍵id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "分類名稱")
private String name;
@ApiModelProperty(value = "該分類下的文章數量")
private Integer num;
@ApiModelProperty(value = "默認類型圖片地址")
private String prticleUrl;
@ApiModelProperty(value = "分類排序")
private Integer orderNum;
@ApiModelProperty(value = "是否有效,默認為1為有效,0為無效")
private Boolean isEffective;
@ApiModelProperty(value = "分類創建時間")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date createdDate;
@ApiModelProperty(value = "分類修改時間")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date updatedDate;
}
xml的結果集定義:
<!-- 結果集 -->
<resultMap id="BaseResultMap" type="com.jz.blog.entity.ArticleInfo">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="category_id" property="categoryId" jdbcType="INTEGER"/>
<result column="title" property="title" jdbcType="VARCHAR"/>
<result column="summary" property="summary" jdbcType="VARCHAR"/>
<result column="is_top" property="isTop" jdbcType="INTEGER"/>
<result column="picture_url" property="pictureUrl" jdbcType="VARCHAR"/>
<result column="traffic" property="traffic" jdbcType="INTEGER"/>
<result column="created_date" property="createdDate" jdbcType="TIMESTAMP"/>
<result column="updated_date" property="updatedDate" jdbcType="TIMESTAMP"/>
</resultMap>
<!-- 關聯結果集 -->
<resultMap id="AllArticleInfoWithCategory" type="com.jz.blog.entity.ArticleInfo" extends="BaseResultMap">
<association property="category" javaType="com.jz.blog.entity.Category">
<id column="cid" property="id"/>
<result column="cname" property="name" jdbcType="VARCHAR"/>
</association>
</resultMap>
思路一:
MyBatisPlus對於單表提供了很多方法,但是如果想要進行多表關聯查詢,那么我們就要去進行自定義的查詢。
參考selectPage方法
我們開始寫一下我們自己的方法
對應的xml信息
<select id="selectPage2" resultMap="AllArticleInfoWithCategory">
SELECT a.*,
c.id AS cid,
c.name AS cname
FROM article_info a,
category c
WHERE a.category_id = c.id
<if test="ew.sqlSegment != null and ew.sqlSegment != ''">
AND ${ew.sqlSegment}
</if>
</select>
接下來開始進行測試
思路是,文章信息類作為實體參數,配個分頁信息進行查詢
@Test
public void myPageQueryTest2(){
//參數信息
ArticleInfo articleInfo = new ArticleInfo();
articleInfo.setCategoryId(1);
articleInfo.setSummary("摘要1");
QueryWrapper<ArticleInfo> queryWrapper = new QueryWrapper<ArticleInfo>(articleInfo);
//分頁信息
Page<ArticleInfo> page = new Page<ArticleInfo>(1,10);
IPage<ArticleInfo> iPage = articleInfoMapper.selectPage2(page,queryWrapper);
System.out.println(iPage.getRecords().size());
List<ArticleInfo> lists = iPage.getRecords();
lists.forEach(list ->{
System.out.println(list.toString());
});
}
按照預想,實體內參數應該可以自動生成條件語句,${ew.sqlSegment}拼接在SQL中。
但是結果是,並沒有如預想中拼接在后面:
我開始以為我自己寫錯了,然后我替換成selectPage,MyBatisPlus自帶的分頁查詢,開始實驗。
結果是可行的,下面圖片中就只有查詢的方法改變了
然后呢,是不是我自定義寫錯了,我不傳入實體類,傳入表達式。
結果是可行的
那么問題來了?為什么傳入實體類作為參數,自定義的方法中為何不能拼接成sql呢?
這個有待研究~
總結:思路一暫時行不通
思路二:
純mybatis的形勢,咱們不使用mybatis的分頁插件,將分頁的參數、條件對象一一對應去寫。
(這里的page 需要進行 page = (page-1)*size 轉換)
接口:
xml:
<select id="mySelectPage" resultMap="AllArticleInfoWithCategory">
SELECT a.*,
c.id AS cid,
c.name AS cname
FROM article_info a,
category c
Where a.category_id = c.id
<if test="art.title != null and art.title != ''">
and a.title like concat('%',#{art.title},'%')
</if>
<if test="art.summary != null and art.summary != ''">
and a.summary like concat('%',#{art.summary},'%')
</if>
<if test="art.categoryId != null and art.categoryId != ''">
and a.category_id = #{art.categoryId}
</if>
<if test="page !=null and size!=null">
limit #{page},#{size}
</if>
</select>
測試代碼:
@Test
public void myPageQueryTest3(){
ArticleInfo articleInfo = new ArticleInfo();
articleInfo.setCategoryId(1);
articleInfo.setSummary("摘要1");
List<ArticleInfo> lists = articleInfoMapper.mySelectPage(1,10,articleInfo);
System.out.println(lists.size());
lists.forEach(list ->{
System.out.println(list.toString());
});
}
測試結果是可行的
==> Preparing: SELECT a.*, c.id AS cid, c.name AS cname FROM article_info a, category c Where a.category_id = c.id and a.summary like concat('%',?,'%') and a.category_id = ? limit ?,?
==> Parameters: 摘要1(String), 1(Integer), 1(Integer), 10(Integer)
但是這個有一點欠缺的是,返回的是list合集,而且是本次查詢的結果合集,我們分頁查詢肯定少不了總數,單純用mybatis的話,咱們要再寫一個查詢總數的方法,進行查詢。我們使用MyBatisp的分頁插件的時候,已經直接進行了總數查詢,所以我們就直接二者結合來用。
思路三:
MyBatisPlus的分頁插件+實體傳參的形式
接口:
xml:
<select id="selectPageWithCategory" resultMap="AllArticleInfoWithCategory">
SELECT a.*,
c.id AS cid,
c.name AS cname
FROM article_info a,
category c
Where a.category_id = c.id
<if test="art.title != null and art.title != ''">
and a.title like concat('%',#{art.title},'%')
</if>
<if test="art.summary != null and art.summary != ''">
and a.summary like concat('%',#{art.summary},'%')
</if>
<if test="art.categoryId != null and art.categoryId != ''">
and a.category_id = #{art.categoryId}
</if>
order by a.id desc
</select>
測試代碼:
@Test
public void myPageQueryTest(){
ArticleInfo articleInfo = new ArticleInfo();
articleInfo.setCategoryId(1);
articleInfo.setSummary("摘要1");
Page<ArticleInfo> page = new Page<ArticleInfo>(1,10);
IPage<ArticleInfo> iPage = articleInfoMapper.selectPageWithCategory(page,articleInfo);
System.out.println(iPage.getRecords().size());
List<ArticleInfo> lists = iPage.getRecords();
lists.forEach(list ->{
System.out.println(list.getCategory().getName());
});
}
測試結果可行,進行了兩次查詢,一次總數一次結果,且包含了我需要的分類表數據
總結
思路一參考MyBatisPlus的selectPage方法,但是目前暫時不知道為啥實體參數帶不出來,后面有時間研究一下。
思路二是純mybatis,一一對應還是很容易明白的
思路三是偷懶的方法,省了一次查詢總數的方法