|
|
|
@@ -1,21 +1,9 @@ |
|
|
|
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; |
|
|
|
@@ -25,14 +13,11 @@ 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.alibaba.druid.wall.violation.ErrorCode; |
|
|
|
import com.iformall.plugin.MyBatisPlus; |
|
|
|
import com.iformall.plugin.shard.annotation.IgnoreSharding; |
|
|
|
import com.iformall.plugin.shard.impl.ShardingRuleExcuter; |
|
|
|
@@ -40,9 +25,10 @@ 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.math.BigDecimal; |
|
|
|
import java.sql.Date; |
|
|
|
import java.sql.Time; |
|
|
|
import java.sql.Timestamp; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Properties; |
|
|
|
@@ -83,21 +69,11 @@ public class ShardingSpherePlugin implements MyBatisPlus { |
|
|
|
this.dialect = this.properties.getProperty("dialect"); |
|
|
|
if (null != this.ShardingSpheres) { |
|
|
|
for (ShardingSphere ss : this.ShardingSpheres) { |
|
|
|
System.out.println(">>>>>"+ss.getTableName()+". sharing:"+ss); |
|
|
|
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 void intercept(Invocation invocation) throws Throwable { |
|
|
|
if (!ShardingTableExcuter.hasShardingConfig()) { |
|
|
|
return ; |
|
|
|
@@ -105,29 +81,21 @@ public class ShardingSpherePlugin implements MyBatisPlus { |
|
|
|
StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); |
|
|
|
MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler); |
|
|
|
|
|
|
|
Object object = null; |
|
|
|
/*分离代理对象链(由于目标类可能被多个拦截器[插件]拦截,从而形成多次代理,通过循环可以分离出最原始的目标类)*/ |
|
|
|
while(metaStatementHandler.hasGetter("h")){ |
|
|
|
object = metaStatementHandler.getValue("h"); |
|
|
|
metaStatementHandler = SystemMetaObject.forObject(object); |
|
|
|
} |
|
|
|
|
|
|
|
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"); |
|
|
|
//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 = getMethodFromAllParent(clazz, methodName); |
|
|
|
//if (method != null) { |
|
|
|
// IgnoreSharding ignore = method.getAnnotation(IgnoreSharding.class); |
|
|
|
// if (null == ignore) { |
|
|
|
Object parameterObject = metaStatementHandler.getValue("delegate.boundSql.parameterObject"); |
|
|
|
BoundSql boundSql = statementHandler.getBoundSql(); |
|
|
|
String newSQL = buildTable(boundSql,parameterObject); |
|
|
|
metaStatementHandler.setValue("delegate.boundSql.sql", newSQL); |
|
|
|
} |
|
|
|
} |
|
|
|
// } |
|
|
|
//} |
|
|
|
} |
|
|
|
|
|
|
|
private String buildTable(BoundSql boundSql,Object parameterObject) throws JSQLParserException { |
|
|
|
@@ -182,7 +150,8 @@ public class ShardingSpherePlugin implements MyBatisPlus { |
|
|
|
return oldSql; |
|
|
|
} |
|
|
|
String newtable = getShareTable(table,parameterObject); |
|
|
|
return oldSql.replaceAll(table+" ", newtable+" ").replaceAll(table+".", newtable+"。").replaceAll(table+")", newtable+")"); |
|
|
|
//此处处理前缀相似的表,如wx_c_user, wx_c_user_basic_info, 直接替换wx_c_user会有问题 |
|
|
|
return oldSql.replaceAll(table+"_", "########").replaceAll(table, newtable).replaceAll("########", table+"_"); |
|
|
|
} |
|
|
|
|
|
|
|
private String buildListTables(List<Table> tables,String oldSql,Object parameterObject) { |
|
|
|
@@ -207,8 +176,46 @@ public class ShardingSpherePlugin implements MyBatisPlus { |
|
|
|
private Object getValue(String column,Object parameterObject) { |
|
|
|
if (parameterObject instanceof Map) { |
|
|
|
return ((Map) parameterObject).get(column); |
|
|
|
}else if (parameterObject instanceof Integer || parameterObject instanceof Long || parameterObject instanceof Short || parameterObject instanceof Float |
|
|
|
|| parameterObject instanceof Double || parameterObject instanceof BigDecimal || parameterObject instanceof Character || parameterObject instanceof String |
|
|
|
|| parameterObject instanceof Byte || parameterObject instanceof Date || parameterObject instanceof Time || parameterObject instanceof Timestamp) { |
|
|
|
return parameterObject; |
|
|
|
//认为是实体 |
|
|
|
}else { |
|
|
|
try { |
|
|
|
String[] field = column.split("_"); |
|
|
|
String fieldName = ""; |
|
|
|
if (null != field && field.length > 0) { |
|
|
|
for (String f : field) { |
|
|
|
fieldName = fieldName + f.substring(0,1).toUpperCase()+f.substring(1); |
|
|
|
} |
|
|
|
}else { |
|
|
|
fieldName = column.substring(0,1).toUpperCase()+column.substring(1); |
|
|
|
} |
|
|
|
|
|
|
|
Method method = getMethodFromAllParent(parameterObject.getClass(),"get"+fieldName); |
|
|
|
Object o = method.invoke(parameterObject); |
|
|
|
return o; |
|
|
|
}catch(Exception e) { |
|
|
|
e.printStackTrace(); |
|
|
|
return parameterObject; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private Method getMethodFromAllParent(Class<?> currentClazz,String methodName) { |
|
|
|
Method method = null; |
|
|
|
for(Class<?> clazz = currentClazz ; clazz != Object.class ; clazz = clazz.getSuperclass()) { |
|
|
|
try { |
|
|
|
method = clazz.getDeclaredMethod(methodName) ; |
|
|
|
} catch (Exception e) { |
|
|
|
//这里甚么都不要做!并且这里的异常必须这样写,不能抛出去。 |
|
|
|
//如果这里的异常打印或者往外抛,则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了 |
|
|
|
} |
|
|
|
} |
|
|
|
return parameterObject; |
|
|
|
if (null == method) { |
|
|
|
throw new RuntimeException(currentClazz+" has no method:"+methodName+"()"); |
|
|
|
} |
|
|
|
return method; |
|
|
|
} |
|
|
|
|
|
|
|
} |