MyDefaultSqlInjector.java 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package jnpf.database.plugins;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import com.baomidou.mybatisplus.core.injector.AbstractMethod;
  4. import com.baomidou.mybatisplus.core.injector.AbstractSqlInjector;
  5. import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
  6. import com.baomidou.mybatisplus.core.injector.ISqlInjector;
  7. import com.baomidou.mybatisplus.core.metadata.TableInfo;
  8. import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
  9. import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
  10. import jnpf.config.ApplicationStartErrorCheck;
  11. import jnpf.config.ConfigValueUtil;
  12. import jnpf.util.ReflectionUtil;
  13. import org.apache.ibatis.builder.MapperBuilderAssistant;
  14. import org.apache.ibatis.session.Configuration;
  15. import org.springframework.cglib.proxy.Enhancer;
  16. import org.springframework.cglib.proxy.MethodInterceptor;
  17. import org.springframework.cglib.proxy.MethodProxy;
  18. import org.springframework.util.ReflectionUtils;
  19. import java.lang.reflect.Field;
  20. import java.lang.reflect.Method;
  21. import java.util.*;
  22. /**
  23. * MyBatisPlus自定义方法实现
  24. * 给默认方法新增IgnoreLogic结尾的方法用于操作已逻辑删除的数据
  25. * @author JNPF开发平台组
  26. * @user N
  27. * @copyright 引迈信息技术有限公司
  28. * @date 2023/02/06 10:29
  29. */
  30. public class MyDefaultSqlInjector extends DefaultSqlInjector {
  31. private AbstractSqlInjector sqlInjector;
  32. private ConfigValueUtil configValueUtil;
  33. public static final String ignoreLogicPrefix = "Ilg";
  34. //MP、MPJ的MP方法名集合
  35. public static final Set<String> IGNOREMETHOD = new HashSet<>();
  36. public MyDefaultSqlInjector(ConfigValueUtil configValueUtil) {
  37. this(null, configValueUtil);
  38. }
  39. public MyDefaultSqlInjector(ISqlInjector sqlInjector, ConfigValueUtil configValueUtil) {
  40. this.configValueUtil = configValueUtil;
  41. if (Objects.nonNull(sqlInjector) && sqlInjector instanceof AbstractSqlInjector) {
  42. this.sqlInjector = (AbstractSqlInjector) sqlInjector;
  43. }
  44. }
  45. /* @Override
  46. public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
  47. List<AbstractMethod> innerMethod;
  48. if (Objects.nonNull(sqlInjector)) {
  49. innerMethod = methodFilter(sqlInjector.getMethodList(mapperClass, tableInfo));
  50. } else {
  51. innerMethod = methodFilter(super.getMethodList(mapperClass, tableInfo));
  52. }
  53. //将内置列表加入排除列表
  54. return innerMethod;
  55. }*/
  56. @Override
  57. public List<AbstractMethod> getMethodList(Configuration configuration, Class<?> mapperClass, TableInfo tableInfo) {
  58. return sqlInjector == null ? super.getMethodList(configuration, mapperClass, tableInfo) : sqlInjector.getMethodList(configuration, mapperClass, tableInfo);
  59. }
  60. @Override
  61. public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
  62. // 多线程初始化Mybatis接口
  63. ApplicationStartErrorCheck.getApplicationInitThreadPool().execute(() -> {
  64. try {
  65. super.inspectInject(builderAssistant, mapperClass);
  66. } catch (Exception e) {
  67. ApplicationStartErrorCheck.setStartError();
  68. throw e;
  69. }
  70. });
  71. }
  72. private List<AbstractMethod> methodFilter(List<AbstractMethod> list) {
  73. if (!configValueUtil.isEnableLogicDelete()) {
  74. return list;
  75. }
  76. for (int i = 0; i < list.size(); i++) {
  77. AbstractMethod abstractMethod = list.get(i);
  78. abstractMethod = enhancerMethod(abstractMethod);
  79. list.set(i, abstractMethod);
  80. }
  81. return list;
  82. }
  83. private AbstractMethod enhancerMethod(AbstractMethod method) {
  84. Enhancer enhancer = new Enhancer();
  85. enhancer.setSuperclass(method.getClass());
  86. enhancer.setCallback(new MethodInterceptor() {
  87. @Override
  88. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  89. handleAddMappedStatement(o, method, objects, methodProxy);
  90. handleInject(o, method, objects, methodProxy);
  91. return methodProxy.invokeSuper(o, objects);
  92. }
  93. });
  94. return (AbstractMethod) enhancer.create(new Class[]{String.class}, new Object[]{ReflectionUtil.getFieldValue(method, "methodName")});
  95. }
  96. public void handleAddMappedStatement(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws IllegalAccessException {
  97. //记录自带的方法
  98. if (method.getName().equals("addMappedStatement") && objects.length > 1 && objects[1] instanceof String) {
  99. String id = (String) objects[1];
  100. Field builderAssistantField = ReflectionUtils.findField(AbstractMethod.class, "builderAssistant");
  101. if (builderAssistantField != null) {
  102. ReflectionUtils.makeAccessible(builderAssistantField);
  103. MapperBuilderAssistant builderAssistant = (MapperBuilderAssistant) ReflectionUtils.getField(builderAssistantField, o);
  104. String namespace = builderAssistant.getCurrentNamespace();
  105. String msId = builderAssistant.applyCurrentNamespace(id, false);
  106. Field ignoreCacheField = ReflectionUtils.findField(InterceptorIgnoreHelper.class, "IGNORE_STRATEGY_CACHE");
  107. if (ignoreCacheField != null) {
  108. ReflectionUtils.makeAccessible(ignoreCacheField);
  109. Map<String, IgnoreStrategy> cache = (Map<String, IgnoreStrategy>) ignoreCacheField.get(null);
  110. //将自带方法加入排除列表
  111. IgnoreStrategy ignoreStrategy;
  112. if (cache.containsKey(msId)) {
  113. ignoreStrategy = cache.get(msId);
  114. } else {
  115. ignoreStrategy = IgnoreStrategy.builder().build();
  116. if (cache.containsKey(namespace)) {
  117. BeanUtil.copyProperties(cache.get(namespace), ignoreStrategy);
  118. }
  119. cache.put(msId, ignoreStrategy);
  120. }
  121. Map<String, Boolean> others = ignoreStrategy.getOthers();
  122. if (others == null) {
  123. others = new HashMap<>();
  124. ignoreStrategy.setOthers(others);
  125. }
  126. others.putIfAbsent(ignoreLogicPrefix, true);
  127. }
  128. }
  129. }
  130. }
  131. public void handleInject(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  132. String packageName = o.getClass().getPackage().getName();
  133. //生成忽略逻辑删除的MP、MPJ的MP自带方法
  134. if (method.getName().equals("inject") &&
  135. (packageName.startsWith("com.baomidou.mybatisplus.core.injector.methods") || packageName.startsWith("com.github.yulichang.method.mp"))) {
  136. TableInfo tableInfo = (TableInfo) objects[3];
  137. if (tableInfo.isWithLogicDelete()) {
  138. String methodName = (String) ReflectionUtil.getFieldValue(o, "methodName");
  139. try {
  140. ReflectionUtil.setFieldValue(tableInfo, "withLogicDelete", false);
  141. ReflectionUtil.setFieldValue(o, "methodName", methodName + ignoreLogicPrefix);
  142. methodProxy.invokeSuper(o, objects);
  143. IGNOREMETHOD.add(methodName);
  144. } finally {
  145. ReflectionUtil.setFieldValue(o, "methodName", methodName);
  146. ReflectionUtil.setFieldValue(tableInfo, "withLogicDelete", true);
  147. }
  148. }
  149. }
  150. }
  151. }