mybatis执行一条sql语句的过程(底层源码解析)

测试代码块:

 @Test
    public void testCreateTable(){
        try {
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder= new SqlSessionFactoryBuilder();
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
            SqlSession sqlSession = sqlSessionFactory.openSession(true);
            Teacher teacher=new Teacher(0,"李四",10000,new Date());
            TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
            mapper.updateTeacher(teacher);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

第一句:InputStream is = Resources.getResourceAsStream(“mybatis-config.xml”);

这里就是传入mybatis-config.xml配置文件的路径,获得一个流对象,没什么好讲的
但是有一点值得注意:

    InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
        ClassLoader[] var3 = classLoader;
        int var4 = classLoader.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            ClassLoader cl = var3[var5];
            if (null != cl) {
                InputStream returnValue = cl.getResourceAsStream(resource);
                if (null == returnValue) {
                    returnValue = cl.getResourceAsStream("/" + resource);
                }

                if (null != returnValue) {
                    return returnValue;
                }
            }
        }

        return null;
    }

可以看到returnValue = cl.getResourceAsStream("/" + resource);拼接了一个"/",也就是从项目根路径开始找文件,所以我们在写路径的时候不需要加“/”,同时,如果使用的是maven工程,这些配置文件直接放在resources文件夹下就可以了,在项目编译打包之后,没有resources文件夹,里面的文件都会直接放到src目录下

第二句:SqlSessionFactoryBuilder sqlSessionFactoryBuilder= new SqlSessionFactoryBuilder();

创建一个SqlSessionFactoryBuilder对象

第三句:调用sqlSessionFactoryBuilder的builder方法

重载方法之间的调用:

 public SqlSessionFactory build(InputStream inputStream) {
        return this.build((InputStream)inputStream, (String)null, (Properties)null);
    }
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        SqlSessionFactory var5;
        try {
            XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
            var5 = this.build(parser.parse());
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
        } finally {
            ErrorContext.instance().reset();

            try {
                inputStream.close();
            } catch (IOException var13) {
            }

        }

        return var5;
    }

在这里,我们可以看到创建了一个局部变量SqlSessionFactory对象:var5
并且创建了一个有(inputStream, environment, properties)三个参数的XMLConfigBuilder对象
tip:传入的inputStream就是我们配置文件生成的流,enviroment和properties为null

    private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
        super(new Configuration());
        this.localReflectorFactory = new DefaultReflectorFactory();
        ErrorContext.instance().resource("SQL Mapper Configuration");
        this.configuration.setVariables(props);
        this.parsed = false;
        this.environment = environment;
        this.parser = parser;
    }

紧接着在底层调用了调用了xml解析的方法,把配置文件中的driver,url,username,pasword等信息封装到properties对象中

enviroment对象:

public final class Environment {
    private final String id;
    private final TransactionFactory transactionFactory;
    private final DataSource dataSource;

    public Environment(String id, TransactionFactory transactionFactory, DataSource dataSource) {
        if (id == null) {
            throw new IllegalArgumentException("Parameter 'id' must not be null");
        } else if (transactionFactory == null) {
            throw new IllegalArgumentException("Parameter 'transactionFactory' must not be null");
        } else {
            this.id = id;
            if (dataSource == null) {
                throw new IllegalArgumentException("Parameter 'dataSource' must not be null");
            } else {
                this.transactionFactory = transactionFactory;
                this.dataSource = dataSource;
            }
        }
    }

    public String getId() {
        return this.id;
    }

    public TransactionFactory getTransactionFactory() {
        return this.transactionFactory;
    }

    public DataSource getDataSource() {
        return this.dataSource;
    }

    public static class Builder {
        private final String id;
        private TransactionFactory transactionFactory;
        private DataSource dataSource;

        public Builder(String id) {
            this.id = id;
        }

        public Environment.Builder transactionFactory(TransactionFactory transactionFactory) {
            this.transactionFactory = transactionFactory;
            return this;
        }

        public Environment.Builder dataSource(DataSource dataSource) {
            this.dataSource = dataSource;
            return this;
        }

        public String id() {
            return this.id;
        }

        public Environment build() {
            return new Environment(this.id, this.transactionFactory, this.dataSource);
        }
    }
}

在enviroment对象中封装了数据源等信息

第四句: SqlSession sqlSession = sqlSessionFactory.openSession(true);

SqlSessionFactory是一个接口,有两个实现类:
实现类
如果没有特别设置,使用的是DefaultSqlSessionFactory实现类
在defaultSqlSessionFactory中有openSession的很多重载方法

 public SqlSession openSession() {
        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
    }

    public SqlSession openSession(boolean autoCommit) {
        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, autoCommit);
    }

    public SqlSession openSession(ExecutorType execType) {
        return this.openSessionFromDataSource(execType, (TransactionIsolationLevel)null, false);
    }

    public SqlSession openSession(TransactionIsolationLevel level) {
        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), level, false);
    }

    public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {
        return this.openSessionFromDataSource(execType, level, false);
    }

可以传入参数设定自动提交,执行类型,事务传播级别等等

在sqlsession对象中封装了很多执行sql语句的元素,比如自动提交设置,执行器(statment),以及回滚等方法

public class DefaultSqlSession implements SqlSession {
    private final Configuration configuration;
    private final Executor executor;
    private final boolean autoCommit;
    private boolean dirty;
    private List<Cursor<?>> cursorList;

    public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
        this.configuration = configuration;
        this.executor = executor;
        this.dirty = false;
        this.autoCommit = autoCommit;
    }

    public DefaultSqlSession(Configuration configuration, Executor executor) {
        this(configuration, executor, false);
    }

    public <T> T selectOne(String statement) {
        return this.selectOne(statement, (Object)null);
    }

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

    public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
        return this.selectMap(statement, (Object)null, mapKey, RowBounds.DEFAULT);
    }

    public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
        return this.selectMap(statement, parameter, mapKey, RowBounds.DEFAULT);
    }

    public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
        List<? extends V> list = this.selectList(statement, parameter, rowBounds);
        DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler(mapKey, this.configuration.getObjectFactory(), this.configuration.getObjectWrapperFactory(), this.configuration.getReflectorFactory());
        DefaultResultContext<V> context = new DefaultResultContext();
        Iterator var8 = list.iterator();

        while(var8.hasNext()) {
            V o = var8.next();
            context.nextResultObject(o);
            mapResultHandler.handleResult(context);
        }

        return mapResultHandler.getMappedResults();
    }

    public <T> Cursor<T> selectCursor(String statement) {
        return this.selectCursor(statement, (Object)null);
    }

    public <T> Cursor<T> selectCursor(String statement, Object parameter) {
        return this.selectCursor(statement, parameter, RowBounds.DEFAULT);
    }

    public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
        Cursor var6;
        try {
            MappedStatement ms = this.configuration.getMappedStatement(statement);
            Cursor<T> cursor = this.executor.queryCursor(ms, this.wrapCollection(parameter), rowBounds);
            this.registerCursor(cursor);
            var6 = cursor;
        } catch (Exception var10) {
            throw ExceptionFactory.wrapException("Error querying database.  Cause: " + var10, var10);
        } finally {
            ErrorContext.instance().reset();
        }

        return var6;
    }

    public <E> List<E> selectList(String statement) {
        return this.selectList(statement, (Object)null);
    }

    public <E> List<E> selectList(String statement, Object parameter) {
        return this.selectList(statement, parameter, RowBounds.DEFAULT);
    }

    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
        List var5;
        try {
            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;
    }

    public void select(String statement, Object parameter, ResultHandler handler) {
        this.select(statement, parameter, RowBounds.DEFAULT, handler);
    }

    public void select(String statement, ResultHandler handler) {
        this.select(statement, (Object)null, RowBounds.DEFAULT, handler);
    }

    public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
        try {
            MappedStatement ms = this.configuration.getMappedStatement(statement);
            this.executor.query(ms, this.wrapCollection(parameter), rowBounds, handler);
        } catch (Exception var9) {
            throw ExceptionFactory.wrapException("Error querying database.  Cause: " + var9, var9);
        } finally {
            ErrorContext.instance().reset();
        }

    }

    public int insert(String statement) {
        return this.insert(statement, (Object)null);
    }

    public int insert(String statement, Object parameter) {
        return this.update(statement, parameter);
    }

    public int update(String statement) {
        return this.update(statement, (Object)null);
    }

    public int update(String statement, Object parameter) {
        int var4;
        try {
            this.dirty = true;
            MappedStatement ms = this.configuration.getMappedStatement(statement);
            var4 = this.executor.update(ms, this.wrapCollection(parameter));
        } catch (Exception var8) {
            throw ExceptionFactory.wrapException("Error updating database.  Cause: " + var8, var8);
        } finally {
            ErrorContext.instance().reset();
        }

        return var4;
    }

    public int delete(String statement) {
        return this.update(statement, (Object)null);
    }

    public int delete(String statement, Object parameter) {
        return this.update(statement, parameter);
    }

    public void commit() {
        this.commit(false);
    }

    public void commit(boolean force) {
        try {
            this.executor.commit(this.isCommitOrRollbackRequired(force));
            this.dirty = false;
        } catch (Exception var6) {
            throw ExceptionFactory.wrapException("Error committing transaction.  Cause: " + var6, var6);
        } finally {
            ErrorContext.instance().reset();
        }

    }

    public void rollback() {
        this.rollback(false);
    }

    public void rollback(boolean force) {
        try {
            this.executor.rollback(this.isCommitOrRollbackRequired(force));
            this.dirty = false;
        } catch (Exception var6) {
            throw ExceptionFactory.wrapException("Error rolling back transaction.  Cause: " + var6, var6);
        } finally {
            ErrorContext.instance().reset();
        }

    }

    public List<BatchResult> flushStatements() {
        List var1;
        try {
            var1 = this.executor.flushStatements();
        } catch (Exception var5) {
            throw ExceptionFactory.wrapException("Error flushing statements.  Cause: " + var5, var5);
        } finally {
            ErrorContext.instance().reset();
        }

        return var1;
    }

    public void close() {
        try {
            this.executor.close(this.isCommitOrRollbackRequired(false));
            this.closeCursors();
            this.dirty = false;
        } finally {
            ErrorContext.instance().reset();
        }

    }

    private void closeCursors() {
        if (this.cursorList != null && !this.cursorList.isEmpty()) {
            Iterator var1 = this.cursorList.iterator();

            while(var1.hasNext()) {
                Cursor cursor = (Cursor)var1.next();

                try {
                    cursor.close();
                } catch (IOException var4) {
                    throw ExceptionFactory.wrapException("Error closing cursor.  Cause: " + var4, var4);
                }
            }

            this.cursorList.clear();
        }

    }

    public Configuration getConfiguration() {
        return this.configuration;
    }

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

    public Connection getConnection() {
        try {
            return this.executor.getTransaction().getConnection();
        } catch (SQLException var2) {
            throw ExceptionFactory.wrapException("Error getting a new connection.  Cause: " + var2, var2);
        }
    }

    public void clearCache() {
        this.executor.clearLocalCache();
    }

    private <T> void registerCursor(Cursor<T> cursor) {
        if (this.cursorList == null) {
            this.cursorList = new ArrayList();
        }

        this.cursorList.add(cursor);
    }

    private boolean isCommitOrRollbackRequired(boolean force) {
        return !this.autoCommit && this.dirty || force;
    }

    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 static class StrictMap<V> extends HashMap<String, V> {
        private static final long serialVersionUID = -5741767162221585340L;

        public StrictMap() {
        }

        public V get(Object key) {
            if (!super.containsKey(key)) {
                throw new BindingException("Parameter '" + key + "' not found. Available parameters are " + this.keySet());
            } else {
                return super.get(key);
            }
        }
    }
}

第五句:TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);

经过层层调用:

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

返回一个 **return mapperProxyFactory.newInstance(sqlSession);**代理对象

第六句: mapper.updateTeacher(teacher);

使用代理对象执行方法,底层使用了sqlsession对象,以及拿到了封装在properties中的sql语句,进行执行sql语句

新手,欢迎指正!!!!!!!!!!!!!!!!!!!!!!!!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值