通过手写模拟Mybatis底层源码实现,了解参数解析底层原理,了解执行SQL底层原理,了解Mybatis结果处理底层原理
目录
![](https://img-blog.csdnimg.cn/img_convert/c4417f2c286582020bcfed6641a3e48c.png)
启动
public class MyApplication {
public static void main(String[] args) {
UserMapper mapper = ProxyFactory.getMapper(UserMapper.class);
List<User> list = mapper.getUser("root", "123");
System.out.println(list);
User user = mapper.getUser(2);
System.out.println(user);
}
}
代理工厂类ProxyFactory
package com.example.demo.mybatis;
import com.example.demo.User;
import java.lang.reflect.*;
import java.sql.*;
import java.util.*;
public class ProxyFactory {
static String url="jdbc:mysql://localhost:3306/springcloud?characterEncoding=utf8";
static String username="root";
static String userpwd="123456";
private static Map<Class,TypeHandler> typeHandlerMap=new HashMap<>();
static {
typeHandlerMap.put(String.class,new StringTypeHandler());
typeHandlerMap.put(Integer.class,new IntegerTypeHandler());
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static <T> T getMapper(Class<T> mapper){
Object proxyInstance = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{mapper}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Connection connection = DriverManager.getConnection(url, username, userpwd);
Select annotation = method.getAnnotation(Select.class);
String value = annotation.value();
Map<String,Object> map=new HashMap<>();
//获得方法参数名称存放到map集合中,键为参数名称,值为参数数值
Parameter[] parameters = method.getParameters();
for (int i=0;i<parameters.length;i++) {
String value1 = parameters[i].getAnnotation(Param.class).value();
map.put(value1,args[i]);
map.put(parameters[i].getName(),args[i]);
}
//Mybatis占位符解析器
ParameterMappingTokenHandler parameterMappingTokenHandler=new ParameterMappingTokenHandler();
GenericTokenParser genericTokenParser=new GenericTokenParser("#{","}",parameterMappingTokenHandler);
String parse = genericTokenParser.parse(value);
//执行sql语句
PreparedStatement preparedStatement = connection.prepareStatement(parse);
//获得sql语句{}内的参数名称
List<ParameterMapping> parameterMappingList = parameterMappingTokenHandler.getParameterMappingList();
for (int i=0;i<parameterMappingList.size();i++) {
String property = parameterMappingList.get(i).getProperty();
Object o = map.get(property);
Class<?> type = o.getClass();
//根据参数的不同类型执行不同preparedStatement的set方法
typeHandlerMap.get(type).setParameter(preparedStatement,i+1,o);
}
ResultSet resultSet = preparedStatement.executeQuery();
//获得方法的返回类型,根据是否是泛型进行判断,获得实体类的Class对象
Class resultType=null;
Type genericReturnType = method.getGenericReturnType();
if(genericReturnType instanceof Class){
resultType=(Class)genericReturnType;
}
else if(genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
resultType=(Class) actualTypeArguments[0];
}
//获取数据库字段
ResultSetMetaData metaData = resultSet.getMetaData();
List<String> list=new ArrayList<>();
for(int i=0;i<metaData.getColumnCount();i++){
list.add(metaData.getColumnName(i+1));
}
//将实体类的所有的set方法放到map集合中,键为属性名,值为对应的set方法
Map<String,Method> methodMap=new HashMap<>();
for (Method declaredMethod : resultType.getDeclaredMethods()) {
if(declaredMethod.getName().startsWith("set")){
String substring = declaredMethod.getName().substring(3);
substring=substring.substring(0,1).toLowerCase(Locale.ROOT)+substring.substring(1);
methodMap.put(substring,declaredMethod);
}
}
List<Object> resultlist=new ArrayList<>();
Object result=null;
while (resultSet.next()){
Object instance = resultType.newInstance();//实体类必须有无参构造对象
for(int i=0;i<list.size();i++){
String column = list.get(i);//数据库字段
Method method1 = methodMap.get(column);//获得对应的set方法
Class clazz = method1.getParameterTypes()[0];//获得set方法参数
TypeHandler typeHandler = typeHandlerMap.get(clazz);
method1.invoke(instance,typeHandler.getResult(resultSet,column));
}
resultlist.add(instance);
}
if(method.getReturnType().equals(List.class)){
result=resultlist;
}else {
result=resultlist.get(0);
}
connection.close();
return result;
}
});
return (T) proxyInstance;
};
}
TypeHandler接口
public interface TypeHandler<T> {
void setParameter(PreparedStatement preparedStatement,int i,T t);
T getResult(ResultSet resultSet,String columnName);
}
StringTypeHandler
public class StringTypeHandler implements TypeHandler<String>{
@Override
public void setParameter(PreparedStatement preparedStatement, int i, String s) {
try {
preparedStatement.setString(i,s);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@Override
public String getResult(ResultSet resultSet, String columnName) {
try {
return resultSet.getString(columnName);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
}
注:源码下载链接在我的文件资源:https://download.csdn.net/download/qq_43649937/87513406