Mybatis3

一.第一步创建连接

public static void main(String[] args){
    String resource = "nor/mybatis.xml";
    InputStream inputStream = null;
    SqlSessionFactory factory = null;
    try {
        inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //factory里面有个configuration属性,是Configuration对象的,他里面存了xml解析出来的东西
        //
        factory = builder.build(inputStream);
    } catch (IOException e) {
        e.printStackTrace();
    }

    //开启一个事务
    SqlSession sqlSession=factory.openSession();
    UserBean userBean=new UserBean();
    userBean.setUser_name("sbsbsb");
    //sqlSession.insert("com.x.nor.UserMapper.insert",userBean);
    //sqlSession.commit();
    //UserBean user=sqlSession.selectOne("com.x.nor.UserMapper.select",new UserBean(1,"ff"));
    UserBean user=sqlSession.selectOne("com.x.nor.UserMapper.selectDy",new UserBean(1,"ff"));
    System.out.println(userBean.user_id);
    System.out.println(user.getUser_name());


    //获得代理类,代理类的方法实际上还是调用sqlSession的方法namespace+id
    User userMapper = sqlSession.getMapper(User.class);
    UserBean userBean1=userMapper.select(new UserBean(1,"ff"));

}

在builder.build(inputStream)中解析了xml生成了一个config,这个var5就是SqlSessionFactory

XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
var5 = this.build(parser.parse());

然后进入SqlSession sqlSession=factory.openSession();

这边进入DefaultSqlSessionFactory打开一个sqlSession

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;

    DefaultSqlSession var8;
    try {
        //这个是配置文件里面的environment标签里的         
        Environment environment = this.configuration.getEnvironment();
        //打开一个jdbc事务
        TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
        tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
        //默认是caching类型的
        Executor executor = this.configuration.newExecutor(tx, execType);
        //这边吧上面的东西封装进去自动提交设置autoCommit是false的
        var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
    } catch (Exception var12) {
        this.closeTransaction(tx);
        throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var12, var12);
    } finally {
        ErrorContext.instance().reset();
    }

    return var8;
}
这边默认生成的Executor是Caching类型的,用了装饰器模式


然后返回main方法执行一条查询

sqlSession.selectOne("com.x.nor.UserMapper.selectDy",new UserBean(1,"ff"));

就是执行selectList然后获取第一条数据

public <T> T selectOne(String statement, Object parameter) {
    List<T> list = this.selectList(statement, parameter);
    if (list.size() == 1) {
        return list.get(0);
    } else if (list.size() > 1) {
        throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
    } else {
        return null;
    }
}

到达selectList方法里面configuration这个就是我们之前注入的xml解析之后的放置类

public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    List var5;
    try {
        //进去获取MappedStatement          
        MappedStatement ms = this.configuration.getMappedStatement(statement);
        var5 = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception var9) {
        throw ExceptionFactory.wrapException("Error querying database.  Cause: " + var9, var9);
    } finally {
        ErrorContext.instance().reset();
    }

    return var5;
}

然后进去,这边进去看看是否需要初始化一下


然后这个我们的idMap<String, MappedStatement> mappedStatements这个是个map,里面的MappedStatement就是我们的namespace+id组成的,保存着一条sql,当然里面分为静态和动态的


返回到上面selectList,查询前判断一下数据如果是集合类或者数组的用StrictMap包装一下

private Object wrapCollection(Object object) {
    DefaultSqlSession.StrictMap map;
    if (object instanceof Collection) {
        map = new DefaultSqlSession.StrictMap();
        map.put("collection", object);
        if (object instanceof List) {
            map.put("list", object);
        }

        return map;
    } else if (object != null && object.getClass().isArray()) {
        map = new DefaultSqlSession.StrictMap();
        map.put("array", object);
        return map;
    } else {
        return object;
    }
}

然后进入查询

public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    BoundSql boundSql = ms.getBoundSql(parameterObject);
    CacheKey key = this.createCacheKey(ms, parameterObject, rowBounds, boundSql);
    return this.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

看一下这个ms.getBoundSql这个sqlSource是xml解析好后放进来的,他里面有个contents里面放着静态和动态的


public BoundSql getBoundSql(Object parameterObject) {
        //获取sql
     BoundSql boundSql = this.sqlSource.getBoundSql(parameterObject);
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings == null || parameterMappings.isEmpty()) {
        boundSql = new BoundSql(this.configuration, boundSql.getSql(), this.parameterMap.getParameterMappings(), parameterObject);
    }

    Iterator var4 = boundSql.getParameterMappings().iterator();

    while(var4.hasNext()) {
        ParameterMapping pm = (ParameterMapping)var4.next();
        String rmId = pm.getResultMapId();
        if (rmId != null) {
            ResultMap rm = this.configuration.getResultMap(rmId);
            if (rm != null) {
                this.hasNestedResultMaps |= rm.hasNestedResultMaps();
            }
        }
    }

    return boundSql;
}

接着进入sqlSource的getBoundSql,这边这个rootSqlNode.apply就是遍历里面的sql加入到context里面的stringbuilder

静态直接加入,动态的比如我的if的xml节点的,就会用Ognl这个引擎来执行下参数和语句是否匹配

public BoundSql getBoundSql(Object parameterObject) {
    DynamicContext context = new DynamicContext(this.configuration, parameterObject);
    this.rootSqlNode.apply(context);
    SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(this.configuration);
    Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
    SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    Iterator var7 = context.getBindings().entrySet().iterator();

    while(var7.hasNext()) {
        Entry<String, Object> entry = (Entry)var7.next();
        boundSql.setAdditionalParameter((String)entry.getKey(), entry.getValue());
    }

    return boundSql;
}

在回到query方法里面最后的boundsql就是这个样子的


public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    BoundSql boundSql = ms.getBoundSql(parameterObject);
    CacheKey key = this.createCacheKey(ms, parameterObject, rowBounds, boundSql);
    return this.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

然后生成缓存key,进入下一个query方法,这边二级缓存都在每一个MappedStatement,也就是一条sql一个缓存

public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    //这边是从MappedStatement 获取缓存

    Cache cache = ms.getCache();
    if (cache != null) {
        this.flushCacheIfRequired(ms);
        if (ms.isUseCache() && resultHandler == null) {
            this.ensureNoOutParams(ms, parameterObject, boundSql);
            //这边缓存在TransactionalCacheManager
             List<E> list = (List)this.tcm.getObject(cache, key);
            if (list == null) {
                list = this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
                this.tcm.putObject(cache, key, list);
            }

            return list;
        }
    }

    return this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

接着往下到BaseExecutor

public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (this.closed) {
        throw new ExecutorException("Executor was closed.");
    } else {
        if (this.queryStack == 0 && ms.isFlushCacheRequired()) {
            this.clearLocalCache();
        }

        List list;
        try {
            ++this.queryStack;
            //这边获取一级缓存
             list = resultHandler == null ? (List)this.localCache.getObject(key) : null;
            if (list != null) {
                this.handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
            } else {//这边查数据了
                list = this.queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
            }
        } finally {
            --this.queryStack;
        }

        //省略

        return list;
    }
}

这边进行正式查询略过

private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    this.localCache.putObject(key, ExecutionPlaceholder.EXECUTION_PLACEHOLDER);

    List list;
    try {
        list = this.doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally {
        this.localCache.removeObject(key);
    }

    this.localCache.putObject(key, list);
    if (ms.getStatementType() == StatementType.CALLABLE) {
        this.localOutputParameterCache.putObject(key, parameter);
    }

    return list;
}

看看用借口来查询

//获得代理类,代理类的方法实际上还是调用sqlSession的方法namespace+id
User userMapper = sqlSession.getMapper(User.class);
UserBean userBean1=userMapper.select(new UserBean(1,"ff"));

进入

public <T> T getMapper(Class<T> type) {
    return this.configuration.getMapper(type, this);
}

进入代理

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
    if (mapperProxyFactory == null) {
        throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    } else {
        try {
            return mapperProxyFactory.newInstance(sqlSession);
        } catch (Exception var5) {
            throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
        }
    }
}

查看代理的生成

protected T newInstance(MapperProxy<T> mapperProxy) {
    return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy);
}

public T newInstance(SqlSession sqlSession) {
    MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);
    return this.newInstance(mapperProxy);
}

jdk动态代理然后看MapperProxy里面的invoke方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //省略

    MapperMethod mapperMethod = this.cachedMapperMethod(method);
    return mapperMethod.execute(this.sqlSession, args);
}

看看MapperMethod

public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
    this.command = new MapperMethod.SqlCommand(config, mapperInterface, method);
    this.method = new MapperMethod.MethodSignature(config, mapperInterface, method);
}

看下sqlCommand,这边获得MappedStatement是用接口名加上方法名

private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName, Class<?> declaringClass, Configuration configuration) {
        String statementId = mapperInterface.getName() + "." + methodName;
        //省略
}

然后回到MapperMethod这边就是最后的执行还是sqlsession的方法,command就是sqlcommand

public Object execute(SqlSession sqlSession, Object[] args) {
    Object param;
    Object result;
    switch(this.command.getType()) {
    case INSERT:
        param = this.method.convertArgsToSqlCommandParam(args);
        result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
        break;
    case UPDATE:
        param = this.method.convertArgsToSqlCommandParam(args);
        result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
        break;
    case DELETE:
        param = this.method.convertArgsToSqlCommandParam(args);
        result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
        break;
    case SELECT:
        if (this.method.returnsVoid() && this.method.hasResultHandler()) {
            this.executeWithResultHandler(sqlSession, args);
            result = null;
        } else if (this.method.returnsMany()) {
            result = this.executeForMany(sqlSession, args);
        } else if (this.method.returnsMap()) {
            result = this.executeForMap(sqlSession, args);
        } else if (this.method.returnsCursor()) {
            result = this.executeForCursor(sqlSession, args);
        } else {
            param = this.method.convertArgsToSqlCommandParam(args);
            result = sqlSession.selectOne(this.command.getName(), param);
        }
        break;
    case FLUSH:
        result = sqlSession.flushStatements();
        break;
    default:
        throw new BindingException("Unknown execution method for: " + this.command.getName());
    }

    if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
        throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
    } else {
        return result;
    }
}










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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值