Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
sf.database.mapper.handle.MethodHandleSQL Maven / Gradle / Ivy
package sf.database.mapper.handle;
import sf.common.wrapper.Page;
import sf.database.dao.DBClient;
import sf.database.mapper.MapperInvoke;
import sf.database.mapper.annotation.ExecuteSQL;
import sf.database.mapper.annotation.SelectKey;
import sf.database.support.DMLType;
import sf.tools.ArrayUtils;
import sf.tools.JavaTypeUtils;
import sf.tools.StringUtils;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 接口执行SQL
*/
public class MethodHandleSQL implements MapperInvoke {
protected static MethodHandleSQL ms = new MethodHandleSQL();
public static MethodHandleSQL getInstance() {
return ms;
}
private MethodHandleSQL() {
}
@Override
public Object call(DBClient dbClient, Class entityClass, Method m, Object[] params) {
Object ret = null;
ExecuteSQL es = m.getAnnotation(ExecuteSQL.class);
String sql = StringUtils.join(es.value());
DMLType type = es.type();
if (type == DMLType.OTHER) {
type = HandleHelp.getTypeBySql(sql);
}
switch (type) {
case SELECT:
ret = parseSelectList(m, dbClient, sql, params);
break;
case INSERT:
ret = parseInsert(m, dbClient, sql, params, es.batch());
break;
default:
ret = parseUpdate(m, dbClient, sql, params);
break;
}
return ret;
}
protected Object parseInsert(Method method, DBClient dbClient, String sql, Object[] params, boolean batch) {
SelectKey returnKey = method.getAnnotation(SelectKey.class);
List pkeys = Collections.emptyList();
if (returnKey != null && StringUtils.isNotBlank(returnKey.keyColumn())) {
pkeys = Collections.singletonList(returnKey.keyColumn());
}
List> rMap = new LinkedList<>();
List pa = new ArrayList<>();
if (!batch) {
pa.add(params);
} else {
if (params != null && params.length > 0) {
pa.addAll((Collection extends Object[]>) params[0]);
}
}
dbClient.executeBatch(sql, pa, false, 100, pkeys, rMap);
if (!rMap.isEmpty() && returnKey != null) {
Object value = rMap.get(0).values().iterator().next();
if (returnKey.resultType() == Integer.class || returnKey.resultType() == int.class) {
return ((Number) value).intValue();
} else if (returnKey.resultType() == Long.class || returnKey.resultType() == long.class) {
return ((Number) value).longValue();
} else if (returnKey.resultType() == Map.class) {
return rMap.get(0);
}
}
return null;
}
/**
* 根据返回参数int 或者int[] 判断是否是批处理。如果都没有,根据第一参数判断
* @param method
* @param dbClient
* @param sql
* @param params
* @return
*/
protected Object parseUpdate(Method method, DBClient dbClient, String sql, Object[] params) {
Class[] paras = method.getParameterTypes();
Class ret = method.getReturnType();
boolean batch = false;
if (JavaTypeUtils.isInt(ret)) {
batch = false;
} else if (ret.isArray()) {
//如果更新语句返回了int[],
Class type = ret.getComponentType();
if (JavaTypeUtils.isInt(type)) {
batch = true;
}
}
//通过输入参数判断
if (paras.length == 1) {
Class first = paras[0];
if (List.class.isAssignableFrom(first) && this.isUpdateBatchByFirstList(method)) {
batch = true;
} else if (first.isArray()) {
Class ct = first.getComponentType();
if (this.isPojo(ct)) {
batch = true;
}
}
}
if (batch) {
return dbClient.executeBatch(sql, (List) params[0]);
} else {
return dbClient.execute(sql, params);
}
}
private boolean isUpdateBatchByFirstList(Method method) {
Type firstType = method.getGenericParameterTypes()[0];
Class type = HandleHelp.getType(firstType);
if (type == null) {
//不知道List里面是什么,认为是batchUpdate,兼容以前情况
return true;
}
return isPojo(type);
}
private boolean isPojo(Class type) {
if (type.isPrimitive()) {
return false;
}
if (Map.class.isAssignableFrom(type)) {
return true;
}
String pkg = getPackageName(type);
return !pkg.startsWith("java.") && !pkg.startsWith("javax.");
}
public static String getPackageName(Class> clazz) {
return StringUtils.substringBefore(clazz.getName(), ".");
}
protected Object parseSelectList(Method method, DBClient dbClient, String sql, Object[] paras) {
if (paras == null) {
paras = ArrayUtils.EMPTY_OBJECT_ARRAY;
}
Class> returnType = method.getReturnType();
Type retType = method.getGenericReturnType();
Class[] paraClass = method.getParameterTypes();
if (returnType == Page.class) {
Class resultType = HandleHelp.getPageType(retType, Map.class);
RowLimit rl = new RowLimit(0, 10);//默认
List list = new ArrayList<>();
for (int i = 0; i < paraClass.length; i++) {
Class> clz = paraClass[i];
if (clz == RowLimit.class) {
rl = (RowLimit) paras[i];
} else {
list.add(clz);
}
}
return dbClient.selectPage(rl.getOffset(), rl.getLimit(), resultType, sql, list.toArray());
//else否则就默认为mapper类型
}
if (Map.class.isAssignableFrom(returnType)) {
//如果定义返回结果为Map,无论是否泛型,都认为返回一个Map
return dbClient.selectOne(Map.class, sql, paras);
} else if (List.class.isAssignableFrom(returnType)) {
Class type = HandleHelp.getType(retType);
if (type == null) {
type = Map.class;
}
return dbClient.selectList(type, sql, paras);
}
//更改类型为Single
return dbClient.selectOne(returnType, sql, paras);
}
}