mybtais 源码分析

一.最原始的使用jdbc连接mysql:

     maven依赖只要一个:

   <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.45</version>
    </dependency>


步骤:加载驱动(可以省略)—>获取连接对象—>创建预执行语句对象—>执行sql—>释放连接对象(口诀:贾琏欲执事)代码如下:

public class App 
{
    public static void main( String[] args )
    {
        Connection connection=null;
        try {
            //获取连接对象
            connection = DriverManager.getConnection("jdbc:mysql://192.168.50.117:23306/shop?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false", "shop", "shop");
            String sql="update  shop_order_attr set flg_type=? where cod_order_id=?";
            //获取预执行语句
            PreparedStatement preparedStatement = connection.prepareStatement(sql);

            preparedStatement.setInt(1,30);
            preparedStatement.setString(2,"666655555555");
            connection.setAutoCommit(false);
            //执行sql
            boolean execute = preparedStatement.execute();
            connection.commit();
            if (execute){
                System.out.println("成功");
            }
        } catch (Exception e) {
            try {
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }

        }finally {
            if(connection!=null){
                try {
                    //释放连接对象
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

 

 接下来,我们看看mybatis是如何实现上面的功能的:

               首先添加对应的maven 依赖

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>

在resources文件夹下创建mybatis.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="mysql.properties" >
    </properties>
    <settings>
            <setting name="cacheEnabled" value="true"/>
            <setting name="lazyLoadingEnabled" value="true"/>
            <setting name="multipleResultSetsEnabled" value="true"/>
            <setting name="useColumnLabel" value="true"/>
            <setting name="useGeneratedKeys" value="false"/>
            <setting name="autoMappingBehavior" value="PARTIAL"/>
            <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
            <setting name="defaultExecutorType" value="SIMPLE"/>
            <setting name="defaultStatementTimeout" value="25"/>
            <setting name="defaultFetchSize" value="100"/>
            <setting name="safeRowBoundsEnabled" value="false"/>
            <setting name="mapUnderscoreToCamelCase" value="false"/>
            <setting name="localCacheScope" value="SESSION"/>
            <setting name="jdbcTypeForNull" value="OTHER"/>
            <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
    </settings>
    <typeAliases>
        <typeAlias type="com.yang.xiao.hui.entity.ShopOrderAttr" alias="shopOrderAttr"></typeAlias>
        <package name="com.yang.xiao.hui.entity"/>
    </typeAliases>
    <typeHandlers>
        <typeHandler handler="com.yang.xiao.hui.entity.ExampleTypeHandler"></typeHandler>
    </typeHandlers>
    <objectFactory type="com.yang.xiao.hui.entity.MyObjectFactory"></objectFactory>
    <reflectorFactory type="org.apache.ibatis.reflection.DefaultReflectorFactory"/>
    <plugins>
        <plugin interceptor="com.yang.xiao.hui.interceptor.MyInterceptor"></plugin>
    </plugins>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <databaseIdProvider type="DB_VENDOR" />
    <mappers>
        <mapper resource="com/yang/xiao/hui/mapper/ShopOrderAttr.xml"/>
    </mappers>
</configuration>

之后我们给张表shop_order_attr创建实体类 Mapper接口以及Mapper.xml文件:

 

 之后在启动类加入如下代码:

public class MybatisApp {
    public static void main(String[] args) {
        String resource = "mybtais.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //读取mybatis.xml的内容获取sessionFactory的工厂

            SqlSession sqlSession = sqlSessionFactory.openSession();//获取SqlSession
            ShopOrderAttrMapper shopOrderAttrMapper = sqlSession.getMapper(ShopOrderAttrMapper.class); //获取代理类
            String orderId = shopOrderAttrMapper.selectOne("666655555555",30);//调用对应的方法
            System.out.println(orderId);


        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 该方法会解析mybtis.xml并将所有的信息存到一个叫Configuration的对象中,后续所有的操作都跟该对象相关;

mybatis创建代理对象的流程:我们通过SqlSession获取Mapper的代理类,会委托给Configuration对象,然后configuration对象委托给MapperReistry对象,该对象里面有个knownMappes集合,该集合在解析mybtis.xml时,已经将对应的接口信息封装成MapperProxyFactory对象中,

因此,通过knownMappes可以得到一个MapperProxyFactory,该对象有个创建代理对象的方法,newInstance(),调用该方法先创建一个MapperProxy对象,该对象实现了InvocationHandler接口,因此在创建代理类时,将其作为参数传入得到代理类,

代理类的所有方法执行,都会被MapperProxy进行拦截 

 sql执行流程:由前面知道,Mapper对象因为动态代理,执行目标方法时,会被MapperProxy进行拦截,在拦截的方法里,会根据方法创建SqlCommand对象,然后根据该对象的类型调用SqlSession的对应方法,

底层会委托给Executor去执行,该对象最终调用PrepareStatment对象进行数据库的调用,得到结果交给ResultSetHandler进行处理

SqlCommand对象的创建:里面有2个属性,name是接口.方法名,如com.tft.User.selectOne  type是sql的类型,如Select Update等

 

 MethodSignature:方法签名:主要的逻辑是存储方法返回值的类型以及所有的参数Map<key为index,value为方法名>

 

posted @ 2020-10-12 12:11  yangxiaohui227  阅读(105)  评论(0编辑  收藏  举报