Преглед изворни кода

增加分表处理

release_toaliyun_real
xiaohanzi пре 5 година
родитељ
комит
046c2f4687
8 измењених фајлова са 393 додато и 0 уклоњено
  1. +16
    -0
      mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/annotation/IgnoreSharding.java
  2. +27
    -0
      mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/EnumShardingRule.java
  3. +29
    -0
      mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/ShardingRuleExcuter.java
  4. +38
    -0
      mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/ShardingSphere.java
  5. +33
    -0
      mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/ShardingTableExcuter.java
  6. +17
    -0
      mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/rule/ShardingRuleDefaultService.java
  7. +6
    -0
      mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/rule/ShardingRuleService.java
  8. +227
    -0
      mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/plugin/ShardingSpherePlugin.java

+ 16
- 0
mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/annotation/IgnoreSharding.java Прегледај датотеку

@@ -0,0 +1,16 @@
package com.iformall.plugin.shard.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* 在mapper方法上面用
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface IgnoreSharding {
}

+ 27
- 0
mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/EnumShardingRule.java Прегледај датотеку

@@ -0,0 +1,27 @@
package com.iformall.plugin.shard.impl;

public enum EnumShardingRule {

HASH(1,"哈希值分表");

private Integer code;
private String name;
private EnumShardingRule(Integer code, String name) {
this.code = code;
this.name = name;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

+ 29
- 0
mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/ShardingRuleExcuter.java Прегледај датотеку

@@ -0,0 +1,29 @@
package com.iformall.plugin.shard.impl;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.alibaba.druid.util.StringUtils;
import com.iformall.plugin.shard.impl.rule.ShardingRuleDefaultService;
import com.iformall.plugin.shard.impl.rule.ShardingRuleService;

public class ShardingRuleExcuter {

private static Map<Integer,ShardingRuleService> serviceMap = null;
private static Map<Integer,ShardingRuleService> getServiceMap() {
if (null == serviceMap) {
serviceMap = new ConcurrentHashMap<Integer, ShardingRuleService>();
serviceMap.put(EnumShardingRule.HASH.getCode(), new ShardingRuleDefaultService());
}
return serviceMap;
}
public static String getTableIndex(Integer rule,Object value,int tableCount) {
String index = getServiceMap().get(rule).getTableIndex(value, tableCount);
if (StringUtils.isEmpty(index)) {
throw new RuntimeException("Sharding Rule["+rule+"] not support.");
}
return index;
}
}

+ 38
- 0
mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/ShardingSphere.java Прегледај датотеку

@@ -0,0 +1,38 @@
package com.iformall.plugin.shard.impl;

public class ShardingSphere {

public static final String TABLE_SUFFIX = "_";
/*表名,不用带下划线**/
private String tableName;
/*分表列名**/
private String column;
/*分表规则**/
private Integer rule;
/*表数量**/
private Integer count;
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getColumn() {
return column;
}
public void setColumn(String column) {
this.column = column;
}
public Integer getRule() {
return rule;
}
public void setRule(Integer rule) {
this.rule = rule;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}

+ 33
- 0
mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/ShardingTableExcuter.java Прегледај датотеку

@@ -0,0 +1,33 @@
package com.iformall.plugin.shard.impl;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ShardingTableExcuter {

private static Map<String,ShardingSphere> tableMap = new ConcurrentHashMap<String, ShardingSphere>();
public static Map<String,ShardingSphere> setTableSharding(String table ,ShardingSphere ss) {
tableMap.put(table, ss);
return tableMap;
}
public static ShardingSphere getShardingSphere(String table) {
return tableMap.get(table);
}
public static boolean isShardingTable(String table) {
ShardingSphere ss = getShardingSphere(table);
if (null == ss) {
return false;
}
return true;
}
public static boolean hasShardingConfig() {
if (null == tableMap || tableMap.size() <= 0) {
return false;
}
return true;
}
}

+ 17
- 0
mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/rule/ShardingRuleDefaultService.java Прегледај датотеку

@@ -0,0 +1,17 @@
package com.iformall.plugin.shard.impl.rule;

public class ShardingRuleDefaultService implements ShardingRuleService {

@Override
public String getTableIndex(Object value, int count) {
if (null == value || count <= 0 ) {
return null;
}
int hash = value.hashCode();
if (hash < 0 ) {
hash = Math.abs(hash);
}
return String.valueOf(hash%count);
}

}

+ 6
- 0
mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/impl/rule/ShardingRuleService.java Прегледај датотеку

@@ -0,0 +1,6 @@
package com.iformall.plugin.shard.impl.rule;

public interface ShardingRuleService {

public String getTableIndex(Object value,int count);
}

+ 227
- 0
mybatis-multi-tenancy/src/main/java/com/iformall/plugin/shard/plugin/ShardingSpherePlugin.java Прегледај датотеку

@@ -0,0 +1,227 @@
package com.iformall.plugin.shard.plugin;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.create.table.ColDataType;
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.*;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.util.TablesNamesFinder;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;

import com.iformall.plugin.shard.annotation.IgnoreSharding;
import com.iformall.plugin.shard.impl.ShardingRuleExcuter;
import com.iformall.plugin.shard.impl.ShardingSphere;
import com.iformall.plugin.shard.impl.ShardingTableExcuter;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
*分表
*/
@Intercepts({
//@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
//@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
@Signature( method = "prepare", type = StatementHandler.class,args = {Connection.class, Integer.class}),
@Signature(method = "query", type = StatementHandler.class, args = {java.sql.Statement.class, ResultHandler.class})
})
public class ShardingSpherePlugin implements Interceptor {


public ShardingSpherePlugin(){
}

//属性参数信息
private Properties properties;
private String dialect = "mysql";
private List<ShardingSphere> ShardingSpheres;
public String getDialect() {
return dialect;
}
public void setDialect(String dialect) {
this.dialect = dialect;
}
public List<ShardingSphere> getShardingSpheres() {
return ShardingSpheres;
}
public void setShardingSpheres(List<ShardingSphere> shardingSpheres) {
ShardingSpheres = shardingSpheres;
}

/**
* 生成代理对象
*
* @param target
* @return
*/
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
/**
* 获取配置信息
* {dialect=mysql, tenantInfo=org.xue.test.TenantInfoImpl, tenantIdColumn=tenant_id, parentTenantIdColumn=parent_tenant_id}
* @param properties
*/
@Override
public void setProperties(Properties properties) {
this.properties=properties;
this.dialect = this.properties.getProperty("dialect");
if (null != this.ShardingSpheres) {
for (ShardingSphere ss : this.ShardingSpheres) {
ShardingTableExcuter.setTableSharding(ss.getTableName(), ss);
}
}
}
private Method findMethod(Method[] methods, String methodName) {
for (Method method : methods) {
if (method.getName().equals(methodName)) {
return method;
}
}

return null;
}
public Object intercept(Invocation invocation) throws Throwable {
if (!ShardingTableExcuter.hasShardingConfig()) {
return invocation.proceed();
}
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
MappedStatement ms = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
String id = ms.getId();
String className = id.substring(0, id.lastIndexOf("."));
String methodName = id.substring(id.lastIndexOf(".") + 1);
Class<?> clazz = Class.forName(className);
Method method = findMethod(clazz.getDeclaredMethods(), methodName);
if (method != null) {
IgnoreSharding ignore = method.getAnnotation(IgnoreSharding.class);
if (null == ignore) {
//Configuration configuration = (Configuration) metaStatementHandler.getValue("delegate.configuration");
Object parameterObject = metaStatementHandler.getValue("delegate.boundSql.parameterObject");
BoundSql boundSql = statementHandler.getBoundSql();
String newSQL = buildTable(boundSql,parameterObject);
metaStatementHandler.setValue("delegate.boundSql.sql", newSQL);
}
}
return invocation.proceed();
}

private String buildTable(BoundSql boundSql,Object parameterObject) throws JSQLParserException {
String oldSql = boundSql.getSql();
Statement stmt = CCJSqlParserUtil.parse(oldSql);
if (stmt instanceof Insert) {
return buildInsert((Insert) stmt,oldSql,parameterObject);
}

if (stmt instanceof Delete) {
return buildDelete((Delete) stmt,oldSql,parameterObject);
}

if (stmt instanceof Update) {
return buildUpdate((Update) stmt,oldSql,parameterObject);
}

if (stmt instanceof Select) {
return buildSelect((Select) stmt,oldSql,parameterObject);
}

if (stmt instanceof CreateTable) {
return oldSql;
}
throw new RuntimeException("非法sql语句,请检查"+oldSql);
}
private String buildInsert(Insert stmt,String oldSql,Object parameterObject) {
return buildTable(stmt.getTable(), oldSql, parameterObject);
}
private String buildDelete(Delete stmt,String oldSql,Object parameterObject) {
return buildTable(stmt.getTable(), oldSql, parameterObject);
}
private String buildUpdate(Update stmt,String oldSql,Object parameterObject) {
return buildListTables(stmt.getTables(), oldSql, parameterObject);
}
private String buildSelect(Select stmt,String oldSql,Object parameterObject) {
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
List<String> tableList = tablesNamesFinder.getTableList(stmt);
return buildByListTableNames(tableList, oldSql, parameterObject);
}
private String buildByTableName(String table,String oldSql,Object parameterObject) {
if (!ShardingTableExcuter.isShardingTable(table)) {
return oldSql;
}
String newtable = getShareTable(table,parameterObject);
return oldSql.replaceAll(table, newtable);
}
private String buildTable(Table table,String oldSql,Object parameterObject) {
return buildByTableName(table.getName(), oldSql, parameterObject);
}
private String buildListTables(List<Table> tables,String oldSql,Object parameterObject) {
for (Table t : tables) {
oldSql = buildTable(t,oldSql,parameterObject);
}
return oldSql;
}
private String buildByListTableNames(List<String> tables,String oldSql,Object parameterObject) {
for (String t : tables) {
oldSql = buildByTableName(t,oldSql,parameterObject);
}
return oldSql;
}
private String getShareTable(String table,Object parameterObject) {
ShardingSphere ss = ShardingTableExcuter.getShardingSphere(table);
return ss.getTableName()+ShardingSphere.TABLE_SUFFIX+ShardingRuleExcuter.getTableIndex(ss.getRule(), getValue(ss.getColumn(),parameterObject), ss.getCount());
}
private Object getValue(String column,Object parameterObject) {
if (parameterObject instanceof Map) {
return ((Map) parameterObject).get(column);
}
return parameterObject;
}
}

Loading…
Откажи
Сачувај