1. Mybaits-plus實戰(三)
1.1. 特殊使用規則
1.1.1. Model邏輯刪除
- 數據庫對應實體類,繼承Model類能夠實現AR模式的sql語句操做,但這裏須要注意的是,對邏輯刪除,官方說明須要實現以下重寫方法才能生效,也就是使用
實例化對象.deleteById()
@Override
protected Serializable pkVal() {
/**
* AR 模式這個必須有,不然 xxById 的方法都將失效!
* 另外 UserMapper 也必須 AR 依賴該層注入,有可無 XML
*/
return id;
}
- 事實上,在主鍵字段添加
@TableId(value = "id", type = IdType.AUTO)
該註解,效果等同上面
- 還要注意的,對邏輯刪除字段不要加
transient
修飾詞,不然邏輯刪除也會不生效
1.1.2. MetaObjectHandler統一數據庫操做數據處理
- 你能夠在操做數據庫前打印日誌,也能夠對即將輸入的數據作修改
- 重要的是,若是你只是實現了這個接口實現類,並注入了Spring,對你修改的字段,返回前端的數據是會有修改的內容,可是插入或更新數據庫是不存在的;這裏你須要作的是在要進行插入或修改的字段上面加上註解
@TableField(fill = FieldFill.INSERT)
,這裏FieldFill
有四種選擇,以下,它默認是不作處理的,因此必定要填個
public enum FieldFill {
/**
* 默認不處理
*/
DEFAULT,
/**
* 插入填充字段
*/
INSERT,
/**
* 更新填充字段
*/
UPDATE,
/**
* 插入和更新填充字段
*/
INSERT_UPDATE
}
- 效果以下
1.1.3. 級聯操做
- 對自定義語句條件用wrapper包裝,實現多表聯合查詢也能夠用鏈式的條件查詢
- 例子基本都在下面了
//可直接在這裏定義方法列表,默認只有在類上加註解纔會支持方法
@QuerySupport("selectPageByCustomWithXml")
public interface UserMapper extends BaseMapper<User> {
String JOIN_SQL = "SELECT user.*, role.name as role_name, role.create_time as role_create_time FROM user as user LEFT JOIN role as role ON user.role_id = role.id";
@QuerySupport
@Select("SELECT user.*, role.name as role_name, role.create_time as role_create_time FROM user as user LEFT JOIN role as role ON user.role_id = role.id")
List<UserRoleVO> findUserWithRoleByVoWithQueryList(@Param(Constants.WRAPPER) QueryWrapper<UserRoleVO> wrapper);
@QuerySupport
@Select(JOIN_SQL)
List<User> selectListByCustom(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
/**
* 使用mybatis-plus自定義分頁查詢,使用resultMap將結果解析到關聯對象中
*
* @param page 必須爲第一個參數
* @param wrapper
* @return
*/
//類型優先級 (若未存在註解,當類型與mapper泛型不一致時使用其自己) @ResultType > @ResultMap > @Table(在類型一致時應用存在的resultMap)
@ResultMap("userCascadeResult")
@QuerySupport
@Select({"<script>", JOIN_SQL, "</script>"})
Page<User> selectPageByCustom(Page<User> page, @Param(Constants.WRAPPER) Wrapper<User> wrapper);
@QuerySupport
Page<User> selectPageByCustomWithXml(Page<User> page, @Param(Constants.WRAPPER) Wrapper<User> wrapper);
@QuerySupport
@Select({JOIN_SQL, "WHERE user.id = #{id}"})
User selectCascadeById(Serializable id);
@ResultMap("userCascadeResult")
@Select({JOIN_SQL, "WHERE user.id = #{id}"})
User selectCascadeById2(Serializable id);
@QuerySupport
@Select({"${text}"})
List<User> selectByText(@Param("text") String text, @Param(Constants.WRAPPER) Wrapper<User> wrapper);
/**
* Wrapper支持select指定列的方式
* @param wrapper
* @return
*/
@QuerySupport
@Select("SELECT %s FROM user as user LEFT JOIN role as role ON user.role_id = role.id")
List<UserRoleVO> findUserWithRoleByVoWithQueryListAndColumns(@Param(Constants.WRAPPER) Wrapper<UserRoleVO> wrapper);
@ResultMap("userNotCascadeResult")
@QuerySupport
@Select("SELECT %s FROM user")
Page<User> selectPageByCustomWithAssociationAndColumns(Page<User> page, @Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
<select id="selectPageByCustomWithXml" resultMap="userCascadeResult">
SELECT user.*,
role.name as role_name,
role.create_time as role_create_time
FROM user as user
LEFT JOIN role as role
ON user.role_id = role.id
</select>
1.1.4. 增刪改查技巧
@Resource
private UserMapper mapper;
- 增
mapper.insert(
new User().setId(10086L)
.setName("miemie")
.setEmail("miemie@baomidou.com")
.setAge(3));
- 刪
mapper.delete(new QueryWrapper<User>()
.lambda().eq(User::getName, "Sandy"))
- 改
mapper.update(
new User().setEmail("miemie@baomidou.com"),
new QueryWrapper<User>()
.lambda().eq(User::getId, 2)
);
- 查
User user = mapper.selectOne(new QueryWrapper<User>().lambda().eq(User::getId, 10086));
List<User> users = mapper.selectList(Wrappers.<User>query().orderByAsc("age"));
1.1.5. 查詢去字段技巧
- 以前說過一個,經過加
transient
,利用jackson或fastjson,在返回前端的時候對它作處理去掉對應的字段,但同時咱們又遇到個問題,好比del_flag
,該字段每每前端不須要,但又不能加transient
,緣由上面也說了會致使邏輯刪除功能失效,這時,還有個辦法解決
- 在實體字段上加上註解
@TableField(select = false)
,表示在進行sql查詢時,去掉該字段的查詢,這是在sql層面去掉該字段的查詢,固然,若是你明確sql要查詢這個字段仍是能夠查的
/**
* 添加transient會致使邏輯刪除模式失效
*/
@ApiModelProperty(value = "是否刪除:0-正常 1-軟刪除")
@TableLogic
@TableField(select = false)
private Integer delFlag;
1.1.6. 子查詢和嵌套查詢
System.out.println("----- 帶子查詢(sql注入) ------");
List<User> plainUsers2 = userMapper.selectList(new QueryWrapper<User>()
.inSql("role_id", "select id from role where id = 2"));
List<User> lambdaUsers2 = userMapper.selectList(new QueryWrapper<User>().lambda()
.inSql(User::getRoleId, "select id from role where id = 2"));
Assert.assertEquals(plainUsers2.size(), lambdaUsers2.size());
print(plainUsers2);
System.out.println("----- 帶嵌套查詢 ------");
List<User> plainUsers3 = userMapper.selectList(new QueryWrapper<User>()
.nested(i -> i.eq("role_id", 2L).or().eq("role_id", 3L))
.and(i -> i.ge("age", 20)));
List<User> lambdaUsers3 = userMapper.selectList(new QueryWrapper<User>().lambda()
.nested(i -> i.eq(User::getRoleId, 2L).or().eq(User::getRoleId, 3L))
.and(i -> i.ge(User::getAge, 20)));
Assert.assertEquals(plainUsers3.size(), lambdaUsers3.size());
print(plainUsers3);
----- 帶子查詢(sql注入) ------
SELECT id,name,age,email,role_id FROM user WHERE role_id IN (select id from role where id = 2)
----- 帶嵌套查詢 ------
SELECT id,name,age,email,role_id FROM user WHERE ( role_id = ? OR role_id = ? ) AND ( age >= ? )
1.2. 其它功能點(基本都是插件)
- 性能分析(sql執行時間)
- 樂觀鎖
- 分頁
- 主鍵生成器
- 自定義sql
- 多租戶
1.3. 總結
- 其它功能點不是前面已經寫過例子的,就是不多使用
- 到如今我已經把mybatis-plus的全部官方文檔和sample代碼例子都看了一遍,也作了一些總結和特別標註,畢竟不少功能可能暫時用不到不表明之後用不到,在總結此篇的時候也讓我對此前的博客有些技術上的修正,好比
MetaObjectHandler
的使用,並非只能把值放返回對象,它是能夠直接插入數據庫的
- mybatis-plus的總結工做到如今結束了,知識點應該已經歸納了官方文檔的全部,有啥意見建議請下面提^_^