zoukankan      html  css  js  c++  java
  • mybatis源码解析

    mybatis源码解析
    mybatis原理:
        1.创建sessionFactory
            sessionFactory = SqlSessionFactoryBuilder.build(Configuration config)
        2.MyBatis的SQL查询流程
            原理:利用元数据获取结构集
                ResultSetMetaData metaData = resultSet.getMetaData();
                int column = metaData.getColumnCount();
                for (int i = 1; i <= column; i++) {
                    JdbcType jdbcType = JdbcType.forCode(metaData.getColumnType(i));
                    typeHandlers.add(TypeHandlerRegistry.getTypeHandler(jdbcType));
    
                    columnNames.add(metaData.getColumnName(i));
                }
            步骤:
                sqlSession = sessionFactory.openSession();
                User user = sqlSession.selectOne("UserDao.findById", 1);
                selectOne
                    selectList
                        query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler)
                            query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
                                queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
                                    SimpleExecutor.doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) 
                                    {
                                        Configuration configuration = ms.getConfiguration();
                                        StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
                                        /* SQL查询参数的设置 */
                                        stmt = prepareStatement(handler, ms.getStatementLog());
                                        /* SQL查询操作和结果集封装 */
                                        return handler.<E>query(stmt, resultHandler);
                                    }
                SimpleExecutor
                    {
                        /* SQL查询参数的设置 */
                        Statement prepareStatement(StatementHandler handler, Log statementLog)
                        {
                            /* 获取Connection连接 */
                            Connection connection = getConnection(statementLog);
                            /* 准备Statement */
                            stmt = handler.prepare(connection, transaction.getTimeout());
                            /* 设置SQL查询中的参数值 */
                            handler.parameterize(stmt) 
                            {
                                DefaultParameterHandler.setParameters(PreparedStatement ps)
                                {
                                    /** 设置SQL参数值,从ParameterMapping中读取参数值和类型,然后设置到SQL语句中 */
                                    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
                                    for (int i = 0; i < parameterMappings.size(); i++) {
                                        ParameterMapping parameterMapping = parameterMappings.get(i);
                                        if (parameterMapping.getMode() != ParameterMode.OUT) {
                                            String propertyName = parameterMapping.getProperty();    
                                            Object value = getValueByPropertyName(propertyName);
                                            ...
                                            TypeHandler typeHandler = parameterMapping.getTypeHandler();
                                            JdbcType jdbcType = parameterMapping.getJdbcType();
                                            if (value == null && jdbcType == null) {
                                                jdbcType = configuration.getJdbcTypeForNull();
                                            }
                                            typeHandler.setParameter(ps, i + 1, value, jdbcType);
                                        }
                                    }
                                }
                            }
                            return stmt;
                        }
                        
                        /* SQL查询操作和结果集封装 */
                        <E> List<E> query(Statement statement, ResultHandler resultHandler)
                        {
                            PreparedStatement ps = (PreparedStatement) statement;
                            ps.execute(); // 执行查询操作
                            // 执行结果集封装
                            return resultSetHandler.<E> handleResultSets(ps) {
                                DefaultReseltSetHandler {
                                    List<Object> handleResultSets(Statement stmt) {
                                        /* 获取第一个ResultSet,同时获取数据库的MetaData数据,包括数据表列名、列的类型、类序号等。这些信息都存储在了ResultSetWrapper中了*/
                                        ResultSetWrapper rsw = getFirstResultSet(stmt);
                                        while(rsw != null && resultMapCount > resultSetCount) { // 数量多于1条
                                            handleResultSet(rsw, resultMap, multipleResults, null) { // 处理行结果
                                                handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping) {
                                                    handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping) { // 封装数据
                                                        while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) { // 获取行数据
                                                            Object rowValue = getRowValue(rsw, discriminatedResultMap) {
                                                                // createResultObject为新创建的对象,数据表对应的类
                                                                Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);
                                                                // 把数据填充进去,metaObject中包含了resultObject信息
                                                                foundValues = foundValues || applyAutomaticMappings(rsw, resultMap, metaObject, null) {
                                                                    // 这里进行for循环调用,因为user表中总共有7列,所以也就调用7次
                                                                    for (UnMappedColumnAutoMapping mapping : autoMapping) {
                                                                        // 这里将esultSet中查询结果转换为对应的实际类型
                                                                        final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
                                                                        if (value != null) foundValues = true;
                                                                        metaObject.setValue(mapping.property, value) { // 设值
                                                                            PropertyTokenizer prop = new PropertyTokenizer(name);
                                                                            if (prop.hasNext()) {
                                                                                MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
                                                                                value = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
                                                                                // metaValue.setValue方法最后会调用到Java类中对应数据域的set方法,这样也就完成了SQL查询结果集的Java类封装过程。
                                                                                metaValue.setValue(prop.getChildren(), value);
                                                                            } else {
                                                                                objectWrapper.set(prop, value);
                                                                            }
                                                                        }
                                                                    }
                                                                }
                                                                return foundValues;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
  • 相关阅读:
    数据库连接池的原理。为什么要使用连接池。
    如果你也用过 struts2.简单介绍下 springMVC 和 struts2 的区别有哪些?
    MyBatis 与 Hibernate 有哪些不同?
    Class.forName的作用?为什么要用?
    一个Redis实例最多能存放多少的keys?List、Set、Sorted Set他们最多能存放多少元素?
    MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据?
    如果有大量的key需要设置同一时间过期,一般需要注意什么?
    使用过Redis做异步队列么,你是怎么用的?
    我们如何在Struts2应用程序中集成log4j?
    我们怎样才能在动作类中获得Servlet API请求,响应,HttpSession等对象?
  • 原文地址:https://www.cnblogs.com/ice-line/p/10572763.html
Copyright © 2011-2022 走看看