mybatis是什么?
1、ORM框架,将字段映射出对象属性,是对JDBC规范的封装实现
我们先来看看假如用JDBC来操作数据库连接的几个步骤:
- 导入JDBC驱动包
- 通过DriverManger注册驱动
- 创建连接
- 创建Statement
- CRUD
- 操作结果集
- 关闭连接
所以能够看出来,用JDBC来操作数据库的话,会有大量的代码,很繁琐,所以mybatis应运而生。
2、mybatis sql解析原理:接口实例化一个bean,通过代理模式,jdk动态代理,拦截方法的执行,执行过程中回调InvocationHandler的invoke方法
通过反射对注解上的sql进行解析
interface DuofenCardNewMapper{
@Select("select * from t_duofen_card_new where id = #{id} and title = #{title}")
List<DuofenCardNew> duofenCardList(Integer id,String title);
}
public class MybatisApplicationTests {
public static void main(String[] args) {
DuofenCardNewMapper duofenCardNewMapper = (DuofenCardNewMapper) Proxy.newProxyInstance(MybatisApplicationTests.class.getClassLoader(),
new Class<?>[]{DuofenCardNewMapper.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//拿到注解
Select annotation = method.getAnnotation(Select.class);
//参数名对应的参数值map
Map<String,Object> nameArgsMap = buildMethodNameArgsMap(method,args);
System.out.println(nameArgsMap);
if(annotation != null){
//注解上的value值
String[] values = annotation.value();
//解析sql
String sql = pardeSQL(values[0],nameArgsMap);
System.out.println(sql);
}
return null;
}
});
duofenCardNewMapper.duofenCardList(1,"优惠券");
}
public static String pardeSQL(String sql,Map<String,Object> nameArgsMap){
StringBuilder stringBuilder = new StringBuilder();
int length = sql.length();
for(int i = 0;i < length;i++){
char c = sql.charAt(i);
if(c == '#'){
int nextIndex = i + 1;
char nextChar = sql.charAt(nextIndex);
if(nextChar != '{'){
throw new RuntimeException(String.format("这里应该为#{\nsql:%s\nindex:%d",stringBuilder.toString(),nextIndex));
}
StringBuilder argSB = new StringBuilder();
i = parseSQLArg(argSB,sql,nextIndex);
String argName = argSB.toString();
Object argValue = nameArgsMap.get(argName);
if(argValue == null){
throw new RuntimeException(String.format("找不到参数值:%s",argName));
}
stringBuilder.append(argValue.toString());
continue;
}
stringBuilder.append(c);
}
return stringBuilder.toString();
}
private static int parseSQLArg(StringBuilder argSB, String sql, int nextIndex) {
nextIndex++;
for (;nextIndex < sql.length();nextIndex++){
char c = sql.charAt(nextIndex);
if(c != '}'){
argSB.append(c);
continue;
}
return nextIndex;
}
throw new RuntimeException(String.format("缺少有括号\nindex:%d",nextIndex));
}
/**
* 封装map
* @param method
* @param args
* @return 参数名对应的参数值map
*/
public static Map<String,Object> buildMethodNameArgsMap(Method method, Object[] args){
Map<String,Object> nameArgsMap = new HashMap<>();
//拿到方法参数
Parameter[] parameters = method.getParameters();
int index[] = {0};
//AtomicInteger integer = new AtomicInteger(0);
Arrays.asList(parameters).forEach(parameter -> {
//System.out.println(integer);
nameArgsMap.put(parameter.getName(),args[index[0]]);
index[0]++;
//integer.incrementAndGet();
});
return nameArgsMap;
}
}
执行结果