有關Mybatis-Plus常用功能之前有做過一篇總結:
一、什麼是SQL隱碼攻擊器
我們在使用Mybatis-Plus時,dao層都會去繼承BaseMapper介面,這樣就可以用BaseMapper介面所有的方法,
BaseMapper中每一個方法其實就是一個SQL隱碼攻擊器
在Mybatis-Plus的核心(core)包下,提供的預設可注入方法有這些:
那如果我們想自定義SQL隱碼攻擊器呢,我們該如何去做?
比如在Mybatis-Plus中呼叫updateById方法進行資料更新預設情況下是不能更新空值欄位的。
而在實際開發過程中,往往會遇到需要將欄位值更新為空值的情況。
那如何讓Mybatis-Plus支援空值更新呢?
如果僅是想實現支援更新空值欄位並不需要我們自定義SQL隱碼攻擊器,因為Mybatis-Plus提供了幾個擴充套件SQL隱碼攻擊器。
二、內建擴充套件SQL隱碼攻擊器有哪些?
1、自帶擴充套件SQL隱碼攻擊器
Mybatis-Plus 擴充套件SQL隱碼攻擊器在擴充套件包下,為我們提供了可擴充套件的可注入方法:
AlwaysUpdateSomeColumnById
: 根據id更新欄位(全量更新不忽略null欄位),updateById預設會自動忽略實體中null值欄位。
InsertBatchSomeColumn
: 真實批次插入,saveBatch其實是偽批次插入。
LogicDeleteBatchByIds
: 邏輯刪除增加填充功能,比如刪除的時候填充更新時間、更新人。
Upsert
: 插入一條資料(選擇欄位插入)。
2、SQL隱碼攻擊器全域性配置
@Component
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
/**
* 把兩個擴充套件內建擴充套件SQL隱碼攻擊器注入
*/
methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
methodList.add(new AlwaysUpdateSomeColumnById(i -> i.getFieldFill() != FieldFill.INSERT));
return methodList;
}
}
3、自定義Mapper
public interface MyBaseMapper<T> extends BaseMapper<T> {
/**
* 全欄位更新,不會忽略null值
*
* @param entity 實體物件
*/
int alwaysUpdateSomeColumnById(T entity);
/**
* 全量插入,等價於insert
*
* @param entityList 實體集合
*/
int insertBatchSomeColumn(List<T> entityList);
}
三、擴充套件SQL隱碼攻擊器示例測試
1、使用者表
CREATE TABLE `user` (
`id` int unsigned AUTO_INCREMENT COMMENT '主鍵',
`username` varchar(128) COMMENT '使用者名稱',
`phone` varchar(32) COMMENT '手機號',
`sex` char(1) COMMENT '性別',
`create_time` datetime COMMENT '建立時間',
`update_time` datetime COMMENT '更新時間',
`deleted` tinyint DEFAULT '0' COMMENT '1、刪除 0、未刪除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1
2、建立對應實體
@Data
@Accessors(chain = true)
@TableName("user")
public class UserDO implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 使用者名稱
*/
@TableField("username")
private String username;
/**
* 手機號
*/
@TableField("phone")
private String phone;
/**
* 性別
*/
@TableField("sex")
private String sex;
/**
* 建立時間
*/
@TableField(value = "create_time",fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新時間
*/
@TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
/**
* 1、刪除 0、未刪除
*/
@TableField(value = "deleted",fill = FieldFill.INSERT)
private Integer deleted;
}
其它有關程式碼這裡就不貼上了,具體看專案原始碼。
我們自定義的Mapper不再繼承BaseMapper而是繼承MyBaseMapper
/**
* 通用mapper介面,以後建立其他mapper介面時,不再繼承BaseMapper,而是繼承MyBaseMapper
*/
@Mapper
public interface UserMapper extends MyBaseMapper<UserDO> {
}
3、測試程式碼
@SpringBootTest
@RunWith(SpringRunner.class)
@ComponentScan("com.jincou.mybatisplus.dao")
public class SqlInjectorTest {
@Autowired
private UserMapper mapper;
@Test
public void alwaysUpdateSomeColumnById() {
UserDO user = new UserDO();
user.setUsername("小小");
user.setPhone(null);
user.setSex("女");
user.setId(1);
mapper.alwaysUpdateSomeColumnById(user);
}
@Test
public void insertBatchSomeColumn() {
UserDO user = new UserDO();
user.setUsername("zhangsan");
user.setPhone("13811111111");
user.setSex("女");
UserDO user1 = new UserDO();
user1.setUsername("lisi");
user1.setPhone("13822222222");
user1.setSex("男");
ArrayList<UserDO> userDOS = Lists.newArrayList(user, user1);
mapper.insertBatchSomeColumn(userDOS);
}
}
執行結果
alwaysUpdateSomeColumnById方法
insertBatchSomeColumn方法
成功!
四、如何自定義SQL隱碼攻擊器?
在實際開發過程中,當Mybatis-Plus自帶的一些SQL隱碼攻擊器不滿足我們的條件時,我們就需要自定義SQL隱碼攻擊器,整個流程也非常簡單
這裡我們以一個很簡單的findAll方法為例進行學習。
在MyBaseMapper中新增findAll方法
public interface MyBaseMapper<T> extends BaseMapper<T> {
/**
* 查詢所有使用者
*/
List<T> findAll();
}
2、編寫FindAll SQL隱碼攻擊器
public class FindAll extends AbstractMethod {
public FindAll() {
super("findAll");
}
public FindAll(String methodName) {
super(methodName);
}
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
/* 執行 SQL ,動態 SQL 參考類 SqlMethod */
String sql = "select * from " + tableInfo.getTableName();
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return this.addSelectMappedStatementForTable(mapperClass, sqlSource, tableInfo);
}
}
3、註冊到Spring容器
@Component
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
/**
* 自定義SQL隱碼攻擊器注入
*/
methodList.add(new FindAll());
return methodList;
}
}
4、測試
@Test
public void findAll() {
List<UserDO> userDOS = mapper.findAll();
}
成功!
補充
專案地址: https://github.com/yudiandemingzi/spring-boot-study
Mybatis-Plus官方SQL隱碼攻擊器示例地址:https://baomidou.com/pages/42ea4a/
宣告: 公眾號如需轉載該篇文章,發表文章的頭部一定要 告知是轉至公眾號: 後端元宇宙。同時也可以問本人要markdown原稿和原圖片。其它情況一律禁止轉載!