MySchemaInnerInterceptor.java 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package jnpf.database.plugins;
  2. import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
  3. import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
  4. import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
  5. import com.baomidou.mybatisplus.core.toolkit.TableNameParser;
  6. import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
  7. import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
  8. import jnpf.constant.MsgCode;
  9. import jnpf.database.util.DataSourceUtil;
  10. import jnpf.database.util.DynamicDataSourceUtil;
  11. import jnpf.database.util.NotTenantPluginHolder;
  12. import jnpf.exception.DataException;
  13. import jnpf.util.TenantHolder;
  14. import lombok.AllArgsConstructor;
  15. import lombok.Getter;
  16. import lombok.NoArgsConstructor;
  17. import lombok.Setter;
  18. import lombok.extern.slf4j.Slf4j;
  19. import org.apache.ibatis.executor.Executor;
  20. import org.apache.ibatis.executor.statement.StatementHandler;
  21. import org.apache.ibatis.mapping.BoundSql;
  22. import org.apache.ibatis.mapping.MappedStatement;
  23. import org.apache.ibatis.mapping.SqlCommandType;
  24. import org.apache.ibatis.session.ResultHandler;
  25. import org.apache.ibatis.session.RowBounds;
  26. import org.springframework.beans.factory.annotation.Autowired;
  27. import java.sql.Connection;
  28. import java.sql.SQLException;
  29. import java.util.ArrayList;
  30. import java.util.List;
  31. /**
  32. * Schema模式租户插件
  33. * @author JNPF开发平台组
  34. * @user N
  35. * @copyright 引迈信息技术有限公司
  36. * @date 2022/10/14 10:35
  37. */
  38. @Getter
  39. @Setter
  40. @NoArgsConstructor
  41. @AllArgsConstructor
  42. @Slf4j
  43. public class MySchemaInnerInterceptor extends DynamicTableNameInnerInterceptor implements ITenantPlugin {
  44. private Runnable hook;
  45. public void setHook(Runnable hook) {
  46. this.hook = hook;
  47. }
  48. /**
  49. * 表名处理器,是否处理表名的情况都在该处理器中自行判断
  50. */
  51. private TableNameHandler tableNameHandler;
  52. @Autowired
  53. private DataSourceUtil dataSourceUtil;
  54. @Override
  55. public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
  56. if(TenantHolder.getLocalTenantCache() == null){
  57. printNoTenant(v -> log.warn("未设置租户信息, 禁止查询数据库, {}, {}, {}, {}", v.getUserId(), v.getUrl(), v.getToken(), v.getStack()));
  58. //未设置租户信息不允许操作数据库
  59. throw new DataException(MsgCode.LOG113.get());
  60. }
  61. //租户指定数据源不处理
  62. if (!TenantHolder.getLocalTenantCache().isSchema()) {
  63. return;
  64. }
  65. if (NotTenantPluginHolder.isNotSwitch()) {
  66. NotTenantPluginHolder.clearNotSwitchFlag();
  67. return;
  68. }
  69. //非主库不切库
  70. if(!DynamicDataSourceUtil.isPrimaryDataSoure()){
  71. return;
  72. }
  73. //不绑定数据源的接口不切库
  74. /*if(NotTenantPluginHolder.isNotSwitchAlways()){
  75. return;
  76. }*/
  77. PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
  78. if (!InterceptorIgnoreHelper.willIgnoreDynamicTableName(ms.getId())) {
  79. // 非忽略执行
  80. mpBs.sql(this.changeTable(mpBs.sql()));
  81. }
  82. }
  83. @Override
  84. public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
  85. if(TenantHolder.getLocalTenantCache() == null){
  86. printNoTenant(v -> log.warn("未设置租户信息, 禁止查询数据库, {}, {}, {}, {}", v.getUserId(), v.getUrl(), v.getToken(), v.getStack()));
  87. //未设置租户信息不允许操作数据库
  88. throw new DataException(MsgCode.LOG113.get());
  89. }
  90. //租户指定数据源不处理
  91. if (!TenantHolder.getLocalTenantCache().isSchema()) {
  92. return;
  93. }
  94. if (NotTenantPluginHolder.isNotSwitch()) {
  95. NotTenantPluginHolder.clearNotSwitchFlag();
  96. return;
  97. }
  98. //非主库不切库
  99. if(!DynamicDataSourceUtil.isPrimaryDataSoure()){
  100. return;
  101. }
  102. //不绑定数据源的接口不切库
  103. /*if(NotTenantPluginHolder.isNotSwitchAlways()){
  104. return;
  105. }*/
  106. PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
  107. MappedStatement ms = mpSh.mappedStatement();
  108. SqlCommandType sct = ms.getSqlCommandType();
  109. if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
  110. if (!InterceptorIgnoreHelper.willIgnoreDynamicTableName(ms.getId())) {
  111. // 非忽略执行
  112. PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
  113. mpBs.sql(this.changeTable(mpBs.sql()));
  114. /*
  115. //只有修改、新增、删除数据才切库
  116. //先保留代码看后续需求
  117. SQLStatement sqlStatement = SQLParserUtils.createSQLStatementParser(mpBs.sql(), DbTypeUtil.getDb(dataSourceUtil).getDruidDbType()).parseStatement();
  118. if (sqlStatement instanceof SQLSelectStatement
  119. || sqlStatement instanceof SQLUpdateStatement
  120. || sqlStatement instanceof SQLInsertStatement
  121. || sqlStatement instanceof SQLDeleteStatement) {
  122. mpBs.sql(this.changeTable(mpBs.sql()));
  123. }*/
  124. }
  125. }
  126. }
  127. public String changeTable(String sql) {
  128. ExceptionUtils.throwMpe(null == tableNameHandler, "Please implement TableNameHandler processing logic");
  129. TableNameParser parser = new TableNameParser(sql);
  130. List<TableNameParser.SqlToken> names = new ArrayList<>();
  131. parser.accept(names::add);
  132. StringBuilder builder = new StringBuilder();
  133. int last = 0;
  134. for (TableNameParser.SqlToken name : names) {
  135. int start = name.getStart();
  136. if (start != last) {
  137. builder.append(sql, last, start);
  138. builder.append(tableNameHandler.dynamicTableName(sql, name.getValue()));
  139. }
  140. last = name.getEnd();
  141. }
  142. if (last != sql.length()) {
  143. builder.append(sql.substring(last));
  144. }
  145. if (hook != null) {
  146. hook.run();
  147. }
  148. return builder.toString();
  149. }
  150. }