2021-05-28 21:55  阅读(3564)
文章分类:Mybatis 源码分析 文章标签:MybatisMybatis 源码
©  原文作者:ashan_li 原文地址:https://blog.csdn.net/ashan_li/category_6047775.html

背景

我们大多项目都使用了Mybatis。Mybatis的中的sql大多都是配置在xml文件中的,我们为了方便dba对sql统一的管理需要将sql保存在数据库中。这样就要求Mybatis从数据库中加载配置,同时dba优化sql之后还得实现让Mybatis在不重启应用的情况下动态加载。要实现这些功能,需要对Mybatis进行扩展,所以本人花了一些时间分析一Mybatis3源码,在此记录。

分析计划

主要分析如下三大内容:

  1. 分析Mybatis是怎么解析配置文件
  2. 分析Mybatis是如何执行Sql并映射结果
  3. 分析Mybatis是如何使用缓存的

技术要求

#

  1. core java。尤其是jdbc部分。
  2. 基本的xml知识。
  3. 以上都具备的话,还需要花点时间看看Mybatis:http://mybatis.org/mybatis-3/zh/

环境准备

在eclipse中新建一个普通的maven工程,并加上Mybatis的依赖

        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
          <groupId>com.ashan</groupId>
          <artifactId>mybatis</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <dependencies>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.2.6</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.26</version>
            </dependency>
            <dependency>
                <groupId>commons-lang</groupId>
                <artifactId>commons-lang</artifactId>
                <version>2.5</version>
            </dependency>
          </dependencies>
        </project>
    

数据模型

电信行业最简单的三户模型:客户、用户、账户

  1. 客户:即一个证件对应一个客户
  2. 用户:一个电话号码或宽带账号对应一个用户
  3. 账户:一个银行账户对应一个账户

这里假定这个情形:你拿身份证去电信运营商里办了一个号码,并且提供了两个银行账户,每个月都可以使用这两个账号自动交话费。

用户定义

        package com.ashan.mybatis;
    
        import java.util.List;
    
        /**
         * 用户
         *
         * @author ashan
         *
         */
        public class User
        {
    
            /**
             * 用户id,主键
             */
            private String id;
    
            private String username;
    
            /**
             * 用户号码
             */
            private String svcnum;
    
            private String password;
    
            /**
             * 一个用户只能对应一个客户
             */
            private Cust cust;
    
            /**
             * 一个用户可以有多个账户
             */
            private List<Acct> accts;
    
            /**
             * 用户类型,两种:普通用户和重要用户
             */
            private UserType type;
    
    
    
            public User(String id, String username)
            {
                super();
                this.id = id;
                this.username = username;
            }
    
            public String getId()
            {
                return id;
            }
    
            public void setId(String id)
            {
                this.id = id;
            }
    
            public String getUsername()
            {
                return username;
            }
    
            public void setUsername(String username)
            {
                this.username = username;
            }
    
            public String getPassword()
            {
                return password;
            }
    
            public void setPassword(String password)
            {
                this.password = password;
            }
    
            public Cust getCust()
            {
                return cust;
            }
    
            public void setCust(Cust cust)
            {
                this.cust = cust;
            }
    
            public List<Acct> getAccts()
            {
                return accts;
            }
    
            public void setAccts(List<Acct> accts)
            {
                this.accts = accts;
            }
    
            public UserType getType()
            {
                return type;
            }
    
            public void setType(UserType type)
            {
                this.type = type;
            }
    
            public String getSvcnum()
            {
                return svcnum;
            }
    
            public void setSvcnum(String svcnum)
            {
                this.svcnum = svcnum;
            }
    
    
    
    
        }
    
    

用户定义

        package com.ashan.mybatis;
    
        public class Cust
        {
            private String id;
    
            private String custname;
    
            /**
             * 证件号码
             */
            private String certNo;
    
            public String getId()
            {
                return id;
            }
    
            public void setId(String id)
            {
                this.id = id;
            }
    
            public String getCustname()
            {
                return custname;
            }
    
            public void setCustname(String custname)
            {
                this.custname = custname;
            }
    
            public String getCertNo()
            {
                return certNo;
            }
    
            public void setCertNo(String certNo)
            {
                this.certNo = certNo;
            }
    
    
    
        }
    
    

账户定义

        package com.ashan.mybatis;
    
        public class Acct
        {
            private String id;
    
            private String payName;
    
            /**
             * 银行账号
             */
            private String bankNo;
    
            public String getId()
            {
                return id;
            }
    
            public void setId(String id)
            {
                this.id = id;
            }
    
            public String getPayName()
            {
                return payName;
            }
    
            public void setPayName(String payName)
            {
                this.payName = payName;
            }
    
            public String getBankNo()
            {
                return bankNo;
            }
    
            public void setBankNo(String bankNo)
            {
                this.bankNo = bankNo;
            }
    
    
        }
    
    

用户类型

        package com.ashan.mybatis;
    
        public enum UserType
        {
    
            /**
             * 普通用户
             */
            GENERAL,
    
    
            /**
             * 重要用户
             */
            IMPORTANT
        }
    
    

Mybatis配置

mybatis-config.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="db.properties"></properties>
    
            <environments default="development">
                <environment id="development">
                    <transactionManager type="JDBC"></transactionManager>
                    <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>
    
    
            <mappers>
                <mapper resource="UserMapper.xml"/>
            </mappers>
    
        </configuration>
    

UserMapper.xml

        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        <mapper namespace="com.ashan.user">
            <resultMap type="com.ashan.mybatis.User" id="detailUserResultMap">
                <constructor>
                    <idArg column="user_id" javaType="String"/>
                    <arg column="user_name"/>
                </constructor>
    
                <result property="password" column="user_pwd" />
                <result property="type" column="user_type" javaType="com.ashan.mybatis.UserType" typeHandler="com.ashan.mybatis.UserTypeHandler"/>
                <result property="svcnum" column="svc_num" />
    
                <association property="cust" javaType="com.ashan.mybatis.Cust">
                    <id property="id" column="cust_id"/>
                    <result property="custname" column="cust_name"/>
                    <result property="certNo" column="cert_no"/>
                </association>
    
                <collection property="accts" ofType="com.ashan.mybatis.Acct">
                    <id property="id" column="acct_id" />
                    <result property="payName" column="pay_name"/>
                    <result property="bankNo" column="bank_no"/>
                </collection>
    
            </resultMap>
    
    
            <select id="selectUserDetail" resultMap="detailUserResultMap">
                <![CDATA[
                    select user_id,user_name,user_type,cust_id from tf_f_user a where a.user_id=#{userId}
                ]]>
            </select>
    
    
        </mapper>
    

跑跑试试看有没有问题

        package com.ashan.mybatis;
    
        import java.io.InputStream;
    
        import org.apache.ibatis.io.Resources;
        import org.apache.ibatis.session.SqlSessionFactory;
        import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
        public class SqlSesstionFactoryTest
        {
    
            public static void main(String[] args) throws Exception
            {
                String resouce="mybatis-config.xml";
                InputStream is=Resources.getResourceAsStream(resouce);
                SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(is);
                System.out.println(sqlSessionFactory.getConfiguration());
            }
        }
    
    

运行没有异常说明配置OK!

其他说明

搭建这个环境的作用是为了在分析代码过程中进行Debuger,有些时候源代码很难明白,Debuger一下能知道代码的走向,有时源代码看明白了,Debuger一下也能帮助验证自己的理解是否有错。Debuger对分析源码非常有用。

使用Maven构建这个工程除了方便jar导入之后,还有一个用处就是在eclipse中查看源代码非常方便。在eclipse使用maven工程,eclipse会自动下载并关联源代码。

点赞(2)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Mybatis3源码分析(01)-前期准备
下一篇
Mybatis3源码分析(02)-加载Configuration-XMLConfigBuilder