• 一、MyBatis 框架



    一、MyBatis 概念

    • MyBatis 是一款优秀的 持久层框架,它支持 定制化SQL、存储过程 以及 高级映射
    • MyBatis 避免了几乎所有的 JDBC代码 和 手动设置参数,以及获取结果集。
    • MyBatis 可以使用 简单的XML 或 注解,来配置和映射 原生类型、接口 和 Java的POJO(Plain Old Java Objects,普通老式 Java对象)为数据库中的记录。

    1. 其它持久层框架

    1. JDBC
    2. DataUtils
    3. JdbcTemplate
    4. Hibernate

    2. 核心对象的 作用域 与 生命周期

    • SqlSessionFactoryBuilder。
      用于构建会话工厂,基于 SqlMapConfig.xml 的 environment、properties 构建会话工厂,构建完成后即可丢弃。

    • SqlSessionFactory。
      用于生成会话的工厂,作用于整个应用运行期间,一般不需要构造多个工厂对像。

    • SqlSession。
      作用于单次会话,如:WEB一次请求期间,不能用作于某个对像属性,也不能在多个线程间共享,因为它是线程不安全的。

    3. 接口式编程

    • 由于每次调用时都去找对应用 statement 以及拼装参数,使用上不是特别友好,MyBatis 引入了 接口机制,将接口与 mapper.xml 的 namespace 名称绑定,MyBatis 就可以根据 ASM工具 动态构建该接口的实例。
    • Mapper 映射器接口实例。
      通过 session.getMapper(Class<T> type) 就可以获取 mapper 实例,该实例一般作用于方法域。

    二、全局 SqlMapConfig.xml配置


    1. 属性

    • properties元素。
    1. 可以通过 resource 或 url加载外部 properties文件 中的属性,也可以直接设置 property属性。
    2. 在 xml中 就可以通过 ${属性名} 进行引用替换。
    • 从 MyBatis-3.4.2 开始,占位符可以指定一个默认值。例如:${jdbc.user:root}

    2. 设置

    • 设置 MyBatis全局参数,约定 MyBatis的全局行为。
    <!-- 设置 -->
    <settings>
        <!-- 开启二级缓存。-->
        <setting name="cacheEnabled" value="true"/>
        <!-- 开启驼峰命名适配。-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3. 别名

    • 在 MyBatis 中经常会用到 Java中的类型,如:SQL块中的 parameterType参数引用中JavaType,结果集 映射的JavaType,都要使用 Java全路径名。
    • 提示:建议不要设置。
      因为常用的类 MyBatis 已经内置别名,而 自定义的类 设置别名 反而不好去找,影响阅读。

    3. 环境

    • 一个项目经常需要在例如 开发坏境、测试环境、预演环境、生产环境中 等不同环境中进行部署,每个环境所对应的参数是不一样的,MyBatis 中可以通过 environment 来设置不同环境的属性。
    • 可通过 SqlSessionFactoryBuilder.build(String environment) 来指定初始化那个环境。

    4. 类型处理器

    • 持久层框架 其中比较重要的工作就是 处理数据 的 映射转换,把 Java类型 转换成 JDBC类型 的参数,又需要把 JDBC类型 的结果集转换成 Java类型。
    • 在 MyBatis 中是通过 TypeHandler接口 来实现的。
    • TypeHandler 两个作用 设置参数 与 获取结果。
      在这里插入图片描述

    • 两种方式指定处理的范围。
    <!-- 类型处理器 -->
    <typeHandlers>
        <typeHandler handler="com.qs.mybatisfast.config.LongTimeHandler" 
        			 javaType="long" jdbcType="TIMESTAMP"/>
    </typeHandlers>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    @MappedJdbcTypes(value = JdbcType.TIMESTAMP, includeNullJdbcType = true)
    @MappedTypes(Long.class)
    public class LongTimeHandler extends BaseTypeHandler<Long> {
    }
    
    • 1
    • 2
    • 3
    • 4

    • 在 resultMap 中指定 typeHandler。
    <!-- 
    1、`javaType属性`:Java类型。
    2、`jdbcType属性`:JDBC类型。
    3、`typeHandler属性`:指定类型处理器。
    -->
    <result property="createTime" javaType="Long"
    		column="create_time" jdbcType="TIMESTAMP"
     		typeHandler="com.qs.mybatisfast.config.LongTimeHandler"/>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5. 映谢器

    <!-- 映谢器 -->
    <!-- 加载`Mapper文件`。-->
    <mappers>
        <!-- 1、`resource属性`:基于`classpath`查找`Mapper文件`。-->
        <mapper resource="mapper/fast.xml"/>
    <!--        <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>-->
        <!-- 2、`url属性`:基于资源定位加载`Mapper文件`。-->
    <!--        <mapper url="http://www.xxx.com/xml/BlogMapper.xml"/>-->
    
        <!-- 3、`class属性`:根据`接口名称`加载`Mapper文件`。
      	2.1、`Mapper映射文件`和`接口`在同一个目录下。
       	2.2、`Mapper映射文件`和`接口`名称一致。
       	2.3、`class`就是接口的权限定名。
       	2.4、`mapper.xml中的namespace`必须与接口名称对应。
       	2.5、通过`class或package`中加载时,`mapper.xml文件`必须与接口在同一级目录。
       	-->
        <!--        <mapper class="com.qs.mybatisfast.mapper.UserMapper"/>-->
    
        <!-- 4、`name属性`:使用`包扫描方式`加载`Mapper文件`。-->
        <package name="com.qs.mybatisfast.mapper"/>
    </mappers>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    三、Mapper文件


    1. SQL语句块 statement

    • 通过 原生JDBC 写 DAO 的年代 ,程序员最怕莫过于 拼接SQL语句(拼接参数 与 设置返回结果集)。
    • Hibernate 将 拼接SQL 时代成为过去,通过 ORM映谢,完全不需要处理任何SQL。但这又带来了新的问题,无法编写 自定义SQL,从而丧失了 灵活活 及 更好的性能。
    • MyBatis 通过 mapper映射SQL 很好解决了这一点。它无需在 JAVA代码 中 拼接SQL,而是将其移至 mapper 文件,集中 处理SQL 节约了大量的开发时间。

    2. Mapper文件中的标签

    • cache:对给定命名空间的缓存配置。
    • resultMap:结果集映射。
    • sql:可被其他语句引用的可重用语句块。
    • insert:插入语句。
    • update:更新语句。
    • delete:删除语句。
    • select:查询语句。

    2.1 select标签 标签及属性

    • 子标签。
    <!ELEMENT select 
    (#PCDATA 
    | include 
    | trim 
    | where 
    | set 
    | foreach 
    | choose 
    | if 
    | bind
    )*>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    • 属性。
    <!ATTLIST select
    <!-- `id属性`:语句块的唯一标识,与接口中方法名称对应。-->
    id CDATA #REQUIRED 
    <!-- `parameterMap属性`:参数映射。-->
    parameterMap CDATA #IMPLIED
    <!-- `parameterType属性`:参数Java类型。-->
    parameterType CDATA #IMPLIED
     <!-- `resultMap属性`:返回结果映射。-->
    resultMap CDATA #IMPLIED
    <!-- `resultType属性`:返回结果Java类型。-->
    resultType CDATA #IMPLIED
    resultSetType (FORWARD_ONLY | SCROLL_INSENSITIVE | SCROLL_SENSITIVE) #IMPLIED
    <!-- `statementType = PREPARED`:执行类型。-->
    statementType (STATEMENT|PREPARED|CALLABLE) #IMPLIED
    fetchSize CDATA #IMPLIED
    <!-- `timeout = 10`-->
    timeout CDATA #IMPLIED
    <!-- `flushCache = true`:每次调用都会`刷新一二级缓存`。-->
    flushCache (true|false) #IMPLIED
    <!-- `useCache = true`:是否保存至`二级缓存`当中去。-->
    useCache (true|false) #IMPLIED
    databaseId CDATA #IMPLIED
    lang CDATA #IMPLIED
    resultOrdered (true|false) #IMPLIED
    resultSets CDATA #IMPLIED 
    >
    
    • 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

    2.2 insert标签 标签及属性

    • 子标签。
    <!ELEMENT insert 
    (#PCDATA 
    | selectKey 
    | include 
    | trim 
    | where 
    | set 
    | foreach 
    | choose 
    | if 
    | bind
    )*>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    • 属性。
    <!ATTLIST insert
    <!-- `id属性`:语句块的唯一标识,与接口中方法名称对应。-->
    id CDATA #REQUIRED
    parameterMap CDATA #IMPLIED
    parameterType CDATA #IMPLIED
    timeout CDATA #IMPLIED
    flushCache (true|false) #IMPLIED
    statementType (STATEMENT|PREPARED|CALLABLE) #IMPLIED
    <!-- 主键对应的Java属性(多个用逗号分割)。-->
    keyProperty CDATA #IMPLIED
    <!-- 插入成功后,将值回设至原参数。-->
    useGeneratedKeys (true|false) #IMPLIED
    <!-- 主键列(多个用逗号分割)。-->
    keyColumn CDATA #IMPLIED
    databaseId CDATA #IMPLIED
    lang CDATA #IMPLIED
    >
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3. 参数映射

    • 参数映射 是最强大功能之一,可以通过以下方式进行引用。
    1. 单个简单参数引用:如果方法中只有一个参数,可通过任意名称进行引用。
    2. 多个简单参数引用:通过参数下标引用 #{arg0}, #{arg1}#{param1}, #{param2}
    3. 对象属性引用:直接通过 属性名称 引用,嵌套对象通过 对象.属性名称 进行引用。
    4. Map key值引用。
    5. 变量名称引用:需要JDK-1.8支持,通过方法中参数名称引用,且在编译时必须加上 -parameters 编译命令。
    • 注意:一旦可以通过 变量名称 引入,将不在支持 arg0获取。

    • 在 IDEA 中添加 编译参数。
      在这里插入图片描述

    • 在 Maven 中添加 编译参数。
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.1 参数引用—相关属性

    <!-- 
    1、`javaType属性`:Java类型。
    2、`jdbcType属性`:JDBC类型。
    3、`typeHandler属性`:指定类型处理器。
    -->
    <result property="createTime" javaType="Long"
    		column="create_time" jdbcType="TIMESTAMP"
     		typeHandler="com.qs.mybatisfast.config.LongTimeHandler"/>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.2 参数拼接

    • 基于 #{参数引用} 其原理是通过 ?占位符,通过预处理能获得 更好的性能 和 安全性(防止SQL注入)。
    • 但有些需求是通过 ?占位符 无法实现的,就需要通过 ${拼接SQL}
    1. 比如:在一些分库分表的场景中,我们需要 动态的拼接表结构。
    2. 比如:某系统日志表 是 按年 进行切割的(2020_log、2021_log)。
    @Select("SELECT * FROM ${table} WHERE id = #{id}")
    User selectByTable(String table, int id);
    
    • 1
    • 2

    4. 结果集映射

    • 结果集映射 是指将 resultSet 中的内容封装转换成 Java对像。
    • 在纯 JDBC时代 全部都是用调用 resultSet的getXxx(columnName) 来获取属性并封装。
      代码量大编程效率低,尤其当数据模型是一对多,或多对多这种复杂关系,这种封装代码将会变得非常复杂。
    • 结果集映射 就是为解决这个问题,通过 resultMap集中处理 结果集 与 Java对像 的关系。

    4.1 结果集自动映射

    • 在 select 中指定 resultType=“” 后无需任何配置。
      MyBatis 会基于 resultType中的Java类型 及 属性,自动推断生成 一个隐示的 resultMap,从而完成结果映射。

    4.2 resultMap标签

    • 但有时候 JDBC 并不是与 Java Bean 完全贴合,这时就需要手动设置 resultMap。
    <!-- `resultMap标签`。
    1、`type属性`返回结果集映射的pojo,可以使用别名。
    -->
    <resultMap type="com.qs.mybatisfast.pojo.Order" id="order_list_result_map">
        <!-- `id标签`:主键的映射。
        1、`property属性`:是`pojo`中`主键属性`。
        2、`column属性`:是`数据库主键列`。
        -->
        <id property="id" column="id"/>
        <!-- `result标签`:普通列映射。
        1、`property`
        2、`jdbcType`
        3、`javaType`
        4、`column`
        5、`typeHandler`
        -->
        <result property="userId" column="user_id"/>
        <result property="money" column="money"/>
        <result property="note" column="note"/>
        <result property="createTime" column="create_time"/>
    </resultMap>
    <select id="getOrderListResultMap" resultMap="order_list_result_map">
        SELECT id, user_id, money, note, create_time
        FROM `order`
    </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

    4.3 resultMap.association标签

    <resultMap type="com.qs.mybatisfast.pojo.Order" id="order_user_result_map">
        <id property="id" column="id"/>
        <result property="userId" column="user_id"/>
        <result property="money" column="money"/>
        <result property="note" column="note"/>
        <result property="createTime" column="create_time"/>
        <!-- `association标签`:配置`一对一`关联映射。
        1、`property属性`:对于`order`中的`user属性`。
        2、`javaType属性`:是`user属性`的`数据类型`
        -->
        <association property="user" column="user_id" javaType="com.qs.mybatisfast.pojo.User">
            <id property="id" column="user_id"/>
            <result property="username" column="username"/>
            <result property="address" column="address"/>
        </association>
    </resultMap>
    
    <select id="getOrderUserResultMap" resultMap="order_user_result_map">
        SELECT o.id,
               o.user_id,
               o.money,
               o.note,
               o.create_time,
               u.username,
               u.address
        FROM `order` o
                 LEFT JOIN `user` u ON u.id = o.user_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
    • 26
    • 27
    • 28

    <resultMap type="com.qs.mybatisfast.pojo.Order" id="order_user_result_map">
        <id property="id" column="id"/>
        <result property="userId" column="user_id"/>
        <result property="money" column="money"/>
        <result property="note" column="note"/>
        <result property="createTime" column="create_time"/>
    	<!-- 一对一 -->
        <association property="user" javaType="com.qs.mybatisfast.pojo.User"
        			 column="user_id" select="getUserById">
        </association>
    </resultMap>
    
    <select id="getOrderUserResultMap" resultMap="order_user_result_map">
        SELECT id, user_id, money, note, create_time
    	FROM `order`
    </select>
    
    <select id="getUserById" parameterType="int" resultType="com.qs.mybatisfast.pojo.User">
        SELECT *
        FROM `user`
        WHERE 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

    4.3 resultMap.collection标签

    <resultMap type="com.qs.mybatisfast.pojo.User" id="user_order_result_map">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="sex" column="sex"/>
        <result property="birthday" column="birthday"/>
        <result property="address" column="address"/>
        <!-- `collection标签`:配置`一对多`关联映射。
        1、`property属性`:对于`user对象`中的`集合属性`。
        2、`ofType属性`:集合中每个元素的数据类型。
        -->
        <collection notNullColumn="oid" property="orders" javaType="java.util.List"
                    ofType="com.qs.mybatisfast.pojo.Order">
            <!-- id对于order的主键属性 -->
            <id property="id" column="oid"/>
            <result property="money" column="money"/>
            <result property="note" column="note"/>
            <result property="createTime" column="create_time"/>
        </collection>
    </resultMap>
    
    <select id="getUserWithOrders" resultMap="user_order_result_map">
        SELECT u.id,
               u.username,
               u.sex,
               u.birthday,
               u.address,
               o.id AS oid,
               o.money,
               o.note,
               o.create_time
        FROM `user` u
                 LEFT JOIN `order` o ON o.user_id = u.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
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
  • 相关阅读:
    Ubuntu22.2下C语言编程实现,首次,最佳适应算法
    Linux中“EXT 类型文件恢复与xfs 类型文件备份和恢复”
    Java迭代器 & for循环的区别
    C语言入门(五)分支结构
    uni微信小程序隐私协议
    Vue3+ECharts
    图片添加边框和文字怎么弄?图片编辑在线教学
    快速弄懂C++中的深拷贝和浅拷贝
    Linux 5.19内核终于接纳了Zstd压缩固件更新
    基于Stable Diffusion的AIGC服饰穿搭实践
  • 原文地址:https://blog.csdn.net/qq_38667427/article/details/125482735