主頁 > 後端開發 > Mybatis

Mybatis

2023-02-16 07:17:15 後端開發

第一章 初識Mybatis

1.1 框架概述

  • 生活中“框架”

    • 買房子
    • 筆記本電腦
  • 程式中框架【代碼半成品】

    • Mybatis框架:持久化層框架【dao層】
    • SpringMVC框架:控制層框架【Servlet層】
    • Spring框架:全能...

1.2 Mybatis簡介

  • Mybatis是一個半自動化持久化層ORM框架

  • ORM:Object Relational Mapping【物件 關系 映射】

    • 將Java中的物件與資料庫中建議映射關系,優勢:操作Java中的物件,就可以影響資料庫中表的資料
  • Mybatis與Hibernate對比

    • Mybatis是一個半自動化【需要手寫SQL】
    • Hibernate是全自動化【無需手寫SQL】
  • Mybatis與JDBC對比

    • JDBC中的SQL與Java代碼耦合度高
    • Mybatis將SQL與Java代碼解耦
  • Java POJO(Plain Old Java Objects,普通老式 Java 物件)

    • JavaBean 等同于 POJO

1.3 官網地址

  • 檔案地址:https://mybatis.org/mybatis-3/
  • 原始碼地址:https://github.com/mybatis/mybatis-3

第二章 搭建Mybatis框架

匯入jar包

撰寫組態檔

使用核心類別庫

2.1 準備

  • 建庫建表建約束
  • 準備maven工程

2.2 搭建Mybatis框架步驟

  1. 匯入jar包

    <!--匯入MySQL的驅動包-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.37</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.26</version>
    </dependency>
    
    <!--匯入MyBatis的jar包-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <!--junit-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    
  2. 撰寫核心組態檔【mybatis-config.xml】

    • 位置:resources目標下

    • 名稱:推薦使用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>
          <environments default="development">
              <environment id="development">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
      <!--                mysql8版本-->
      <!--                <property name="driver" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/com.mysql.cj.jdbc.Driver"/>-->
      <!--                <property name="url" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/jdbc:mysql://localhost:3306/db220106?serverTimezone=UTC"/>-->
      <!--                mysql5版本-->
                      <property name="driver" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/com.mysql.jdbc.Driver"/>
                      <property name="url" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/jdbc:mysql://localhost:3306/db220106"/>
                      <property name="username" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/root"/>
                      <property name="password" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/root"/>
                  </dataSource>
              </environment>
          </environments>
          <!--    設定映射檔案路徑-->
          <mappers>
              <mapper resource="mapper/EmployeeMapper.xml"/>
          </mappers>
      </configuration>
      
  3. 書寫相關介面及映射檔案

    • 映射檔案位置:resources/mapper

    • 映射檔案名稱:XXXMapper.xml

    • 映射檔案作用:主要作用為Mapper介面書寫Sql陳述句

      • 映射檔案名與介面名一致
      • 映射檔案namespace與介面全類名一致
      • 映射檔案SQL的Id與介面的方法名一致
    • 示例代碼

      <?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.atguigu.mybatis.mapper.EmployeeMapper">
          <select id="selectEmpById" resultType="com.atguigu.mybatis.pojo.Employee">
              SELECT
                  id,
                  last_name,
                  email,
                  salary
              FROM
                  tbl_employee
              WHERE
                  id=#{empId}
          </select>
      </mapper>
      
  4. 測驗【SqlSession】

    • 先獲取SqlSessionFactory物件
    • 再獲取SqlSession物件
    • 通過SqlSession物件獲取XXXMapper代理物件
    • 測驗

2.3 添加Log4j日志框架

  • 匯入jar包

    <!-- log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    
  • 撰寫組態檔

    • 組態檔名稱:log4j.xml

    • 組態檔位置:resources

    • 示例代碼

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
      
      <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
      
          <appender name="STDOUT" >
              <param name="Encoding" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/UTF-8" />
              <layout >
                  <param name="ConversionPattern" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/%-5p %d{MM-dd HH:mm:ss,SSS} %m  (%F:%L) /n" />
              </layout>
          </appender>
          <logger name="java.sql">
              <level value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/debug" />
          </logger>
          <logger name="org.apache.ibatis">
              <level value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/info" />
          </logger>
          <root>
              <level value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/debug" />
              <appender-ref ref="STDOUT" />
          </root>
      </log4j:configuration>
      

第三章 Mybatis核心配置詳解【mybatis-config.xml】

3.1 核心組態檔概述

  • MyBatis 的組態檔包含了會深深影響 MyBatis 行為的設定和屬性資訊,

3.2 核心組態檔根標簽

  • 沒有實際語意,主要作用:所有子標簽均需要設定在跟標簽內部

3.3 核心組態檔常用子標簽

  • properties子標簽

    • 作用:定義或引入外部屬性檔案

    • 示例代碼

      #key=value
      db.driver=com.mysql.jdbc.Driver
      db.url=jdbc:mysql://localhost:3306/db220106
      db.username=root
      db.password=root
      
      <properties resource="db.properties"></properties>
      
      <environments default="development">
              <environment id="development">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
      <!--                mysql8版本-->
      <!--                <property name="driver" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/com.mysql.cj.jdbc.Driver"/>-->
      <!--                <property name="url" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/jdbc:mysql://localhost:3306/db220106?serverTimezone=UTC"/>-->
      <!--                mysql5版本-->
                      <property name="driver" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/${db.driver}"/>
                      <property name="url" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/${db.url}"/>
                      <property name="username" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/${db.username}"/>
                      <property name="password" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/${db.password}"/>
                  </dataSource>
              </environment>
          </environments>
      
  • settings子標簽

    • 作用:這是 MyBatis 中極為重要的調整設定,它們會改變 MyBatis 的運行時行為,

    • mapUnderscoreToCamelCase屬性:是否開啟駝峰命名自動映射,默認值false,如設定true會自動將

      欄位a_col與aCol屬性自動映射

      • 注意:只能將字母相同的欄位與屬性自動映射
  • 型別別名(typeAliases)

    • 作用:型別別名可為 Java 型別設定一個縮寫名字,

    • 語法及特點

      <typeAliases>
      <!--        為指定型別定義別名-->
      <!--        <typeAlias type="com.atguigu.mybatis.pojo.Employee" alias="employee"></typeAlias>-->
      <!--        為指定包下所有的類定義別名
                      默認將類名作為別名,不區分大小寫【推薦使用小寫字母】
      -->
              <package name="com.atguigu.mybatis.pojo"/>
          </typeAliases>
      
    • Mybatis自定義別名

      別名 型別
      _int int
      integer或int Integer
      string String
      list或arraylist ArrayList
      map或hashmap HashMap
  • 環境配置(environments)

    • 作用:設定資料庫連接環境

    • 示例代碼

      <!--    設定資料庫連接環境-->
          <environments default="development">
              <environment id="development">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
      <!--                mysql8版本-->
      <!--                <property name="driver" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/com.mysql.cj.jdbc.Driver"/>-->
      <!--                <property name="url" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/jdbc:mysql://localhost:3306/db220106?serverTimezone=UTC"/>-->
      <!--                mysql5版本-->
                      <property name="driver" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/${db.driver}"/>
                      <property name="url" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/${db.url}"/>
                      <property name="username" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/${db.username}"/>
                      <property name="password" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/${db.password}"/>
                  </dataSource>
              </environment>
          </environments>
      
  • mappers子標簽

    • 作用:設定映射檔案路徑

    • 示例代碼

      <!--    設定映射檔案路徑-->
          <mappers>
              <mapper resource="mapper/EmployeeMapper.xml"/>
              <!-- 要求:介面的包名與映射檔案的包名需要一致-->
      <!--        <package name="com.atguigu.mybatis.mapper"/>-->
          </mappers>
      
  • 注意:核心配置中的子標簽,是有順序要求的,

image

第四章 Mybatis映射檔案詳解

4.1 映射檔案概述

  • MyBatis 的真正強大在于它的陳述句映射,這是它的魔力所在,
  • 如果拿它跟具有相同功能的 JDBC 代碼進行對比,你會立即發現省掉了將近 95% 的代碼,

4.2 映射檔案根標簽

  • mapper標簽
  • mapper中的namespace要求與介面的全類名一致

4.3 映射檔案子標簽

子標簽共有9個,注意學習其中8大子標簽

  • insert標簽:定義添加SQL
  • delete標簽:定義洗掉SQL
  • update標簽:定義修改SQL
  • select標簽:定義查詢SQL
  • sql標簽:定義可重用的SQL陳述句塊
  • cache標簽:設定當前命名空間的快取配置
  • cache-ref標簽:設定其他命名空間的快取配置
  • resultMap標簽:描述如何從資料庫結果集中加載物件
    • resultType解決不了的問題,交個resultMap,

4.4 映射檔案中常用屬性

  • resultType:設定期望結果集回傳型別【全類名或別名】
    • 注意:如果回傳的是集合,那應該設定為集合包含的型別,而不是集合本身的型別,
    • resultType 和 resultMap 之間只能同時使用一個,

4.5 獲取主鍵自增資料

  • useGeneratedKeys:啟用主鍵生成策略
  • keyProperty:設定存盤屬性值

4.6 獲取資料庫受影響行數

  • 直接將介面中方法的回傳值設定為int或boolean即可
    • int:代表受影響行數
    • boolean
      • true:表示對資料庫有影響
      • false:表示對資料庫無影響

第五章 Mybatis中引數傳遞問題

5.1 單個普通引數

  • 可以任意使用:引數資料型別、引數名稱不用考慮

5.2 多個普通引數

  • Mybatis底層封裝Map結構,封裝key為param1、param2....【支持:arg0、arg1、...】

5.3 命名引數

  • 語法:

    • @Param(value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/引數名")
    • @Param("引數名")
  • 位置:引數前面

  • 注意:

    • 底層封裝Map結構
    • 命名引數,依然支持引數【param1,param2,...】
  • 示例代碼

    /**
     * 通過員工姓名及薪資查詢員工資訊【命名引數】
     * @return
     */
    public List<Employee> selectEmpByNamed(@Param("lName")String lastName,
                                           @Param("salary") double salary);
    
    <select id="selectEmpByNamed" resultType="employee">
        SELECT
            id,
            last_name,
            email,
            salary
        FROM
            tbl_employee
        WHERE
            last_name=#{param1}
        AND
            salary=#{param2}
    </select>
    
  • 原始碼分析

    • MapperMethod物件:142行代碼【命名引數底層代碼入口】

    • 命名引數底層封裝map為ParamMap,ParamMap繼承HashMap

    • ParamNameResolver物件:130行代碼,命名引數底層實作邏輯

      //130行
      final Map<String, Object> param = new ParamMap<>();
      int i = 0;
      for (Map.Entry<Integer, String> entry : names.entrySet()) {
        param.put(entry.getValue(), args[entry.getKey()]);
        // add generic param names (param1, param2, ...)
        final String genericParamName = GENERIC_NAME_PREFIX + (i + 1);
        // ensure not to overwrite parameter named with @Param
        if (!names.containsValue(genericParamName)) {
          param.put(genericParamName, args[entry.getKey()]);
        }
        i++;
      }
      return param;
      

5.4 POJO引數

  • Mybatis支持POJO【JavaBean】入參,引數key是POJO中屬性

5.5 Map引數

  • Mybatis支持直接Map入參,map的key=引數key

5.6 Collection|List|Array等引數

  • 引數名:collection、list、array

第六章 Mybatis引數傳遞【#與$區別】

6.1 回顧JDBC

  • DriverManager
  • Connection
  • Statement:執行SQL陳述句,入參使用SQL【String】拼接方式
  • PreparedStatement執行SQL陳述句【預編譯SQL】,入參使用占位符方式
  • ResultSet

6.2 #與$區別

  • 【#】底層執行SQL陳述句的物件,使用PreparedStatementd,預編譯SQL,防止SQL注入安全隱患,相對比較安全,
  • 【$】底層執行SQL陳述句的物件使用Statement物件,未解決SQL注入安全隱患,相對不安全,

6.3 #與$使用場景

查詢SQL:select col,col2 from table1 where col=? and col2=? group by ?, order by ? limit ?,?

  • 使用場景,sql占位符位置均可以使用#

  • $使用場景,#解決不了的引數傳遞問題,均可以交給$處理【如:form 動態化表名】

    /**
     * 測驗$使用場景
     */
    public List<Employee> selectEmpByDynamitTable(@Param("tblName") String tblName);
    
    <select id="selectEmpByDynamitTable" resultType="employee">
        SELECT
            id,
            last_name,
            email,
            salary
        FROM
            ${tblName}
    </select>
    

第七章 Mybatis查詢中回傳值四種情況

7.1 查詢單行資料回傳單個物件

/**
 * 通過id獲取員工資訊
 */
public Employee selectEmpById(int empId);
<select id="selectEmpById" resultType="employee">
    SELECT
        id,
        last_name,
        email,
        salary
    FROM
        tbl_employee
    WHERE
        id=#{empId}
</select>

7.2 查詢多行資料回傳物件的集合

/**
 * 查詢所有員工資訊
 */
public List<Employee> selectAllEmps();
<select id="selectAllEmps" resultType="employee">
    SELECT
        id,
        last_name,
        email,
        salary
    FROM
        tbl_employee
</select>
  • 注意:如果回傳的是集合,那應該設定為集合包含的型別,而不是集合本身的型別,

7.3 查詢單行資料回傳Map集合

  • Map<String key,Object value>

    • 欄位作為Map的key,查詢結果作為Map的Value
  • 示例代碼

    /**
     * 查詢單行資料回傳Map集合
     * @return
     */
    public Map<String,Object> selectEmpReturnMap(int empId);
    
    <!--    查詢單行資料回傳Map集合-->
    <select id="selectEmpReturnMap" resultType="map">
        SELECT
            id,
            last_name,
            email,
            salary
        FROM
        	tbl_employee
        WHERE
        	id=#{empId}
    </select>
    

7.4 查詢多行資料回傳Map集合

  • Map<Integer key,Employee value>

    • 物件的id作為key
    • 物件作為value
  • 示例代碼

    /**
     * 查詢多行資料回傳Map
     * Map<Integer,Object>
     * Map<Integer,Employee>
     *      物件Id作為:key
     *      物件作為:value
     * @return
     */
    @MapKey("id")
    public Map<Integer,Employee> selectEmpsReturnMap();
    
    <select id="selectEmpsReturnMap" resultType="map">
        SELECT
            id,
            last_name,
            email,
            salary
        FROM
            tbl_employee
    </select>
    

第八章 Mybatis中自動映射與自定義映射

自動映射【resultType】

自定義映射【resultMap】

8.1 自動映射與自定義映射

  • 自動映射【resultType】:指的是自動將表中的欄位與類中的屬性進行關聯映射
    • 自動映射解決不了兩類問題
      • 多表連接查詢時,需要回傳多張表的結果集
      • 單表查詢時,不支持駝峰式自動映射【不想為欄位定義別名】
  • 自定義映射【resultMap】:自動映射解決不了問題,交給自定義映射
  • 注意:resultType與resultMap只能同時使用一個

8.2 自定義映射-級聯映射

<!--    自定義映射 【員工與部門關系】-->
<resultMap id="empAndDeptResultMap" type="employee">
    <!--  定義主鍵欄位與屬性關聯關系 -->
    <id column="id" property="id"></id>
    <!--  定義非主鍵欄位與屬性關聯關系-->
    <result column="last_name" property="lastName"></result>
    <result column="email" property="email"></result>
    <result column="salary" property="salary"></result>
    <!--        為員工中所屬部門,自定義關聯關系-->
    <result column="dept_id" property="dept.deptId"></result>
    <result column="dept_name" property="dept.deptName"></result>
</resultMap>
<select id="selectEmpAndDeptByEmpId" resultMap="empAndDeptResultMap">
   SELECT
        e.`id`,
        e.`email`,
        e.`last_name`,
        e.`salary`,
        d.`dept_id`,
        d.`dept_name`
    FROM
        tbl_employee e,
        tbl_dept d
    WHERE
        e.`dept_id` = d.`dept_id`
    AND
        e.`id` = #{empId}
</select>

8.3 自定義映射-association映射

  • 特點:解決一對一映射關系【多對一】

  • 示例代碼

    • <!--    自定義映射 【員工與部門關系】-->
      <resultMap id="empAndDeptResultMapAssociation" type="employee">
          <!--  定義主鍵欄位與屬性關聯關系 -->
          <id column="id" property="id"></id>
          <!--  定義非主鍵欄位與屬性關聯關系-->
          <result column="last_name" property="lastName"></result>
          <result column="email" property="email"></result>
          <result column="salary" property="salary"></result>
          <!--        為員工中所屬部門,自定義關聯關系-->
          <association property="dept"
                      javaType="com.atguigu.mybatis.pojo.Dept">
              <id column="dept_id" property="deptId"></id>
              <result column="dept_name" property="deptName"></result>
          </association>
      </resultMap>
      

8.4 自定義映射-collection映射

  • 示例代碼

    /**
     * 通過部門id獲取部門資訊,及部門所屬員工資訊
     */
    public Dept selectDeptAndEmpByDeptId(int deptId);
    
    <resultMap id="deptAndempResultMap" type="dept">
        <id property="deptId" column="dept_id"></id>
        <result property="deptName" column="dept_name"></result>
        <collection property="empList"
                    ofType="com.atguigu.mybatis.pojo.Employee">
            <id column="id" property="id"></id>
            <result column="last_name" property="lastName"></result>
            <result column="email" property="email"></result>
            <result column="salary" property="salary"></result>
        </collection>
    </resultMap>
    <select id="selectDeptAndEmpByDeptId" resultMap="deptAndempResultMap">
        SELECT
            e.`id`,
            e.`email`,
            e.`last_name`,
            e.`salary`,
            d.`dept_id`,
            d.`dept_name`
        FROM
            tbl_employee e,
            tbl_dept d
        WHERE
            e.`dept_id` = d.`dept_id`
        AND
            d.dept_id = #{deptId}
    </select>
    

8.5 ResultMap相關標簽及屬性

  • resultMap標簽:自定義映射標簽

    • id屬性:定義唯一標識
    • type屬性:設定映射型別
  • resultMap子標簽

    • id標簽:定義主鍵欄位與屬性關聯關系
    • result標簽:定義非主鍵欄位與屬性關聯關系
      • column屬性:定義表中欄位名稱
      • property屬性:定義類中屬性名稱
    • association標簽:定義一對一的關聯關系
      • property:定義關聯關系屬性
      • javaType:定義關聯關系屬性的型別
      • select:設定分步查詢SQL全路徑
      • colunm:設定分步查詢SQL中需要引數
      • fetchType:設定區域延遲加載【懶加載】是否開啟
    • collection標簽:定義一對多的關聯關系
      • property:定義一對一關聯關系屬性
      • ofType:定義一對一關聯關系屬性型別
      • fetchType:設定區域延遲加載【懶加載】是否開啟

8.6 Mybatis中分步查詢

  • 為什么使用分步查詢【分步查詢優勢】?

    • 將多表連接查詢,改為【分步單表查詢】,從而提高程式運行效率
  • 示例代碼

    • 一對一

      /**
       * 通過員工id獲取員工資訊及員工所屬的部門資訊【分步查詢】
              1. 先通過員工id獲取員工資訊【id、last_name、email、salary、dept_id】
              2. 再通過部門id獲取部門資訊【dept_id、dept_name】
       */
      public Employee selectEmpAndDeptByEmpIdAssociationStep(int empId);
      
      <select id="selectEmpAndDeptByEmpIdAssociationStep" resultMap="empAndDeptResultMapAssocationStep">
          select
              id,
              last_name,
              email,
              salary,
              dept_id
          from
              tbl_employee
          where
              id=#{empId}
      </select>
      
      /**
       * 通過部門id獲取部門資訊
       */
      public Dept selectDeptByDeptId(int deptId);
      
      <select id="selectDeptByDeptId" resultType="dept">
          select
              dept_id,
              dept_name
          from
              tbl_dept
          where
              dept_id=#{deptId}
      </select>
      
  • 一對多

    /**
     * 通過部門id獲取部門資訊,及部門所屬員工資訊【分步查詢】
            1. 通過部門id獲取部門資訊
            2. 通過部門id獲取員工資訊
     */
    public Dept selectDeptAndEmpByDeptIdStep(int deptId);
    
    <!--    通過部門id獲取部門資訊,及部門所屬員工資訊【分步查詢】-->
    <!--    1. 通過部門id獲取部門資訊-->
    <!--    2. 通過部門id獲取員工資訊-->
        <select id="selectDeptAndEmpByDeptIdStep" resultMap="deptAndEmpResultMapStep">
            select
                dept_id,
                dept_name
            from
                tbl_dept
            where
                dept_id=#{deptId}
        </select>
    
    /**
     * 通過部門Id獲取員工資訊
     * @param deptId
     * @return
     */
    public List<Employee> selectEmpByDeptId(int deptId);
    
    <select id="selectEmpByDeptId" resultType="employee">
        select
            id,
            last_name,
            email,
            salary,
            dept_id
        from
            tbl_employee
        where
            dept_id=#{deptId}
    </select>
    

8.7 Mybatis延遲加載【懶加載】

  • 需要時加載,不需要暫時不加載

  • 優勢:提升程式運行效率

  • 語法

    • 全域設定

      <!-- 開啟延遲加載 -->
      <setting name="lazyLoadingEnabled" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/true"/>
      <!-- 設定加載的資料是按需加載3.4.2及以后的版本該步驟可省略-->
      <setting name="aggressiveLazyLoading" value="https://www.cnblogs.com/ygstudy/archive/2023/02/15/false"/>
      
    • 區域設定

      • fetchType

        • eager:關閉區域延遲加載
        • lazy:開啟區域延遲加載
      • 示例代碼

        <association property="dept"
                    select="com.atguigu.mybatis.mapper.DeptMapper.selectDeptByDeptId"
                    column="dept_id"
                    fetchType="eager">
        </association>
        

8.8 擴展

  • 如果分步查詢時,需要傳遞給呼叫的查詢中多個引數,則需要將多個引數封裝成

    Map來進行傳遞,語法如下: {k1=v1, k2=v2....}

第九章 Mybatis動態SQL【重點】

SQL中注釋

//方式一
-- 1=1
//方式二【推薦使用】
 <!-- 1=1 -->

9.1 動態SQL概述

  • 動態SQL指的是:SQL陳述句可動態化
  • Mybatis的動態SQL中支持OGNL運算式語言,OGNL( Object Graph Navigation Language )物件圖導航語言

9.2 常用標簽

  • if標簽:用于完成簡單的判斷

  • where標簽:用于解決where關鍵字及where后第一個and或or的問題

  • trim標簽: 可以在條件判斷完的SQL陳述句前后添加或者去掉指定的字符

    • prefix: 添加前綴

    • prefixOverrides: 去掉前綴

    • suffix: 添加后綴

    • suffixOverrides: 去掉后綴

  • set標簽:主要用于解決set關鍵字及多出一個【,】問題

  • choose標簽:類似java中if-else【switch-case】結構

  • foreach標簽:類似java中for回圈

    • collection: 要迭代的集合
    • item: 當前從集合中迭代出的元素
    • separator: 元素與元素之間的分隔符
    • open: 開始字符
    • close:結束字符
  • sql標簽:提取可重用SQL片段

9.3 示例代碼

<?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.atguigu.mybatis.mapper.EmployeeMapper">
    <sql id="emp_col">
        id,
        last_name,
        email,
        salary
    </sql>
    <sql id="select_employee">
        select
            id,
            last_name,
            email,
            salary
        from
            tbl_employee
    </sql>
<!-- 按條件查詢員工資訊【條件不確定】-->
    <select id="selectEmpByOpr" resultType="employee">
        <include refid="select_employee"></include>
        <where>
            <if test="id != null">
               and id = #{id}
            </if>
            <if test="lastName != null">
                and last_name = #{lastName}
            </if>
            <if test="email != null">
                and email = #{email}
            </if>
            <if test="salary != null">
                and salary = #{salary}
            </if>
        </where>
    </select>

    <select id="selectEmpByOprTrim" resultType="employee">
        <include refid="select_employee"></include>
        <trim prefix="where" suffixOverrides="and">
            <if test="id != null">
                id = #{id} and
            </if>
            <if test="lastName != null">
                last_name = #{lastName} and
            </if>
            <if test="email != null">
                email = #{email} and
            </if>
            <if test="salary != null">
                salary = #{salary}
            </if>
        </trim>
    </select>

    <update id="updateEmpByOpr">
        update
            tbl_employee
        <set>
            <if test="lastName != null">
                last_name=#{lastName},
            </if>
            <if test="email != null">
                email=#{email},
            </if>
            <if test="salary != null">
                salary=#{salary}
            </if>
        </set>
        where
            id = #{id}
    </update>


    <select id="selectEmpByOneOpr" resultType="employee">
        select
            <include refid="emp_col"></include>
        from
            tbl_employee
        <where>
            <choose>
                <when test="id != null">
                    id = #{id}
                </when>
                <when test="lastName != null">
                    last_name = #{lastName}
                </when>
                <when test="email != null">
                    email = #{email}
                </when>
                <when test="salary != null">
                    salary = #{salary}
                </when>
                <otherwise>
                    1=1
                </otherwise>
            </choose>
        </where>
    </select>

    <select id="selectEmpByIds" resultType="employee">
        select
            id,
            last_name,
            email,
            salary
        from
            tbl_employee
        <where>
            id in(
            <foreach collection="ids" item="id" separator=",">
                #{id}
            </foreach>
            )
        </where>

    </select>

    <insert id="batchInsertEmp">
        INSERT INTO
            tbl_employee(last_name,email,salary)
        VALUES
            <foreach collection="employees" item="emp" separator=",">
                (#{emp.lastName},#{emp.email},#{emp.salary})
            </foreach>
    </insert>
</mapper>

第十章 Mybatis中快取機制

10.1 快取概述

  • 生活中快取
    • 快取一些音頻、視頻優勢
      • 節約資料流量
      • 提高播放性能
  • 程式中快取【Mybatis快取】
    • 使用快取優勢
      • 提高查詢效率
      • 降低服務器壓力

10.2 Mybatis中的快取概述

  • 一級快取

  • 二級快取

  • 第三方快取

image

10.3 Mybatis快取機制之一級快取

  • 概述:一級快取【本地快取(Local Cache)或SqlSession級別快取】

  • 特點

    • 一級快取默認開啟
    • 不能關閉
    • 可以清空
  • 快取原理

    • 第一次獲取資料時,先從資料庫中加載資料,將資料快取至Mybatis一級快取中【快取底層實作原理Map,key:hashCode+查詢的SqlId+撰寫的sql查詢陳述句+引數】
    • 以后再次獲取資料時,先從一級快取中獲取,如未獲取到資料,再從資料庫中獲取資料,
  • 一級快取五種失效情況

    1. 不同的SqlSession對應不同的一級快取

    2. 同一個SqlSession但是查詢條件不同

    3. 同一個SqlSession兩次查詢期間執行了任何一次增刪改操作

    • 清空一級快取
    1. 同一個SqlSession兩次查詢期間手動清空了快取
    • sqlSession.clearCache()
    1. 同一個SqlSession兩次查詢期間提交了事務
    • sqlSession.commit()

10.4 Mybatis快取機制之二級快取

  • 二級快取【second level cache】概述

    • 二級快取【全域作用域快取】
    • SqlSessionFactory級別快取
  • 二級快取特點

    • 二級快取默認關閉,需要開啟才能使用
    • 二級快取需要提交sqlSession或關閉sqlSession時,才會快取,
  • 二級快取使用的步驟:

    ① 全域組態檔中開啟二級快取

    ② 需要使用二級快取的映射檔案處使用cache配置快取

    ③ 注意:POJO需要實作Serializable介面

image

關閉sqlSession或提交sqlSession時,將資料快取到二級快取

  • 二級快取底層原理

    • 第一次獲取資料時,先從資料庫中獲取資料,將資料快取至一級快取;當提交或關閉SqlSession時,將資料快取至二級快取
    • 以后再次獲取資料時,先從一級快取中獲取資料,如一級快取沒有指定資料,再去二級快取中獲取資料,如二級快取也沒有指定資料時,需要去資料庫中獲取資料,......
  • 二級快取相關屬性

    • eviction=“FIFO”:快取清除【回收】策略,
      • LRU – 最近最少使用的:移除最長時間不被使用的物件,
      • FIFO – 先進先出:按物件進入快取的順序來移除它們,
    • flushInterval:重繪間隔,單位毫秒
    • size:參考數目,正整數
    • readOnly:只讀,true/false
  • 二級快取的失效情況

    • 在兩次查詢之間,執行增刪改操作,會同時清空一級快取和二級快取
    • sqlSession.clearCache():只是用來清除一級快取,

10.5 Mybatis中快取機制之第三方快取

  • 第三方快取:EhCache

  • EhCache 是一個純Java的行程內快取框架

  • 使用步驟

    • 匯入jar包

      <!-- mybatis-ehcache -->
      <dependency>
          <groupId>org.mybatis.caches</groupId>
          <artifactId>mybatis-ehcache</artifactId>
          <version>1.0.3</version>
      </dependency>
      
      <!-- slf4j-log4j12 -->
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-log4j12</artifactId>
          <version>1.6.2</version>
          <scope>test</scope>
      </dependency>
      
    • 撰寫組態檔【ehcache.xml】

      <?xml version="1.0" encoding="UTF-8"?>
      <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
          <!-- 磁盤保存路徑 -->
          <diskStore path="E:\mybatis\ehcache" />
      
          <defaultCache
                  maxElementsInMemory="512"
                  maxElementsOnDisk="10000000"
                  eternal="false"
                  overflowToDisk="true"
                  timeToIdleSeconds="120"
                  timeToLiveSeconds="120"
                  diskExpiryThreadIntervalSeconds="120"
                  memoryStoreEvictionPolicy="LRU">
          </defaultCache>
      </ehcache>
      
    • 加載第三方快取【映射檔案】

    • 開始使用

  • 注意事項

    • 第三方快取,需要建立在二級快取基礎上【需要開啟二級快取,第三方快取才能生效】
    • 如何讓第三方快取失效【將二級快取設定失效即可】

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543983.html

標籤:其他

上一篇:資料型別之字串、資料型別之串列、資料型別之字典、資料型別之布林值、資料型別之元組、資料型別之集合、與用戶互動、格式化輸出、基本運算子

下一篇:集合

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more