com.github.chengyuxing.sql.XQLInvocationHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rabbit-sql Show documentation
Show all versions of rabbit-sql Show documentation
Light wrapper of JDBC, support ddl, dml, query, plsql/procedure/function, transaction and manage sql
file.
package com.github.chengyuxing.sql;
import com.github.chengyuxing.common.DataRow;
import com.github.chengyuxing.common.utils.ObjectUtil;
import com.github.chengyuxing.common.utils.ReflectUtil;
import com.github.chengyuxing.sql.annotation.*;
import com.github.chengyuxing.sql.page.IPageable;
import com.github.chengyuxing.sql.support.SqlInvokeHandler;
import com.github.chengyuxing.sql.support.executor.QueryExecutor;
import com.github.chengyuxing.sql.support.executor.SaveExecutor;
import com.github.chengyuxing.sql.types.Param;
import com.github.chengyuxing.sql.annotation.Type;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@SuppressWarnings("SqlSourceToSinkFlow")
public abstract class XQLInvocationHandler implements InvocationHandler {
// language=Regexp
public static final String QUERY_PATTERN = "^(?:select|query|find|get|fetch|search)[^a-z]\\w*";
// language=Regexp
public static final String INSERT_PATTERN = "^(?:insert|save|add|append)[^a-z]\\w*";
// language=Regexp
public static final String UPDATE_PATTERN = "^(?:update|modify|change)[^a-z]\\w*";
// language=Regexp
public static final String DELETE_PATTERN = "^(?:delete|remove)[^a-z]\\w*";
// language=Regexp
public static final String CALL_PATTERN = "^(?:call|proc|func)[^a-z]\\w*";
private final ClassLoader classLoader = this.getClass().getClassLoader();
protected abstract BakiDao baki();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Class> clazz = method.getDeclaringClass();
Class> returnType = method.getReturnType();
Class> returnGenericType = getReturnGenericType(method);
Object myArgs = resolveArgs(method, args);
if (method.isAnnotationPresent(Insert.class) ||
method.isAnnotationPresent(Update.class) ||
method.isAnnotationPresent(Delete.class)) {
return handleNotXqlMappingMethod(myArgs, method, returnType);
}
if (method.isAnnotationPresent(Procedure.class)) {
Procedure procedure = method.getDeclaredAnnotation(Procedure.class);
return handleProcedure(procedure.value(), myArgs, method, returnType);
}
if (method.isAnnotationPresent(com.github.chengyuxing.sql.annotation.Function.class)) {
com.github.chengyuxing.sql.annotation.Function function = method.getDeclaredAnnotation(com.github.chengyuxing.sql.annotation.Function.class);
return handleProcedure(function.value(), myArgs, method, returnType);
}
String alias = clazz.getDeclaredAnnotation(XQLMapper.class).value();
String sqlName = method.getName();
Type sqlType = detectSQLTypeByMethodPrefix(sqlName);
if (method.isAnnotationPresent(XQL.class)) {
XQL xql = method.getDeclaredAnnotation(XQL.class);
if (!xql.value().trim().isEmpty()) {
sqlName = xql.value();
}
sqlType = xql.type();
}
XQLFileManager.Resource xqlResource = baki().getXqlFileManager().getResource(alias);
if (xqlResource == null) {
throw new IllegalAccessException("XQL file alias '" + alias + "' not found at: " + clazz.getName());
}
if (!xqlResource.getEntry().containsKey(sqlName)) {
throw new IllegalAccessException("SQL name [" + sqlName + "] not found at: " + clazz.getName() + "#" + method.getName());
}
String sqlRef = "&" + alias + "." + sqlName;
if (handlers().containsKey(sqlType)) {
SqlInvokeHandler handler = handlers().get(sqlType);
return handler.handle(baki(), sqlRef, myArgs, method, returnType, returnGenericType);
}
switch (sqlType) {
case query:
return handleQuery(alias, sqlName, myArgs, method, returnType, returnGenericType);
case insert:
case update:
case delete:
return handleModify(sqlRef, myArgs, method, returnType);
case procedure:
case function:
return handleProcedure(sqlRef, myArgs, method, returnType);
case ddl:
case plsql:
case unset:
return handleNormal(sqlRef, myArgs, method, returnType);
default:
throw new IllegalAccessException("SQL type [" + sqlType + "] not supported");
}
}
protected Map handlers() {
return baki().getXqlMappingHandlers();
}
protected Type detectSQLTypeByMethodPrefix(String method) {
if (method.matches(QUERY_PATTERN)) {
return Type.query;
}
if (method.matches(INSERT_PATTERN)) {
return Type.insert;
}
if (method.matches(UPDATE_PATTERN)) {
return Type.update;
}
if (method.matches(DELETE_PATTERN)) {
return Type.delete;
}
if (method.matches(CALL_PATTERN)) {
return Type.procedure;
}
return Type.unset;
}
@SuppressWarnings("unchecked")
protected Object handleNotXqlMappingMethod(Object myArgs, Method method, Class> returnType) {
if (returnType != Integer.class && returnType != int.class) {
throw new IllegalStateException(method.getName() + " return type must be Integer or int");
}
if (method.isAnnotationPresent(Insert.class)) {
Insert insert = method.getDeclaredAnnotation(Insert.class);
SaveExecutor