MyDefaultMasterSlaveAutoRoutingPlugin.java 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. package jnpf.database.plugins;
  2. import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
  3. import com.baomidou.dynamic.datasource.enums.DdConstants;
  4. import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
  5. import com.baomidou.dynamic.datasource.tx.TransactionContext;
  6. import jnpf.database.util.DynamicDataSourceUtil;
  7. import jnpf.util.TenantHolder;
  8. import lombok.extern.slf4j.Slf4j;
  9. import org.apache.ibatis.cache.CacheKey;
  10. import org.apache.ibatis.executor.Executor;
  11. import org.apache.ibatis.mapping.BoundSql;
  12. import org.apache.ibatis.mapping.MappedStatement;
  13. import org.apache.ibatis.mapping.SqlCommandType;
  14. import org.apache.ibatis.plugin.Interceptor;
  15. import org.apache.ibatis.plugin.Intercepts;
  16. import org.apache.ibatis.plugin.Invocation;
  17. import org.apache.ibatis.plugin.Signature;
  18. import org.apache.ibatis.session.ResultHandler;
  19. import org.apache.ibatis.session.RowBounds;
  20. import org.springframework.transaction.support.TransactionSynchronizationManager;
  21. import org.springframework.util.StringUtils;
  22. import javax.sql.DataSource;
  23. /**
  24. * 主库读写分离
  25. */
  26. @Intercepts({
  27. @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
  28. @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
  29. @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
  30. @Slf4j
  31. public class MyDefaultMasterSlaveAutoRoutingPlugin implements Interceptor {
  32. protected DynamicRoutingDataSource dynamicDataSource;
  33. public MyDefaultMasterSlaveAutoRoutingPlugin(DataSource dataSource){
  34. this.dynamicDataSource = (DynamicRoutingDataSource) dataSource;
  35. }
  36. @Override
  37. public Object intercept(Invocation invocation) throws Throwable {
  38. // 连接隔离模式多租户不处理, 当前非主数据源不处理, 未添加从库不处理
  39. if (TenantHolder.isRemote()
  40. || !DynamicDataSourceUtil.isPrimaryDataSoure()
  41. || !dynamicDataSource.getGroupDataSources().containsKey(DdConstants.SLAVE)) {
  42. return invocation.proceed();
  43. }
  44. Object[] args = invocation.getArgs();
  45. MappedStatement ms = (MappedStatement) args[0];
  46. String pushedDataSource = null;
  47. try {
  48. // 存在事务只使用主库
  49. boolean hasTrans = TransactionSynchronizationManager.isActualTransactionActive();
  50. if (!hasTrans) {
  51. hasTrans = StringUtils.hasText(TransactionContext.getXID());
  52. }
  53. String dataSource = !hasTrans && SqlCommandType.SELECT == ms.getSqlCommandType() ? DdConstants.SLAVE : DynamicDataSourceUtil.dynamicDataSourceProperties.getPrimary();
  54. pushedDataSource = DynamicDataSourceContextHolder.push(dataSource);
  55. return invocation.proceed();
  56. } finally {
  57. if (pushedDataSource != null) {
  58. DynamicDataSourceContextHolder.poll();
  59. }
  60. }
  61. }
  62. }