Commit 52f6fe8d authored by liaozan's avatar liaozan 🏀

Update baseDao methodHandle usage

parent ba8388bb
package com.schbrain.framework.dao.mybatis; package com.schbrain.framework.dao.mybatis;
import com.schbrain.common.exception.BaseException;
import com.schbrain.framework.dao.BaseDao; import com.schbrain.framework.dao.BaseDao;
import com.schbrain.framework.dao.mybatis.mapper.BaseMapper; import com.schbrain.framework.dao.mybatis.mapper.BaseMapper;
import org.apache.ibatis.reflection.ExceptionUtil; import org.apache.ibatis.reflection.ExceptionUtil;
import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.SqlSessionTemplate;
import java.io.Serializable; import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* description * @author liwu
* * @since 2019/7/29
* @author liwu on 2019/7/29
*/ */
public class BaseMethodInvocationHandler<T> implements InvocationHandler, Serializable { public class BaseDaoInvocationHandler<T> implements InvocationHandler {
private static final long serialVersionUID = -5077848994288044943L; private final Map<Method, MethodHandle> methodHandleCache = new ConcurrentHashMap<>();
private final T originMapperProxy; private final T originMapperProxy;
private final BaseMapper baseMapper; private final BaseMapper baseMapper;
private final Lookup mapperInterfaceLookup;
public BaseMethodInvocationHandler(T originMapperProxy, SqlSessionTemplate sqlSession, Class<T> mapperInterface) { public BaseDaoInvocationHandler(T originMapperProxy, SqlSessionTemplate sqlSession, Class<T> mapperInterface) throws IllegalAccessException {
this.originMapperProxy = originMapperProxy; this.originMapperProxy = originMapperProxy;
baseMapper = new BaseMapper(sqlSession, mapperInterface); this.baseMapper = new BaseMapper(sqlSession, mapperInterface);
this.mapperInterfaceLookup = MethodHandles.privateLookupIn(mapperInterface, MethodHandles.lookup());
} }
@Override @Override
...@@ -39,21 +42,27 @@ public class BaseMethodInvocationHandler<T> implements InvocationHandler, Serial ...@@ -39,21 +42,27 @@ public class BaseMethodInvocationHandler<T> implements InvocationHandler, Serial
} else if (isBaseMethod(method)) { } else if (isBaseMethod(method)) {
return invokeBaseMethod(method, args); return invokeBaseMethod(method, args);
} }
} catch (Throwable t) { } catch (Throwable throwable) {
throw ExceptionUtil.unwrapThrowable(t); throw ExceptionUtil.unwrapThrowable(throwable);
} }
return method.invoke(originMapperProxy, args); return method.invoke(originMapperProxy, args);
} }
private Object invokeDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable { private Object invokeDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable {
final Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class, int.class); MethodHandle methodHandle = getMethodHandle(proxy, method);
if (!constructor.isAccessible()) { return methodHandle.invokeWithArguments(args);
constructor.setAccessible(true); }
private MethodHandle getMethodHandle(Object proxy, Method method) {
return methodHandleCache.computeIfAbsent(method, key -> bindHandle(proxy, method));
}
private MethodHandle bindHandle(Object proxy, Method method) {
try {
return mapperInterfaceLookup.unreflectSpecial(method, method.getDeclaringClass()).bindTo(proxy);
} catch (IllegalAccessException e) {
throw new BaseException(e.getMessage(), e);
} }
final Class<?> declaringClass = method.getDeclaringClass();
return constructor
.newInstance(declaringClass, Lookup.PRIVATE | Lookup.PROTECTED | Lookup.PACKAGE | Lookup.PUBLIC)
.unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args);
} }
private boolean isBaseMethod(Method method) { private boolean isBaseMethod(Method method) {
......
package com.schbrain.framework.dao.mybatis; package com.schbrain.framework.dao.mybatis;
import cn.hutool.aop.ProxyUtil;
import com.github.pagehelper.PageInterceptor; import com.github.pagehelper.PageInterceptor;
import com.schbrain.framework.dao.BaseDao; import com.schbrain.framework.dao.BaseDao;
import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Interceptor;
...@@ -7,7 +8,6 @@ import org.apache.ibatis.session.Configuration; ...@@ -7,7 +8,6 @@ import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.mapper.MapperFactoryBean; import org.mybatis.spring.mapper.MapperFactoryBean;
import java.lang.reflect.Proxy;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
...@@ -18,16 +18,11 @@ import java.util.Properties; ...@@ -18,16 +18,11 @@ import java.util.Properties;
*/ */
public class CustomizeMapperFactoryBean<T> extends MapperFactoryBean<T> { public class CustomizeMapperFactoryBean<T> extends MapperFactoryBean<T> {
public CustomizeMapperFactoryBean() {
super();
}
public CustomizeMapperFactoryBean(Class<T> mapperInterface) { public CustomizeMapperFactoryBean(Class<T> mapperInterface) {
super(mapperInterface); super(mapperInterface);
} }
@Override @Override
@SuppressWarnings("unchecked")
public T getObject() throws Exception { public T getObject() throws Exception {
T originMapperProxy = super.getObject(); T originMapperProxy = super.getObject();
Class<T> mapperInterface = getMapperInterface(); Class<T> mapperInterface = getMapperInterface();
...@@ -38,15 +33,15 @@ public class CustomizeMapperFactoryBean<T> extends MapperFactoryBean<T> { ...@@ -38,15 +33,15 @@ public class CustomizeMapperFactoryBean<T> extends MapperFactoryBean<T> {
SqlSessionTemplate sqlSession = getSqlSessionTemplate(); SqlSessionTemplate sqlSession = getSqlSessionTemplate();
Configuration configuration = sqlSession.getConfiguration(); Configuration configuration = sqlSession.getConfiguration();
List<Interceptor> interceptorList = configuration.getInterceptors(); List<Interceptor> interceptorList = configuration.getInterceptors();
boolean hasPageInterceptor = interceptorList.stream().anyMatch(e -> PageInterceptor.class.isAssignableFrom(e.getClass())); boolean hasPageInterceptor = interceptorList.stream().anyMatch(PageInterceptor.class::isInstance);
if (!hasPageInterceptor) { if (!hasPageInterceptor) {
PageInterceptor pageInterceptor = new PageInterceptor(); PageInterceptor pageInterceptor = new PageInterceptor();
pageInterceptor.setProperties(new Properties()); pageInterceptor.setProperties(new Properties());
configuration.addInterceptor(pageInterceptor); configuration.addInterceptor(pageInterceptor);
} }
// 创建代理 // 创建代理
BaseMethodInvocationHandler<T> handler = new BaseMethodInvocationHandler<>(originMapperProxy, sqlSession, mapperInterface); BaseDaoInvocationHandler<T> handler = new BaseDaoInvocationHandler<>(originMapperProxy, sqlSession, mapperInterface);
return (T) Proxy.newProxyInstance(getMapperInterface().getClassLoader(), new Class[]{mapperInterface}, handler); return ProxyUtil.newProxyInstance(mapperInterface.getClassLoader(), handler, mapperInterface);
} }
} }
package com.schbrain.framework.dao.mybatis.mapper; package com.schbrain.framework.dao.mybatis.mapper;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
import com.google.common.base.Converter; import com.google.common.base.Converter;
...@@ -7,6 +8,7 @@ import com.schbrain.framework.dao.mybatis.mapper.sqlsource.*; ...@@ -7,6 +8,7 @@ import com.schbrain.framework.dao.mybatis.mapper.sqlsource.*;
import org.apache.ibatis.builder.StaticSqlSource; import org.apache.ibatis.builder.StaticSqlSource;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator; import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.mapping.*; import org.apache.ibatis.mapping.*;
import org.apache.ibatis.mapping.MappedStatement.Builder;
import org.apache.ibatis.scripting.LanguageDriver; import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.Configuration;
...@@ -21,30 +23,22 @@ import java.util.*; ...@@ -21,30 +23,22 @@ import java.util.*;
*/ */
public class BaseMapperStatement { public class BaseMapperStatement {
private static final Converter<String, String> CONVERTER = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.LOWER_UNDERSCORE);
private static final String GMT_UPDATE_FIELD = "gmtUpdate"; private static final String GMT_UPDATE_FIELD = "gmtUpdate";
private static final String GMT_CREATE_FIELD = "gmtCreate"; private static final String GMT_CREATE_FIELD = "gmtCreate";
private final Configuration configuration; private final Map<String, String> fieldColumnMap = new LinkedHashMap<>();
private final List<ResultMap> objectResultMapList = new ArrayList<>(1);
private final List<ResultMap> intResultMapList = new ArrayList<>(1);
private final Configuration configuration;
private final Class<?> mapperInterface; private final Class<?> mapperInterface;
private final LanguageDriver languageDriver; private final LanguageDriver languageDriver;
private final Map<String, String> fieldColumnMap = new LinkedHashMap<>();
private final String tableName; private final String tableName;
private final Class<?> domainClass; private final Class<?> domainClass;
private final Field[] fields; private final Field[] fields;
private final List<ResultMap> objectResultMapList = new ArrayList<>(1);
private final List<ResultMap> intResultMapList = new ArrayList<>(1);
private String selectClause; private String selectClause;
private String insertClause; private String insertClause;
public BaseMapperStatement(Configuration configuration, Class<?> mapperInterface, Class<?> domainClass, String tableName, Field[] fields) { public BaseMapperStatement(Configuration configuration, Class<?> mapperInterface, Class<?> domainClass, String tableName, Field[] fields) {
...@@ -74,8 +68,7 @@ public class BaseMapperStatement { ...@@ -74,8 +68,7 @@ public class BaseMapperStatement {
} }
public String getAddMSId() { public String getAddMSId() {
String methodName = "add"; return mapperInterface.getName() + ".add";
return mapperInterface.getName() + "." + methodName;
} }
public String getAddListMSId(String... fields) { public String getAddListMSId(String... fields) {
...@@ -88,72 +81,58 @@ public class BaseMapperStatement { ...@@ -88,72 +81,58 @@ public class BaseMapperStatement {
} }
public String getGetByIdMSId() { public String getGetByIdMSId() {
String methodName = "getById"; return mapperInterface.getName() + ".getById";
return mapperInterface.getName() + "." + methodName;
} }
public String getListByIdListMSId() { public String getListByIdListMSId() {
String methodName = "getByIdList"; return mapperInterface.getName() + ".getByIdList";
return mapperInterface.getName() + "." + methodName;
} }
public String getListByConditionMSId() { public String getListByConditionMSId() {
String methodName = "listByCondition"; return mapperInterface.getName() + ".listByCondition";
return mapperInterface.getName() + "." + methodName;
} }
public String getListByObjectMSId() { public String getListByObjectMSId() {
String methodName = "listByObject"; return mapperInterface.getName() + ".listByObject";
return mapperInterface.getName() + "." + methodName;
} }
public String getGetOneByObjectMSId() { public String getGetOneByObjectMSId() {
String methodName = "getOneByObject"; return mapperInterface.getName() + ".getOneByObject";
return mapperInterface.getName() + "." + methodName;
} }
public String getCountByConditionMSId() { public String getCountByConditionMSId() {
String methodName = "getCountByCondition"; return mapperInterface.getName() + ".getCountByCondition";
return mapperInterface.getName() + "." + methodName;
} }
public String getDeleteByIdMSId() { public String getDeleteByIdMSId() {
String methodName = "deleteById"; return mapperInterface.getName() + ".deleteById";
return mapperInterface.getName() + "." + methodName;
} }
public String getDeleteByIdListMSId() { public String getDeleteByIdListMSId() {
String methodName = "deleteByIdList"; return mapperInterface.getName() + ".deleteByIdList";
return mapperInterface.getName() + "." + methodName;
} }
public String getDeleteByConditionMSId() { public String getDeleteByConditionMSId() {
String methodName = "deleteByCondition"; return mapperInterface.getName() + ".deleteByCondition";
return mapperInterface.getName() + "." + methodName;
} }
public String getUpdateByIdMSId() { public String getUpdateByIdMSId() {
String methodName = "updateById"; return mapperInterface.getName() + ".updateById";
return mapperInterface.getName() + "." + methodName;
} }
public String getUpdateByIdWithNullMSId() { public String getUpdateByIdWithNullMSId() {
String methodName = "updateByIdWithNull"; return mapperInterface.getName() + ".updateByIdWithNull";
return mapperInterface.getName() + "." + methodName;
} }
public String getUpdateByConditionMSId() { public String getUpdateByConditionMSId() {
String methodName = "updateByCondition"; return mapperInterface.getName() + ".updateByCondition";
return mapperInterface.getName() + "." + methodName;
} }
public String getUpdateByCompleteSqlMSId() { public String getUpdateByCompleteSqlMSId() {
String methodName = "updateByCompleteSql"; return mapperInterface.getName() + ".updateByCompleteSql";
return mapperInterface.getName() + "." + methodName;
} }
private void setClause() { private void setClause() {
Converter<String, String> converter = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.LOWER_UNDERSCORE);
StringBuilder selectClause = new StringBuilder("select "); StringBuilder selectClause = new StringBuilder("select ");
StringBuilder insertClause = new StringBuilder("insert into "); StringBuilder insertClause = new StringBuilder("insert into ");
insertClause.append(tableName).append("("); insertClause.append(tableName).append("(");
...@@ -162,7 +141,7 @@ public class BaseMapperStatement { ...@@ -162,7 +141,7 @@ public class BaseMapperStatement {
continue; continue;
} }
String fieldName = field.getName(); String fieldName = field.getName();
String columnName = converter.convert(fieldName); String columnName = CONVERTER.convert(fieldName);
fieldColumnMap.put(fieldName, columnName); fieldColumnMap.put(fieldName, columnName);
selectClause.append(" ").append(columnName).append(","); selectClause.append(" ").append(columnName).append(",");
insertClause.append(" ").append(columnName).append(","); insertClause.append(" ").append(columnName).append(",");
...@@ -218,7 +197,7 @@ public class BaseMapperStatement { ...@@ -218,7 +197,7 @@ public class BaseMapperStatement {
private String getInsertListScript(String... fields) { private String getInsertListScript(String... fields) {
String tmpInsertClause; String tmpInsertClause;
Set<String> fieldSet; Set<String> fieldSet;
if (null == fields || 0 == fields.length) { if (ArrayUtil.isEmpty(fields)) {
tmpInsertClause = insertClause; tmpInsertClause = insertClause;
fieldSet = fieldColumnMap.keySet(); fieldSet = fieldColumnMap.keySet();
} else { } else {
...@@ -277,9 +256,7 @@ public class BaseMapperStatement { ...@@ -277,9 +256,7 @@ public class BaseMapperStatement {
///////////////////listByIdList ///////////////////listByIdList
private void addListByIdListMS() { private void addListByIdListMS() {
String sql = "<script>" + selectClause String sql = "<script>" + selectClause + " where id in <foreach open='(' close=')' collection='list' item='id' separator=','>#{id}</foreach></script>";
+ " where id in <foreach close=')' collection='list' item='id' open='(' separator=','>"
+ "#{id}</foreach></script>";
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, List.class); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, List.class);
addSelectMappedStatement(getListByIdListMSId(), sqlSource); addSelectMappedStatement(getListByIdListMSId(), sqlSource);
} }
...@@ -330,9 +307,7 @@ public class BaseMapperStatement { ...@@ -330,9 +307,7 @@ public class BaseMapperStatement {
///////////////////deleteByIdList ///////////////////deleteByIdList
private void addDeleteByIdListMS() { private void addDeleteByIdListMS() {
String sql = "<script>delete from " + tableName String sql = "<script>delete from " + tableName + " where id in <foreach open='(' close=')' collection='list' item='id' separator=','>#{id}</foreach></script>";
+ " where id in <foreach close=')' collection='list' item='id' open='(' separator=','>"
+ "#{id}</foreach></script>";
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, List.class); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, List.class);
addUpdateMappedStatement(getDeleteByIdListMSId(), sqlSource, SqlCommandType.DELETE); addUpdateMappedStatement(getDeleteByIdListMSId(), sqlSource, SqlCommandType.DELETE);
} }
...@@ -408,8 +383,7 @@ public class BaseMapperStatement { ...@@ -408,8 +383,7 @@ public class BaseMapperStatement {
if (configuration.hasStatement(msId)) { if (configuration.hasStatement(msId)) {
return; return;
} }
MappedStatement ms = new MappedStatement.Builder(configuration, msId, sqlSource, SqlCommandType.SELECT) MappedStatement ms = new Builder(configuration, msId, sqlSource, SqlCommandType.SELECT).resultMaps(objectResultMapList).flushCacheRequired(true).build();
.resultMaps(objectResultMapList).flushCacheRequired(true).build();
configuration.addMappedStatement(ms); configuration.addMappedStatement(ms);
} }
...@@ -417,8 +391,7 @@ public class BaseMapperStatement { ...@@ -417,8 +391,7 @@ public class BaseMapperStatement {
if (configuration.hasStatement(msId)) { if (configuration.hasStatement(msId)) {
return; return;
} }
MappedStatement ms = new MappedStatement.Builder(configuration, msId, sqlSource, SqlCommandType.SELECT) MappedStatement ms = new Builder(configuration, msId, sqlSource, SqlCommandType.SELECT).resultMaps(intResultMapList).build();
.resultMaps(intResultMapList).build();
configuration.addMappedStatement(ms); configuration.addMappedStatement(ms);
} }
...@@ -428,12 +401,9 @@ public class BaseMapperStatement { ...@@ -428,12 +401,9 @@ public class BaseMapperStatement {
} }
MappedStatement ms; MappedStatement ms;
if (SqlCommandType.INSERT == sqlCommandType) { if (SqlCommandType.INSERT == sqlCommandType) {
ms = new MappedStatement.Builder(configuration, msId, sqlSource, sqlCommandType) ms = new Builder(configuration, msId, sqlSource, sqlCommandType).resultMaps(intResultMapList).keyGenerator(Jdbc3KeyGenerator.INSTANCE).keyColumn("id").keyProperty("id").build();
.resultMaps(intResultMapList).keyGenerator(Jdbc3KeyGenerator.INSTANCE)
.keyColumn("id").keyProperty("id").build();
} else { } else {
ms = new MappedStatement.Builder(configuration, msId, sqlSource, sqlCommandType) ms = new Builder(configuration, msId, sqlSource, sqlCommandType).resultMaps(intResultMapList).build();
.resultMaps(intResultMapList).build();
} }
configuration.addMappedStatement(ms); configuration.addMappedStatement(ms);
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment