1、AutoSqlInjector :
BaseMapper提供了17個常用方法,但是有些需求這些方法還是不能很好的實現,那么怎么辦呢?
大家肯定會想到是在xml文件中寫sql語句解決。
這樣確實可以,因為MP是只做增強不做改變,我們完全可以按照mybatis的原來的方式來解決。
不過MP也提供了另一種解決辦法,那就是自定義全局操作。
所謂自定義全局操作,也就是我們可以在mapper中自定義一些方法,然后通過某些操作,讓自定義的這個方法也能像BaseMapper的內置方法,供全局調用。
接下來就看看如何實現(以deleteAll方法為例)。
1.1在mapper中定義方法
public interface EmplopyeeDao extends BaseMapper<Employee> {
int deleteAll();
}
public interface UserDao extends BaseMapper<User> {
int deleteAll();
}
在這兩個mapper接口中都定義了deleteAll方法。
1.2 編寫自定義注入類
該類繼承AutoSqlInjector,重寫inject方法。
然后編寫sql語句,指定mapper接口中的方法,最后調用addDeleteMappedStatement方法即可。
public class MySqlInjector extends AutoSqlInjector {
@Override
public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant,
Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
/* 添加一個自定義方法 */
deleteAllUser(mapperClass, modelClass, table);
System.out.println(table.getTableName());
}
public void deleteAllUser(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
/* 執行 SQL ,動態 SQL 參考類 SqlMethod */
String sql = "delete from " + table.getTableName();
/* mapper 接口方法名一致 */
String method = "deleteAll";
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
this.addDeleteMappedStatement(mapperClass, method, sqlSource);
}
}
1.3 在Spring文件中配置
先把剛才自定義的類注冊成bean,然后在全局策略配置的bean中引用自定義類的bean即可。
<!-- 定義自定義注入器 -->
<bean class="com.zhu.mybatisplus.injector.MySqlInjector" id="mySqlInjector"/>
..........
<!-- 5、mybatisplus的全局策略配置 -->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<property name="idType" value="0"/>
<property name="tablePrefix" value="tb_"/>
<!-- 注入自定義全局操作 -->
<property name="sqlInjector" ref="mySqlInjector"/>
</bean>
1.4 測試
經測試,當userDao調用deleteAll方法時,會刪除tb_user表的所有數據,employeeDao調用deleteAll方法時,會刪除tb_employee表的所有數據。
說明deleteAll方法是有效的。
不過在運行這兩個測試時,由於是全表刪除操作,所有要先把執行分析插件關了。
@Test
public void testMySqlInjector(){
Integer result = userDao.deleteAll();
System.out.println(result);
}
@Test
public void testMySqlInjector2(){
Integer result = emplopyeeDao.deleteAll();
System.out.println(result);
}
2、邏輯刪除
其實數據並不會輕易的刪除掉,畢竟數據收集不易,所以就有了邏輯刪除。
邏輯刪除: 並不會真正的從數據庫中將數據刪除掉,而是將當前被刪除的這條數據中的一個邏輯刪除字段置為刪除狀態,
比如該數據有一個字段logic_flag,當其值為1表示未刪除,值為-1表示刪除,那么邏輯刪除就是將1變成-1。
2.1 數據表
在數據表中需要添加邏輯刪除字段(logic_flag)
2.2 實體類
數據庫中邏輯刪除字段是logic_flag,所以實體類中的logicFlag需要用@TableLogic注解標記。
@Data
public class User{
private Integer id;
private String name;
private Integer age;
private Integer gender;
@TableLogic //標記邏輯刪除屬性
private Integer logicFlag;
}
2.3 mapper
public interface UserDao extends BaseMapper<User> {
}
2.4 需要在spring-dao.xml中做如下配置:
首先定義邏輯刪除的bean:
<!-- 邏輯刪除 -->
<bean class="com.baomidou.mybatisplus.mapper.LogicSqlInjector" id="logicSqlInjector"/>
再在全局配置的bean中注入邏輯刪除以及邏輯刪除值:
<!-- 5、mybatisplus的全局策略配置 -->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 此處省略其他全局配置 -->
<!-- 注入自定義全局操作,做邏輯刪除時需要先注釋掉 -->
<!--<property name="sqlInjector" ref="mySqlInjector"/>-->
<!-- 注入邏輯刪除,先要把自定義的注釋掉 -->
<property name="sqlInjector" ref="logicSqlInjector"/>
<!-- 注入邏輯刪除值 -->
<property name="logicDeleteValue" value="-1"/><!-- -1是刪除狀態 -->
<property name="logicNotDeleteValue" value="1"/><!-- 1是未刪除狀態 -->
</bean>
因為邏輯刪除實際上也是一個sqlInjector,所以先要把剛才做自定義全局操作時注入的自定義全局操作注釋掉,上面代碼中已有詳細注釋說明。
2.5 測試
@Test
public void testLogicDelete(){
Integer result = userDao.deleteById(1);
System.out.println(result);
//User user = userDao.selectById(1);
//System.out.println(user);
}
運行該測試,執行刪除操作的時候,真正執行的sql語句是UPDATE tb_user SET logic_flag=-1 WHERE id=?,就是把邏輯刪除字段的值設置為-1;
當邏輯刪除字段的值是-1時再執行查詢操作,sql是SELECT ... FROM tb_user WHERE id=? AND logic_flag=1,所以查詢結果是null。