MyLogicDeleteInnerInterceptor.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. package jnpf.database.plugins;
  2. import com.baomidou.mybatisplus.core.metadata.TableInfo;
  3. import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
  4. import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
  5. import com.baomidou.mybatisplus.core.toolkit.*;
  6. import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
  7. import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
  8. import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
  9. import com.baomidou.mybatisplus.extension.toolkit.PropertyMapper;
  10. import jnpf.database.util.LogicDeleteHelper;
  11. import jnpf.util.StringUtil;
  12. import io.swagger.v3.oas.annotations.media.Schema;
  13. import lombok.Data;
  14. import lombok.extern.slf4j.Slf4j;
  15. import net.sf.jsqlparser.JSQLParserException;
  16. import net.sf.jsqlparser.expression.*;
  17. import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
  18. import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
  19. import net.sf.jsqlparser.expression.operators.relational.*;
  20. import net.sf.jsqlparser.parser.CCJSqlParserUtil;
  21. import net.sf.jsqlparser.schema.Column;
  22. import net.sf.jsqlparser.schema.Table;
  23. import net.sf.jsqlparser.statement.Statement;
  24. import net.sf.jsqlparser.statement.delete.Delete;
  25. import net.sf.jsqlparser.statement.insert.Insert;
  26. import net.sf.jsqlparser.statement.select.*;
  27. import net.sf.jsqlparser.statement.update.Update;
  28. import net.sf.jsqlparser.statement.update.UpdateSet;
  29. import org.apache.ibatis.executor.Executor;
  30. import org.apache.ibatis.executor.statement.StatementHandler;
  31. import org.apache.ibatis.mapping.BoundSql;
  32. import org.apache.ibatis.mapping.MappedStatement;
  33. import org.apache.ibatis.mapping.SqlCommandType;
  34. import org.apache.ibatis.session.ResultHandler;
  35. import org.apache.ibatis.session.RowBounds;
  36. import java.sql.Connection;
  37. import java.sql.SQLException;
  38. import java.util.*;
  39. import java.util.stream.Collectors;
  40. /**
  41. * 逻辑删除插件
  42. * @author JNPF开发平台组
  43. * @user N
  44. * @copyright 引迈信息技术有限公司
  45. * @date 2022/10/14 10:29
  46. */
  47. @Data
  48. @Slf4j
  49. public class MyLogicDeleteInnerInterceptor extends TenantLineInnerInterceptor implements InnerInterceptor {
  50. private LogicDeleteHandler logicDeleteHandler;
  51. private static List<String> tableName = new ArrayList<>();
  52. public MyLogicDeleteInnerInterceptor() {
  53. MyLogicDeleteInnerInterceptor instance = this;
  54. super.setTenantLineHandler(new TenantLineHandler() {
  55. @Override
  56. public String getTenantIdColumn() {
  57. return logicDeleteHandler.getLogicDeleteColumn();
  58. }
  59. @Override
  60. public Expression getTenantId() {
  61. return logicDeleteHandler.getNotDeletedValue();
  62. }
  63. @Override
  64. public boolean ignoreTable(String tableName) {
  65. return instance.ignoreTable(tableName);
  66. }
  67. });
  68. }
  69. private boolean isRemoveLogic(){
  70. return LogicDeleteHelper.isIgnoreLogicDelete();
  71. }
  72. @Override
  73. public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
  74. //MybatisPlus自带方法不处理, 兼容Plus、PlusJoin 见MyDefaultSqlInjector
  75. if (InterceptorIgnoreHelper.willIgnoreOthersByKey(ms.getId(), MyDefaultSqlInjector.ignoreLogicPrefix)) return;
  76. //方法名包含ignorelogic不过滤
  77. if (ms.getId().endsWith(MyDefaultSqlInjector.ignoreLogicPrefix)) return;
  78. try {
  79. if(!isRemoveLogic()) {
  80. //添加逻辑删除
  81. if(boundSql.getSql().toLowerCase().contains(logicDeleteHandler.getLogicDeleteColumn().toLowerCase())){
  82. //包含逻辑删除字段不处理
  83. return;
  84. }
  85. }
  86. PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
  87. mpBs.sql(parserSingle(mpBs.sql(), null));
  88. } catch (Exception e){
  89. //特殊语句解析失败
  90. if(log.isDebugEnabled()){
  91. log.debug("语句解析失败", e);
  92. }
  93. }
  94. }
  95. @Override
  96. public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
  97. PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
  98. MappedStatement ms = mpSh.mappedStatement();
  99. //MybatisPlus自带方法不处理, 兼容Plus、PlusJoin 见MyDefaultSqlInjector
  100. if (InterceptorIgnoreHelper.willIgnoreOthersByKey(ms.getId(), MyDefaultSqlInjector.ignoreLogicPrefix)) {
  101. return;
  102. }
  103. //方法名包含ignorelogic不过滤
  104. if (ms.getId().endsWith(MyDefaultSqlInjector.ignoreLogicPrefix)) return;
  105. SqlCommandType sct = ms.getSqlCommandType();
  106. if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
  107. if(!isRemoveLogic()) {
  108. //添加逻辑删除
  109. if (mpSh.mPBoundSql().sql().toLowerCase().contains(logicDeleteHandler.getLogicDeleteColumn().toLowerCase())) {
  110. //包含逻辑删除字段不处理
  111. return;
  112. }
  113. }
  114. try {
  115. PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
  116. mpBs.sql(parserMulti(mpBs.sql(), null));
  117. } catch (Exception e){
  118. //特殊语句解析失败
  119. if(log.isDebugEnabled()){
  120. log.debug("语句解析失败", e);
  121. }
  122. }
  123. }
  124. }
  125. @Override
  126. protected String processParser(Statement statement, int index, String sql, Object obj) {
  127. if (logger.isDebugEnabled()) {
  128. logger.debug("SQL to parse, SQL: " + sql);
  129. }
  130. if (statement instanceof Insert) {
  131. this.processInsert((Insert) statement, index, sql, obj);
  132. } else if (statement instanceof Select) {
  133. this.processSelect((Select) statement, index, sql, obj);
  134. } else if (statement instanceof Update) {
  135. this.processUpdate((Update) statement, index, sql, obj);
  136. } else if (statement instanceof Delete) {
  137. if(isRemoveLogic()) {
  138. //忽略逻辑删除就直接执行删除
  139. this.processDelete((Delete) statement, index, sql, obj);
  140. }else{
  141. //把删除语句替换为修改语句
  142. statement = this.processDeleteToLogicDelete((Delete) statement, index, sql, obj);
  143. }
  144. }
  145. sql = statement.toString();
  146. if (logger.isDebugEnabled()) {
  147. logger.debug("parse the finished SQL: " + sql);
  148. }
  149. return sql;
  150. }
  151. /**
  152. * delete 语句处理
  153. */
  154. protected Statement processDeleteToLogicDelete(Delete delete, int index, String sql, Object obj) {
  155. if (super.getTenantLineHandler().ignoreTable(delete.getTable().getName())) {
  156. // 过滤退出执行
  157. return delete;
  158. }
  159. Update updateStatement = null;
  160. try {
  161. updateStatement = (Update) CCJSqlParserUtil.parse(logicDeleteHandler.getDeleteSql());
  162. } catch (JSQLParserException e) {
  163. throw new RuntimeException(e);
  164. }
  165. updateStatement.setTable(delete.getTable());
  166. updateStatement.setWhere(delete.getWhere());
  167. return updateStatement;
  168. }
  169. @Override
  170. public void setProperties(Properties properties) {
  171. PropertyMapper.newInstance(properties).whenNotBlank("logicDeleteHandler",
  172. ClassUtils::newInstance, this::setLogicDeleteHandler);
  173. }
  174. @Override
  175. public Expression buildTableExpression(Table table, Expression where, String whereSegment) {
  176. if(getTenantLineHandler().ignoreTable(table.getName())){
  177. return null;
  178. }
  179. return getLogicExpression(this.getAliasColumn(table), logicDeleteHandler.getNotDeletedValue());
  180. }
  181. /**
  182. * 逻辑字段别名设置
  183. * <p>F_DELETEMARK 或 tableAlias.F_DELETEMARK</p>
  184. *
  185. * @param table 表对象
  186. * @return 字段
  187. */
  188. @Override
  189. protected Column getAliasColumn(Table table) {
  190. StringBuilder column = new StringBuilder();
  191. // 为了兼容隐式内连接,没有别名时条件就需要加上表名
  192. if (table.getAlias() != null) {
  193. column.append(table.getAlias().getName());
  194. } else {
  195. column.append(table.getName());
  196. }
  197. column.append(StringPool.DOT).append(logicDeleteHandler.getLogicDeleteColumn());
  198. return new Column(column.toString());
  199. }
  200. protected Expression getLogicExpression(Expression column, Expression val){
  201. if("null".equalsIgnoreCase(val.toString())){
  202. IsNullExpression isNullExpression = new IsNullExpression();
  203. isNullExpression.setLeftExpression(column);
  204. isNullExpression.setNot(false);
  205. return isNullExpression;
  206. }else {
  207. return new EqualsTo(column, val);
  208. }
  209. }
  210. private boolean ignoreTable(String table){
  211. if(StringUtil.isEmpty(table) || logicDeleteHandler.ignoreTable(table)){
  212. return true;
  213. }
  214. TableInfo tableInfo = TableInfoHelper.getTableInfo(table);
  215. //无实体暂不执行, 非逻辑删除表不执行
  216. if(tableInfo != null){
  217. return !tableInfo.isWithLogicDelete();
  218. }
  219. return true;
  220. }
  221. // ------------ 移除逻辑删除, 操作全部数据 开始 ------------ //
  222. @Override
  223. protected Expression builderExpression(Expression currentExpression, List<Table> tables, String whereSegment) {
  224. if(isRemoveLogic()) {
  225. return removeCondition(currentExpression);
  226. }
  227. return super.builderExpression(currentExpression, tables, whereSegment);
  228. }
  229. @Override
  230. protected Expression andExpression(Table table, Expression where, String whereSegment) {
  231. if(isRemoveLogic()) {
  232. return removeCondition(where);
  233. }
  234. return super.andExpression(table, where, whereSegment);
  235. }
  236. /**
  237. * 移除SQL中的逻辑删除条件
  238. * @param expression
  239. * @return
  240. */
  241. private Expression removeCondition(Expression expression){
  242. if (expression != null) {
  243. String sql = expression.toString();
  244. if(sql.contains(logicDeleteHandler.getLogicDeleteColumn())){
  245. if (expression instanceof AndExpression || expression instanceof OrExpression) {
  246. BinaryExpression expression1 = (BinaryExpression) expression;
  247. expression1.setLeftExpression(removeCondition(expression1.getLeftExpression()));
  248. expression1.setRightExpression(removeCondition(expression1.getRightExpression()));
  249. }
  250. if (expression instanceof EqualsTo || expression instanceof NotEqualsTo || expression instanceof IsNullExpression) {
  251. return new EqualsTo(new LongValue(1), new LongValue(1));
  252. }
  253. }
  254. }
  255. return expression;
  256. }
  257. // ------------ 移除逻辑删除, 操作全部数据 结束 ------------ //
  258. }