• mybatis


    MyBatis:底层封装了JDBC的持久层框架

    1.为什么使用MyBatis

    1.1. 传统的ORM框架介绍?

    1. 传统的访问数据库的方式?JDBC
      1. 加载驱动 Class.forName()
      2. 获得连接 Connection con…
      3. 创建执行SQL的Statement对象 PreparedStatement…
      4. 执行SQL返回结果 execute executeUpdate executeQuery()
      5. 处理结果 while rs.next()…
      6. 关闭资源 close
      问题:面向对象开发和面向关系存储之间不匹配问题【不完全对应。】开发人员手动处理由对象到关系型数据库之间的对应。【手动处理】
    2. ORM思想的出现:
      1. ORM:Object Relational Mapping 对象关系映射,这种思想目标是把面向对象开发中的对象映射到基于SQL的关系型数据库中。

      2. addStu(Student stu) orm: addStu(Student stu)

        jdbc:手动造车 手动执行 ORM框架.save(stu)–>XML 映射文件

        手动处理结果 手动写SQL 映射文件: 类=表 类中属性-表中字段

        ​ }

    3. ORM是一种思想,其中最著名的实现: Hibernate.

    4. Hibernate是一款“全自动”的ORM映射框架:实现了Pojo到数据库表的全套映射机制,开发人员只需要定义好映射文件。Hibernate会自动的根据映射文件逻辑生成SQL语句、自动的执行SQL语句、自动的返回结果。

    5. Hibernate save()–>insert语句 翻译过程 效率非常低、SQL语句不灵活

    2.MyBatis简介?

    1. MyBatis也是一款ORM思想的实现框架,底层也是封装的JDBC。

    2. MyBatis是一款"半自动的"ORM框架. MyBatis也会执行SQL,返回结果。具体的SQL语句需要开发人员自己写。 灵活 效率高。

    3. MyBatis在2010年之前叫IBatis,属于ASF(apache software foundation),后来退出ASF,改名为MyBatis。

    4. 文档地址:

      https://mybatis.org/mybatis-3/zh/configuration.html

    5. MyBatis中有两类配置文件:

      1. 属性文件mybatis-config.xml:连接数据库的信息+属性 配置
      2. 映射文件StudentMapper.xml: 我们写的SQL语句

    3.MyBatis提供的用户接口?

    1. org.apache.ibatis.session.SqlSessionFactoryBuilder:
      1. build(IO流)
      2. build(Configuration 配置对象)
    2. org.apache.ibatis.session.SqlSessionFactory:
      1. openSession()
    3. org.apache.ibatis.session.SqlSession:[核心]
      1. insert
      2. update
      3. delete
      4. selectOne selectList…

    4. MyBatis的helloworld[对学生表的CRUD]?

    1. 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>
          <settings><!--logImpl:LOG4J 采用log4j做日志-->
              <setting name="logImpl" value="LOG4J"></setting>
          </settings>
        <typeAliases>
              <!--注册别名 所有需要完成包名+类名的地方都可以通过 别名来替换-->
              <!--<typeAlias type="com.etoak.student.entity.Student" alias="stu"></typeAlias>
              <typeAlias type="com.etoak.student.entity.School" alias="sch"></typeAlias>-->
              <!--给指定的包及其子包起别名 别名默认是:类名字首字母小写 ,可以通过@Alias注解修改默认规则-->
            <package name="com.etoak.student.entity"/>
          </typeAliases>
          <environments default="m">
              <environment id="m">
                  <!--事务管理器:JDBC:代表使用JDBC的方式管理事务
                      Connection.setAutoCommit();
                      Connection.commit();/rollback()
                  -->
                  <transactionManager type="JDBC"></transactionManager>
                  <!--POOLED:代表采用MyBatis使用了连接池方式实现的数据源-->
                  <dataSource type="POOLED">
                      <property name="driver" value="${m.driver}"></property>
                      <property name="url" value="${m.url}"></property>
                      <property name="username" value="${m.user}"></property>
                      <property name="password" value="${m.pwd}"></property>
                  </dataSource>
              </environment>
          </environments>
          <mappers>
              <mapper resource="StudentMapper.xml" />
          </mappers>
      </configuration>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36

    请添加图片描述

    1. XXMapper.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.et">
          <!--
          insert: 执行 insert语句 executeUpdate
          -->
          <insert id="addStu" parameterType="com.etoak.student.pojo.Student">
              insert into student( name, age, birth, email, schid)
              values(#{name},#{age},#{birth},#{email},#{schid})
          </insert>
          <!--
          select:执行查询
          -->
          <select id="queryStuById" parameterType="int"
                  resultType="com.etoak.student.pojo.Student">
              select * from student where id=#{id}
          </select>
          <!--
          UPDATE executeUpdate
          -->
          <update id="updateStu" >
              update student set name=#{name},age=#{age},birth=#{birth},
                                 email=#{email} where id=#{id}
          </update>
          <!--
          delete executeUpdate
          -->
          <delete id="deleteStu" >
              delete from student where id=#{id}
          </delete>
          <select id="queryAll" resultType="com.etoak.student.pojo.Student">
              select * from student
          </select>
      
      </mapper>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
    2. 基础操作

     session.insert(SQL语句id,参数)
     session.update(SQL语句id,参数)
     session.delete(SQL语句id,参数)
     session.selectOne(SQL语句id,参数)
     session.selectList(SQL语句id,参数)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5. Mapper方式实现MyBatis?

    • Mapper.xml中namespace的名字和Mapper接口的名字一致
    • Mapper.xml中的SQL语句的id和Mapper接口中方法名字一致

    6. 类中属性和表中字段不完全一致?

    1. 添加

      #{类中的属性不是表中的字段}

    2. 查询
      1. 起别名

         <select id="queryById" parameterType="int"
            resultType="stu">
                select
                s_id as id,
                s_name name,
                s_age age,
                s_birth birth,
                s_email as email,
                s_schid as schid
                from tb_stu where s_id=#{id}
            </select>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
      2. 使用resultMap

        <resultMap id="rMap_stu" type="stu">
                <id property="id" column="s_id"></id>
                <result property="name" column="s_name"></result>
                <result property="age" column="s_age"></result>
                <result property="birth" column="s_birth"></result>
                <result property="email" column="s_email"></result>
                <result property="schid" column="s_schid"></result>
            </resultMap>
            <select id="queryById" parameterType="int"  resultMap="rMap_stu">
                select * from tb_stu where s_id=#{id}
            </select>
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11

    7. 传递多个参数?

    1. Map

    2. @Param

    3. 对象

     List<Student> querySome1(@Param("start")int startadadfa,
                                @Param("pageSize") int pageSizeasdfadf);
    
        List<Student> querySome(Map<String,Object> map);
    
    • 1
    • 2
    • 3
    • 4

    8. resultType和resultMap的区别?

    • resultType:表示执行SQL查询之后的结果集的每一条记录返回的类型,如:自定义的对象Student/User/Teacher、int、map
    • resultMap:一定对应的一个元素的id

    9. MyBatis如何获得添加到数据库中的主键?

    1. JDBC如何获得?

      1. 自动增长的数字
        1. 开关 Statement.RETURN_GENERATED_KEYS
        2. 同一个连接前提下查询:select last_insert_id()
      2. 字符串
        1. select replace(uuid(),‘-’,‘’)
        2. UUID.randomUUID()
        3. KeyGenerator.getId()
    2. MyBatis和JDBC原理一样。

      1. 使用useGeneratedKeys +keyProperty属性

        <insert id="addStudent" parameterType="stu" useGeneratedKeys="true"
            keyProperty="id" keyColumn="s_id" >
                insert into tb_stu( s_name, s_age, s_birth, s_email, s_schid)
                values(#{name},#{age},#{birth},#{email},#{schid})
            </insert>
        
        • 1
        • 2
        • 3
        • 4
        • 5
      2. selectKey

         <insert id="addStudent" parameterType="stu" >
                <selectKey keyProperty="id" keyColumn="s_id" resultType="int"
                order="AFTER">
                    select last_insert_id()
                   <!-- select replace(uuid(),'-','')-->
                </selectKey>
                insert into tb_stu( s_name, s_age, s_birth, s_email, s_schid)
                values(#{name},#{age},#{birth},#{email},#{schid})
            </insert>
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10

    10. 批量添加?

    1. 使用就是动态标签 foreach

       <insert id="addStus1" parameterType="list">
              insert into tb_stu(s_name, s_age, s_birth, s_email, s_schid)
              values
              <foreach collection="list" item="s" separator=",">
                  (#{s.name},#{s.age},#{s.birth},#{s.email},#{s.schid})
              </foreach>
      
          </insert>
      
          <insert id="addStus" parameterType="list">
              insert into tb_stu(s_name, s_age, s_birth, s_email, s_schid)
      
              <foreach collection="list" item="s" separator=" union ">
                  (select  #{s.name},#{s.age},#{s.birth},#{s.email},#{s.schid} )
              </foreach>
      
          </insert>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

    11. 模糊查询:#和$的区别?

    1.#底层使用的是预编译的Statement,即:PreparedStatement,支持?占位符的。$:底层使用的是普通的Statement,不支持?占位符的,参数只能拼接。

    2.有些情况不能使用?占位:

    ​ 参考JDBC :PrearedStatement和Statement的区别。

    12. MyBatis中的动态SQL标签?

    • where

    • if

        <select id="queryByConditions1" resultMap="rMap_stu">
              select * from tb_stu
              <where>
                  <if test="name!=null and name!='' ">
                      and s_name like '%${name}%'
                  </if >
                  <if test="email!=null and email!='' ">
                      and s_email=#{email}
                  </if>
              </where>
          </select>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • foreach

       <insert id="addStus1" parameterType="list">
              insert into tb_stu(s_name, s_age, s_birth, s_email, s_schid)
              values
              <foreach collection="list" item="s" separator=",">
                  (#{s.name},#{s.age},#{s.birth},#{s.email},#{s.schid})
              </foreach>
      
          </insert>
          <insert id="addStus" parameterType="list">
              insert into tb_stu(s_name, s_age, s_birth, s_email, s_schid)
      
              <foreach collection="list" item="s" separator=" union ">
                  (select  #{s.name},#{s.age},#{s.birth},#{s.email},#{s.schid} )
              </foreach>
      
          </insert>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    • trim

       <select id="queryByConditions" resultMap="rMap_stu">
              select * from tb_stu
              <!--prefix:前缀  prefixOverrides:前边遇到什么内容干掉-->
                  <trim prefix="where" prefixOverrides="and">
                      <if test="name!=null and name!='' ">
                          and s_name like '%${name}%'
                      </if >
                      <if test="email!=null and email!='' ">
                          and s_email=#{email}
                      </if>
                  </trim>
      
          </select>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    • chose…when.otherwise

       <select id="queryByConditions" resultMap="rMap_stu">
              select * from tb_stu
              <!--prefix:前缀  prefixOverrides:前边遇到什么内容干掉-->
              <trim prefix="where" prefixOverrides="and">
                 <choose>
                     <when test="name!=null and name!='' ">
                         and s_name like '%${name}%'
                     </when>
                      <otherwise>
                          and s_email=#{email}  
                      </otherwise>
                 </choose>
              </trim>
      
          </select>
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

    13. 一对一和一对多的关联查询?

    • association

       <resultMap id="rMap_stu_sch" type="stu">
              <id property="id" column="s_id"></id>
              <result property="name" column="s_name"></result>
              <result property="age" column="s_age"></result>
              <result property="birth" column="s_birth"></result>
              <result property="email" column="s_email"></result>
              <result property="schid" column="s_schid"></result>
              <!--association:一对一关联
                  property:类中的属性 javaType:属性的类型-->
              <association property="sch" javaType="com.etoak.student.entity.School">
                  <id property="id" column="id"></id>
                  <result property="name" column="name"></result>
                  <result property="phone" column="phone"></result>
                  <result property="info" column="info"></result>
              </association>
          </resultMap>
          <select id="queryByIdWithSch" resultMap="rMap_stu_sch">
              select
              s_id, s_name, s_age, s_birth, s_email, s_schid,
              sch.id, sch.name, sch.phone,sch.info
              from tb_stu s left join school sch
                  on s.s_schid = sch.id where s.s_id=#{id}
          </select>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
    • collection:一对多

        <resultMap id="rMap_sch" type="com.etoak.student.entity.School">
              <id property="id" column="id"></id>
              <result property="name" column="name"></result>
              <result property="phone" column="phone"></result>
              <result property="info" column="info"></result>
              <!--
              collection:表示集合 List /set都可以
                  property:类中的属性
                  ofType:集合中每一个元素的类型
              -->
              <collection property="stus" ofType="stu">
                  <id property="id" column="s_id"></id>
                  <result property="name" column="s_name"></result>
                  <result property="age" column="s_age"></result>
                  <result property="birth" column="s_birth"></result>
                  <result property="email" column="s_email"></result>
                  <result property="schid" column="s_schid"></result>
              </collection>
          </resultMap>
          <select id="querySchWithStus" resultMap="rMap_sch">
              select sch.id, sch.name, sch.phone,sch.info,
                     s_id, s_name, s_age, s_birth, s_email, s_schid
              from school sch   left join tb_stu s on s.s_schid = sch.id
              where sch.id=#{id}
          </select>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25

    14. MyBatis的核心接口【面向内部的】?

    1. org.apache.ibatis.session.Configuration:

      1. 代表MyBatis中的配置文件
      2. 其中的属性:Environment:代表环境标签
      3. 其中的属性:MappedStatement:代表SQL映射文件中的等标签
    2. org.apache.ibatis.mapping.Environment:

      1. 代表环境元素.
      2. 其中的属性:id+transactionFactory+dataSource
    3. org.apache.ibatis.mapping.MappedStatement:

      1. 代表SQL映射文件中的标签

      2. 其中的属性:

        1. StatementType:执行器的类型 枚举

          STATEMENT:普通的执行器
          PREPARED:预编译的执行器
          CALLABLE:执行触发器的执行器
          
          • 1
          • 2
          • 3
        2. ResultSetType:结果集的类型 枚举

          	DEFAULT(-1):默认的结果集
             FORWARD_ONLY(1003):不可滚动的结果集
             SCROLL_INSENSITIVE(1004):可滚动结果集
             SCROLL_SENSITIVE(1005):可滚动的结果集
          
          • 1
          • 2
          • 3
          • 4
        3. SqlCommandType:SQL语句的类型 枚举

          INSERT/UPDATE/DELETE/SELECT/UNKNOWN
          
          • 1
        4. SqlSource:解析SQL语句的方法+获得SQL的方法

          其中有一个方法getBoundSql:BoundSql真正代表SQL语句
          
          • 1
    4. org.apache.ibatis.type.TypeAliasRegistry:类型别名注册器 存放别名

      1. TypeAliasRegistry构造时默认注册一些别名: int string list

      2. new Configuration():中 自动添加别名 如:JDBC POOLED LOG4J

      3. 我们写的别名

          1.  <typeAlias type="" alias="">
        
         
          2.  <typeAliasPackage value="">
        
        • 1
        • 2
        • 3
        • 4

    请添加图片描述

    1. org.apache.ibatis.builder.BaseBuilder:基本的解析器

      1. 代表解析器。解析XML的。

      2. 其中主要属性和构造方法

        public abstract class BaseBuilder{    
            protected final Configuration configuration;
            protected final TypeAliasRegistry typeAliasRegistry;
            protected final TypeHandlerRegistry typeHandlerRegistry;
        
            public BaseBuilder(Configuration configuration) {
                this.configuration = configuration;
                this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
                this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
            }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      1. BaseBuilder有很多子类:

        1. XMLConfigBuilder:解析 mybatis-config.xml
        2. XMLMapperBuilder:解析 *Mapper.xml
        3. XMLStatementBuilder:解析insert update delete标签的
        4. XMLScriptBuilder:SQL语句
    2. org.apache.ibatis.io.Resources:资源

      1. 该类是MyBatis封装的工具类。专门加载配置文件
      2. 底层委托 classLoaderWrapper实现具体加载的。原理就是使用ClassLoader.getResourceAsStream实现的。

    15. 解析配置以及SqlSessionFactory构造的过程?

    1. SF工厂

    请添加图片描述

    1. build(reader)

    请添加图片描述

    1. 分步骤解析:1.XMLConfigBuilder parser = new XMLConfigBuilder(reader)

    请添加图片描述

    XMLPathParser:接收mybatis-config.xml流+resolver,本身提供把流转换成Document对象【JDK中提供DOM解析器】的方法和一堆使用JDK中提供的XPath方式计算XML中每一个部分的的方法。

    请添加图片描述

    1. 分析步骤2: parser.parse():挨个解析mybatis-config和mapper.xml中的每一个元素 最终都装configuration对象

      请添加图片描述

    2. 步骤分析3:new DefaultSqlSessioFacotry(config)

    16. parseConfiguration中的几个部分分析?

    1. 解析元素

      请添加图片描述

    2. 解析元素

    请添加图片描述

    1. 解析元素

    请添加图片描述

    1. XMLConfigBuilder:解析mybatis-config.xml

      1.XMLConfigBuilder中 调用 XMLMapperBuilder解析 Mapper.xml,

      2.然后再XMLMapperBuilder 调用XMLStatementBuilder专门解析元素中的每一个属性和内容

      2.然后再XMLStatementBuilder中调用XMLScriptBuilder 构造SQL语句 BoundSql===》SqlSource

    17. 常见错误?

    • Mapped Statements collection does not contain value for xxx

    ​ 原因: SQL语句映射文件中没有DAO层调用的语句。

    • A query was run and no Result Maps were found for the Mapped Statement ‘com.et2203.queryById’. It’s likely that neither a Result Type nor a Result Map was specified.

      原因:执行的是查询语句,没有resultType或者resultMap。

    • Caused by: org.apache.ibatis.binding.BindingException: Parameter ‘start’ not found. Available parameters are [arg1, arg0, param1, param2]

      原因:传递多个参数MyBatis默认不会按照形参去命名,而是自动命名为:arg0,arg1…或者param1 param2…

  • 相关阅读:
    Springboot项目如何加密返回值和请求参数
    Java项目实战《苍穹外卖》 二、项目搭建
    数字IC设计全流程
    AIE荧光分子杂化介孔二氧化硅杂化纳米微球/聚合诱导微米级多孔SiO2微球
    Android自动化测试工具调研
    WCF配置文件详解
    KOSMOS-2.5:密集文本的多模态读写模型
    Java项目:JSP宠物店管理系统
    javaWeb的概念、Web的资源分类、常见的Web服务器
    面试题三:请你谈一谈Vue中的filter功能的实现
  • 原文地址:https://blog.csdn.net/qq_45041558/article/details/125610317