记学习mybatis源码之路一

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;
    }
}

执行结果

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值