1.表結構
文章表,實體類和結構一樣
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="BArticle對象", description="")
public class BArticle implements Serializable {
private static final long serialVersionUID=1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 文章標題
*/
@ApiModelProperty(value = "文章標題")
private String title;
/**
* 用戶ID,對應user表id
*/
@ApiModelProperty(value = "用戶ID,對應user表id")
private Long userId;
/**
* 文章封面圖片
*/
@ApiModelProperty(value = "文章封面圖片")
private String coverImage;
/**
* 文章專屬二維碼地址
*/
@ApiModelProperty(value = "文章專屬二維碼地址")
private String qrcodePath;
/**
* 編輯器類型,0 markdown,1 html
*/
@ApiModelProperty(value = "編輯器類型,0 markdown,1 html")
private Integer editorType;
}
用戶表
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="OUser對象", description="")
public class OUser implements Serializable {
private static final long serialVersionUID=1L;
/**
* 用戶ID
*/
@ApiModelProperty(value = "用戶ID")
@TableId(value = "user_id", type = IdType.AUTO)
private Long userId;
/**
* 用戶名
*/
@ApiModelProperty(value = "用戶名")
private String username;
/**
* 郵箱
*/
@ApiModelProperty(value = "郵箱")
private String email;
/**
* 聯繫電話
*/
@ApiModelProperty(value = "聯繫電話")
private String mobile;
/**
* 狀態 0鎖定 1有效
*/
@ApiModelProperty(value = "狀態 0鎖定 1有效")
private Integer status;
/**
* 創建時間
*/
@ApiModelProperty(value = "創建時間")
private LocalDateTime createTime;
/**
* 修改時間
*/
@ApiModelProperty(value = "修改時間")
private LocalDateTime updateTime;
/**
* 最近訪問時間
*/
@ApiModelProperty(value = "最近訪問時間")
private LocalDateTime lastLoginTime;
/**
* 性別 0男 1女
*/
@ApiModelProperty(value = "性別 0男 1女")
private Integer sex;
/**
* 主題
*/
@ApiModelProperty(value = "主題")
private String theme;
/**
* 頭像
*/
@ApiModelProperty(value = "頭像")
private String headImg;
/**
* 描述
*/
@ApiModelProperty(value = "描述")
private String description;
}
一對多
一個作者擁有多篇文章
這裏選擇新建實體類接收
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Accessors(chain = true)
@ApiModel(value="UserArticleDto對象", description="")
public class UserArticleDto extends OUser {
private List<BArticle> articleList;
}
查詢方法一、
@ResultMap("selectUserArticle")
@Select("select a.user_id,a.username,a.email,a.mobile,a.sex,a.theme,a.head_img,
b.* from o_user a left join b_article b on a.user_id=b.user_id")
List<UserArticleDto> selectUserArticle();
映射xml
<!-- 這裏採用一條sql解決,簡單映射,因爲映射結果比較簡單直接自動映射-->
<resultMap id="selectUserArticle" type="com.git.model.dto.UserArticleDto" extends="BaseResultMap">
<collection property="articleList" ofType="com.git.model.entity.BArticle" autoMapping="true"></collection>
</resultMap>
先上sql日誌
2019-09-21 16:53:23.518 DEBUG 17156 --- [ main] c.g.m.OUserMapper.selectUserArticle : ==> Preparing: select a.user_id,a.username,a.email,a.mobile,a.sex,a.theme,a.head_img,b.* from o_user a left join b_article b on a.user_id=b.user_id
2019-09-21 16:53:23.541 DEBUG 17156 --- [ main] c.g.m.OUserMapper.selectUserArticle : ==> Parameters:
2019-09-21 16:53:23.581 DEBUG 17156 --- [ main] c.g.m.OUserMapper.selectUserArticle : <== Total: 22
結果
其實最終結果是以用戶表爲主體,得到10條數據
查詢方法二、
List<UserArticleDto> selectUserArticle2();
映射xml
<resultMap id="selectUserArticle2" type="com.git.model.dto.UserArticleDto" extends="BaseResultMap">
<collection property="articleList" ofType="com.git.model.entity.BArticle" select="selectArticle111" column="user_id" autoMapping="true"></collection>
</resultMap>
<select id="selectUserArticle2" resultMap="selectUserArticle2">
select user_id,username,email,mobile,sex,theme,head_img from o_user
</select>
<select id="selectArticle111" resultType="com.git.model.entity.BArticle">
select * from b_article where user_id=#{user_id}
</select>
這裏面映射裏面使用了第二次查詢,結果和第一種方法一樣的,
但是卻執行的多條sql,這就是所謂的n+1問題,
現在進行分頁,先說第二種分頁處理,這種簡單的處理方式直接用mybatisPlus的分頁
@Test
public void testOneToMany2(){
Page<UserArticleDto> page = new Page<>();
page.setSize(5);
page.setCurrent(2);
page = oUserService.selectUserArticle2(page);
System.out.println(page);
}
@Override
public Page<UserArticleDto> selectUserArticle2(Page<UserArticleDto> page) {
return page.setRecords(oUserMapper.selectUserArticle2(page));
}
List<UserArticleDto> selectUserArticle(Page<UserArticleDto> page);
這種分頁,sql不用改變
最後結果
打印的sql
可以看到這種情況雖然可以分頁但是執行了很多的sql,在不追求性能的情況下簡單處理也未嘗不可。
現在想使用第一種方式進行分頁
主表爲用戶表,現在先查詢主表的條數作爲總記錄數,這裏手工分頁。直接在裏面用limit
改進如下
@Test
public void testOneToMany(){
Page<UserArticleDto> page = new Page<>();
page.setSize(5);
page.setCurrent(1);
page = oUserService.selectUserArticle(page);
System.out.println(page);
}
service裏面手工分頁
@Override
public Page<UserArticleDto> selectUserArticle(Page<UserArticleDto> page) {
//先查詢一次總數
page.setTotal(oUserMapper.selectTotal());//總數
Long current = page.getCurrent();//當前頁
Long size = page.getSize();//每頁大小
Long index = (current-1)*size;//數據庫分佈下標
return page.setRecords(oUserMapper.selectUserArticle(index,size));
}
sql
@ResultMap("selectUserArticle")
@Select("select * from\n" +
"(select user_id,username,email,mobile,sex,theme,head_img from o_user ORDER BY create_time desc LIMIT #{index},#{size}) a\n" +
"left join b_article b on a.user_id=b.user_id")
List<UserArticleDto> selectUserArticle(@Param("index") Long index, @Param("size") Long size);
隨後結果和上面的一樣,唯一不同的就是執行了兩次sql,一次查詢總記錄數,一次查詢數據,並且返回的記錄數不等於分頁條數
打印的sql
2019-09-21 17:10:16.074 DEBUG 5228 --- [ main] com.git.mapper.OUserMapper.selectTotal : ==> Preparing: select count(1) from o_user
2019-09-21 17:10:16.099 DEBUG 5228 --- [ main] com.git.mapper.OUserMapper.selectTotal : ==> Parameters:
2019-09-21 17:10:16.121 DEBUG 5228 --- [ main] com.git.mapper.OUserMapper.selectTotal : <== Total: 1
2019-09-21 17:10:16.124 DEBUG 5228 --- [ main] c.g.m.OUserMapper.selectUserArticle : ==> Preparing: select * from (select user_id,username,email,mobile,sex,theme,head_img from o_user ORDER BY create_time desc LIMIT ?,?) a left join b_article b on a.user_id=b.user_id
2019-09-21 17:10:16.125 DEBUG 5228 --- [ main] c.g.m.OUserMapper.selectUserArticle : ==> Parameters: 0(Long), 5(Long)
2019-09-21 17:10:16.146 DEBUG 5228 --- [ main] c.g.m.OUserMapper.selectUserArticle : <== Total: 17
結束
上面處理方式最簡單的結果就是採用分佈查詢,雖然執行的sql多了但是清晰明瞭,
另外一種其實就是子查詢,先查詢總記錄數,在子查詢裏面分頁。
本文爲作者原創,轉載請申請。