【MybatisPlus进阶学习(八)】SQL注入器
使用SQL注入器就可以自定義例如selectById的默認(rèn)方法。
實(shí)現(xiàn)步驟
Step1:創(chuàng)建定義方法的類;
Step2:創(chuàng)建注入器;
Step3:在Mapper中加入自定義方法。
自定義注入器的簡(jiǎn)單使用
第一步:創(chuàng)建定義方法的類
public class DeleteAllMethod extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
//執(zhí)行的SQL
String sql = "delete from " + tableInfo.getTableName();
//mapper接口方法名
String method = "deleteAll";
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
return addDeleteMappedStatement(mapperClass, method, sqlSource);
}
}
第二步:創(chuàng)建注入器
@Component
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
//MP自定義的SQL語(yǔ)句,如果不添加,MP自定義的語(yǔ)句就不能用了
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new DeleteAllMethod());
return methodList;
}
}
DefaultSqlInjector、AbstractSqlInjector、ISqlInjector都能繼承。
第三步:在UserMapper中加入自定義方法deleteAll
/**
* 刪除所有數(shù)據(jù)
* @return 影響行數(shù)
*/
int deleteAll();
第四步:測(cè)試
@Test
public void deleteAll() {
userMapper.deleteAll();
}
結(jié)果如下:
這里需要注意:
不知道大家還記不記得之前邏輯刪除,3.1.2之前的版本配置了一個(gè)SQL注入器。自定義SQL注入器不可以和邏輯刪除一起配置,因?yàn)椴荒芡瑫r(shí)制定兩個(gè)sql注入器,所以報(bào)錯(cuò)。有一個(gè)辦法就是MySqlinjector不要繼承DefaultSqlInjector直接繼承LogicSqlInjector就可以了,這樣配置這一個(gè)sql注入器,就既能使用邏輯刪除又能加入自定義方法了。
如果報(bào)以下錯(cuò)誤
當(dāng)刪除所有數(shù)據(jù)時(shí),由于有的數(shù)據(jù)行有外鍵的約束,不允許你進(jìn)行物理刪除。使用語(yǔ)句刪除外鍵即可,alter table user drop foreign key manager_fk;?;蛘甙淹怄I字段原來(lái)默認(rèn)的Restrict改成CASCADE。
同時(shí)附上初始化數(shù)據(jù)語(yǔ)句,可以多次嘗試
#初始化數(shù)據(jù):
INSERT INTO user (id, name, age, email, manager_id
, create_time)
VALUES (1087982257332887553, '大boss', 40, 'boss@baomidou.com', NULL
, '2019-01-11 14:20:20'),
(1088248166370832385, '王天風(fēng)', 25, 'wtf@baomidou.com', 1087982257332887553
, '2019-02-05 11:12:22'),
(1088250446457389058, '李藝偉', 28, 'lyw@baomidou.com', 1088248166370832385
, '2019-02-14 08:31:16'),
(1094590409767661570, '張雨琪', 31, 'zjq@baomidou.com', 1088248166370832385
, '2019-01-14 09:15:15'),
(1094592041087729666, '劉紅雨', 32, 'lhm@baomidou.com', 1088248166370832385
, '2019-01-14 09:48:16');
優(yōu)化
如果每張表都需要?jiǎng)h除全部,那我們?yōu)槊總€(gè)Mapper都寫一個(gè)deleteAll()方法,非常的繁瑣。這時(shí)候我們可以自己建立一個(gè)MyMapper接口,MyMapper接口繼承BaseMapper,而類似于UserMapper的自定義Mapper全部繼承MyMapper,這樣我們就只需要在MyMapper中編寫一個(gè)deleteAll方法,再由UserMpper和其他Mapper繼承就可以實(shí)現(xiàn)deleteAll()方法的重用。
選裝件InsertBatchSomeColumn
選擇件其實(shí)也是自定義SQL注入器,但是是由官方提供的。InsertBatchSomeColumn的主要功能是批量新增數(shù)據(jù),自選字段insert。接下來(lái)讓我們看看是如何實(shí)現(xiàn)的吧。
第一步:注入器中加入方法
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
//MP自定義的SQL語(yǔ)句,如果不添加,MP自定義的語(yǔ)句就不能用了
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
methodList.add(new DeleteAllMethod());
//加入選裝件InsertBatchSomeColumn,同時(shí)排除邏輯刪除字段
methodList.add(new InsertBatchSomeColumn(t->!t.isLogicDelete()));
return methodList;
}
第二步:在MyMapper中加入insertBatchSomeColumn方法
public interface MyMapper<T> extends BaseMapper<T> {
/**
* 刪除所有數(shù)據(jù)
* @return 影響行數(shù)
*/
int deleteAll();
int insertBatchSomeColumn(List<T> list);
}
第三步:測(cè)試
@Test
public void insertBatchSomeColumn() {
User user = new User();
user.setName("王聚義");
user.setAge(26);
user.setEmail("wjy@163.com");
user.setManagerId(1088248166370832385L);
User user2 = new User();
user2.setName("王收義");
user2.setAge(28);
user2.setEmail("wsy@163.com");
user2.setManagerId(1088248166370832385L);
List<User> list = new ArrayList<>();
list.add(user);
list.add(user2);
userMapper.insertBatchSomeColumn(list);
}
可以看出批量插入成功。
需要注意的是,User對(duì)象中為Null的值會(huì)覆蓋沒(méi)有被排除字段的默認(rèn)值。例如version的默認(rèn)值為1,但是我們插入的User的version為null,如果version這個(gè)字段在注入器組件中沒(méi)有被排除,結(jié)果數(shù)據(jù)庫(kù)中的值應(yīng)該為null。
同時(shí)作者在注解中也提示,選裝器只在mysql中測(cè)試過(guò),所以慎用。
選裝件LogicDeleteByIdWithFill
LogicDeleteByIdWithFill的主要功能是根據(jù)id邏輯刪除數(shù)據(jù)并帶字段填充功能。例如在刪除的時(shí)候需要添加操作人。
第一步:注入器中加入方法
methodList.add(new LogicDeleteByIdWithFill());
第二步:在MyMapper中加入方法
int deleteByIdWithFill(T entity);
第三步:測(cè)試
@Test
public void deleteByIdWithFill() {
User user = new User();
user.setId(1346432120618147841L);
user.setUpdateTime(LocalDateTime.now());
userMapper.deleteByIdWithFill(user);
}
注意,如果想在刪除的同時(shí)修改數(shù)據(jù),被修改的數(shù)據(jù)必須有自動(dòng)填充標(biāo)識(shí),不然無(wú)法完成更新。結(jié)果如下:
選裝件AlwaysUpdateSomeColumnById
AlwaysUpdateSomeColumnById的主要功能是根據(jù)id更新固定的某些字段。
第一步:注入器中加入方法
methodList.add(new AlwaysUpdateSomeColumnById(t->!t.getColumn().equals("name")));
第二步:在MyMapper中加入方法
int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY) T entity);
第三步:測(cè)試
@Test
public void alwaysUpdateSomeColumnById() {
User user = new User();
user.setId(1346432120618147841L);
user.setName("王地風(fēng)");
user.setAge(16);
userMapper.alwaysUpdateSomeColumnById(user);
}
結(jié)果如下:
相關(guān)閱讀:
總結(jié)
以上是生活随笔為你收集整理的【MybatisPlus进阶学习(八)】SQL注入器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。