MyBatis快速上手與知識點總結

来源:https://www.cnblogs.com/dandelion-000-blog/archive/2022/08/29/16636393.html
-Advertisement-
Play Games

閱讀提示: 本文預設已經預裝預裝maven 1、MyBatis概述 1.1 MyBatis概述 持久層框架,用於簡化JDBC開發,是對JDBC的封裝 持久層: 負責將數據保存到資料庫的代碼部分 Java EE三層架構:表現層、業務層、持久層 1.2 JDBC缺點 硬編碼,不利於維護 註冊驅動、獲取連 ...


目錄


閱讀提示:

本文預設已經預裝預裝maven

1、MyBatis概述

1.1 MyBatis概述

  • 持久層框架,用於簡化JDBC開發,是對JDBC的封裝

    持久層:

    • 負責將數據保存到資料庫的代碼部分
    • Java EE三層架構:表現層、業務層、持久層

1.2 JDBC缺點

  • 硬編碼,不利於維護
    • 註冊驅動、獲取連接
    • SQL語句
  • 操作繁瑣
    • 手動設置參數
    • 手動封裝結果集

1.3 MyBatis優化

  • 硬編碼 --> 配置文件
  • 繁瑣慚怍 --> 框架封裝自動完成

2、MyBatis快速入門

  • 需求:查詢user表中的所有數據

  • SQL

    create database mybatis;
    use mybatis;
    
    drop table if exists tb_user;
    
    create table tb_user(
    	id int primary key auto_increment,
    	username varchar(20),
    	password varchar(20),
    	gender char(1),
    	addr varchar(30)
    );
    
    INSERT INTO tb_user VALUES (1, 'zhangsan', '123', '男', '北京');
    INSERT INTO tb_user VALUES (2, '李四', '234', '女', '天津');
    INSERT INTO tb_user VALUES (3, '王五', '11', '男', '西安');
    
  • 代碼實現

    • 創建模塊,導入坐標

      在pom.xml中配置文件中添加依賴的坐標

      註意:需要在項目的resources目錄下創建logback的配置文件

      <dependencies>
          <!--mybatis 依賴-->
          <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis</artifactId>
              <version>3.5.5</version>
          </dependency>
          <!--mysql 驅動-->
          <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>5.1.46</version>
          </dependency>
          <!--junit 單元測試-->
          <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.13</version>
              <scope>test</scope>
          </dependency>
          <!-- 添加slf4j日誌api -->
          <dependency>
              <groupId>org.slf4j</groupId>
              <artifactId>slf4j-api</artifactId>
              <version>1.7.20</version>
          </dependency>
          <!-- 添加logback-classic依賴 -->
          <dependency>
              <groupId>ch.qos.logback</groupId>
              <artifactId>logback-classic</artifactId>
              <version>1.2.3</version>
          </dependency>
          <!-- 添加logback-core依賴 -->
          <dependency>
              <groupId>ch.qos.logback</groupId>
              <artifactId>logback-core</artifactId>
              <version>1.2.3</version>
          </dependency>
      </dependencies>
      
    • 編寫MyBatis核心文件

      核心文件用於替換信息,解決硬編碼問題

      在模塊下的resources目錄下創建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>
          <environments default="development">
              <environment id="development">
                  <!-- 採用JDBC的事務管理方式 -->
                  <transactionManager type="JDBC"/>
                  <!-- 資料庫連接信息 -->
                  <dataSource type="POOLED">
                      <property name="driver" value="com.mysql.jdbc.Driver"/>
                      <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                      <property name="username" value="root"/>
                      <property name="password" value="123456"/>
                  </dataSource>
              </environment>
          </environments>
          <!-- 載入SQL映射文件 -->
          <mappers>
              <mapper resource="UserMapper.xml"/>
          </mappers>
      </configuration>
      
    • 編寫SQL映射文件

      SQL映射文件用於統一管理SQL語句,解決硬編碼問題

      在模塊的resources目錄下創建映射配置文件UserMaooer.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">
      <!--
          namespace:命名空間
      -->
      <mapper namespace="test">
          <!-- statement -->
          <select id="selectAll" resultType="priv.dandelion.entity.User">
              select * from tb_user;
          </select>
      </mapper>
      
    • 編碼

      • 實體類

        package priv.dandelion.entity;
        
        public class User {
        
            private Integer id;
            private String username;
            private String password;
            private String gender;
            private String address;
        
            public User() {
            }
        
            public User(Integer id, String username, String password, String gender, String address) {
                this.id = id;
                this.username = username;
                this.password = password;
                this.gender = gender;
                this.address = address;
            }
        
            public Integer getId() {
                return id;
            }
        
            public void setId(Integer 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 String getGender() {
                return gender;
            }
        
            public void setGender(String gender) {
                this.gender = gender;
            }
        
            public String getAddress() {
                return address;
            }
        
            public void setAddress(String address) {
                this.address = address;
            }
        
            @Override
            public String toString() {
                return "User{" +
                        "id=" + id +
                        ", username='" + username + '\'' +
                        ", password='" + password + '\'' +
                        ", gender='" + gender + '\'' +
                        ", address='" + address + '\'' +
                        '}';
            }
        }
        
        
      • 測試類

        public static void main(String[] args) throws IOException {
            // 載入mybatis的核心配置文件,獲取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            // 獲取Session對象,執行SQL語句
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 執行SQL,處理結果
            List<User> users = sqlSession.selectList("test.selectAll");
            System.out.println(users);
            // 釋放資源
            sqlSession.close();
        }
        

3、Mapper代理開發

3.1 Mapper代理開發概述

解決形如上述測試類中List<User> users = sqlSession.selectList("test.selectAll");的硬編碼問題

  • 解決原生方式中的硬編碼
  • 簡化後期的SQL執行

3.2 使用Mapper代理要求

  • 定義與SQL映射文件同名的Mapper介面,並且將Mapper介面和SQL映射文件放置在同一目錄下

    maven項目開發時要求code和resources分開,可在resources中創建相同包文件來是實現上述效果

  • 設置SQL映射文件的namespace屬性未Mapper介面的全限定名

  • 在Mapper介面中定義方法,方法名就是SQL映射文件中SQL語句的id,並且參數類型和返回值類型一致

3.3 案例代碼實現

  • 修改SQL映射文件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">
    <!--
        namespace:命名空間
    -->
    <mapper namespace="priv.dandelion.mapper.UserMapper">
        <select id="selectAll" resultType="priv.dandelion.entity.User">
            select * from tb_user;
        </select>
    </mapper>
    
  • 創建對應的Mapper介面UserMapper.interface

    public interface UserMapper {
        List<User> selectAll();
    }
    
  • 修改mybatis核心配置文件中載入SQL映射的<mapper></mapper>的路徑

    <mappers>
        <mapper resource="priv/dandelion/mapper/UserMapper.xml"/>
    </mappers>
    
  • 測試代碼

    public static void main(String[] args) throws IOException {
        // 載入mybatis的核心配置文件,獲取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // 獲取Session對象,執行SQL語句
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 執行SQL,處理結果
        // 獲取UserMapper介面的代理對象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.selectAll();
        System.out.println(users);
        // 釋放資源
        sqlSession.close();
    }
    
  • 改進

    如果Mapper介面名稱和SQL映射文件名稱相同,併在同一目錄下,則可以使用包掃描的方式簡化SQL映射文件的載入,簡化mybatis核心配置文件

    <mappers>
        <!--載入sql映射文件-->
        <!-- <mapper resource="priv/dandelion/mapper/UserMapper.xml"/>-->
        <!--Mapper代理方式-->
        <package name="priv.dandelion.mapper"/>
    </mappers>
    

4、核心配置文件

4.1 多環境配置

在核心配置文件的 environments 標簽中其實是可以配置多個 environment ,使用 id 給每段環境起名,在 environments 中使用 default='環境id' 來指定使用哪兒段配置。我們一般就配置一個 environment 即可

<?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>

    <typeAliases>
        <package name="priv.dandelion.entity"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <!-- 採用JDBC的事務管理方式 -->
            <transactionManager type="JDBC"/>
            <!-- 資料庫連接信息 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!-- JDBC連接資料庫,SSL,Unicode字元集,UTF-8編碼 -->
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>

        <environment id="test">
            <transactionManager type="JDBC"/>
            <!-- 資料庫連接信息 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 載入SQL映射文件 -->
    <mappers>
        <!-- <mapper resource="priv/dandelion/mapper/UserMapper.xml"/>-->
        <package name="priv.dandelion.mapper"/>
    </mappers>
</configuration>

4.2 類型別名

映射配置文件中的resultType屬性需要配置數據封裝的類型(類的全限定名),繁瑣

Mybatis 提供了 類型別名(typeAliases) 可以簡化這部分的書寫

<configuration>
    <!-- name屬性未實體類所在的包 -->
    <typeAliases>
        <package name="priv.dandelion.entity"/>
    </typeAliases>
</configuration>
<mapper namespace="priv.dandelion.mapper.UserMapper">
    <!-- resultType的值不區分大小寫 -->
    <select id="selectAll" resultType="user">
        select * from tb_user;
    </select>
</mapper>

5、配置文件實現CRUD

5.1 環境準備

  • SQL

    -- 刪除tb_brand表
    drop table if exists tb_brand;
    -- 創建tb_brand表
    create table tb_brand
    (
        -- id 主鍵
        id           int primary key auto_increment,
        -- 品牌名稱
        brand_name   varchar(20),
        -- 企業名稱
        company_name varchar(20),
        -- 排序欄位
        ordered      int,
        -- 描述信息
        description  varchar(100),
        -- 狀態:0:禁用  1:啟用
        status       int
    );
    -- 添加數據
    insert into tb_brand (brand_name, company_name, ordered, description, status)
    values ('三隻松鼠', '三隻松鼠股份有限公司', 5, '好吃不上火', 0),
           ('華為', '華為技術有限公司', 100, '華為致力於把數字世界帶入每個人、每個家庭、每個組織,構建萬物互聯的智能世界', 1),
           ('小米', '小米科技有限公司', 50, 'are you ok', 1);
    
    
    SELECT * FROM tb_brand;
    
  • 實體類

    public class Brand {
        
        private Integer id;
        private String brand_name;
        private String company_name;
        private Integer ordered;
        private String description;
        private Integer status;
    
        public Brand() {
        }
    
        public Brand(
                Integer id,
                String brand_name,
                String company_name,
                Integer ordered,
                String description,
                Integer status
        ) {
            this.id = id;
            this.brand_name = brand_name;
            this.company_name = company_name;
            this.ordered = ordered;
            this.description = description;
            this.status = status;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getBrand_name() {
            return brand_name;
        }
    
        public void setBrand_name(String brand_name) {
            this.brand_name = brand_name;
        }
    
        public String getCompany_name() {
            return company_name;
        }
    
        public void setCompany_name(String company_name) {
            this.company_name = company_name;
        }
    
        public Integer getOrdered() {
            return ordered;
        }
    
        public void setOrdered(Integer ordered) {
            this.ordered = ordered;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        public Integer getStatus() {
            return status;
        }
    
        public void setStatus(Integer status) {
            this.status = status;
        }
    
        @Override
        public String toString() {
            return "Brand{" +
                    "id=" + id +
                    ", brand_name='" + brand_name + '\'' +
                    ", company_name='" + company_name + '\'' +
                    ", ordered=" + ordered +
                    ", description='" + description + '\'' +
                    ", status=" + status +
                    '}';
        }
    }
    
  • 安裝插件MyBatisX

  • 步驟

    1. 編寫介面方法Mapper介面
      • 參數
      • 返回值
    2. 在SQL映射文件中編寫SQL語句
      • MyBatisX插件自動補全
      • 編寫SQL
      • 若資料庫欄位名和實體類欄位名不同,則需要解決該問題(見 5.2 SQL映射文件)
    3. 編寫執行測試
      • 獲取SqlSessionFactory
      • 獲取sqlSession對象
      • 獲取mapper介面的代理對象
      • 執行方法
      • 釋放資源

5.2 查詢所有數據

本節要點:

  1. 測試類的編寫方式
  2. 解決資料庫欄位和實體類欄位名不同的問題
  • 編寫介面方法

    public interface BrandMapper {
        public List<Brand> selectAll();
    }
    
  • 編寫SQL映射文件

    <?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">
    <!--
        namespace:命名空間
    -->
    <mapper namespace="priv.dandelion.mapper.BrandMapper">
    
    <!-- 起別名解決資料庫和實體類欄位名不同問題
        <sql id="brand_column">
            id, brand_name as brandName, company_name as companyName, ordered, description, status
        </sql>
    
        <select id="selectAll" resultType="priv.dandelion.entity.Brand">
            select * from tb_brand;
    
            select
                <include refid="brand_column"/>
            from tb_brand;
        </select>
     -->
    
        <!-- resultMap解決資料庫和實體類欄位不同問題 -->
        <resultMap id="brandResultMap" type="brand">
            <result column="brand_name" property="brandName" />
            <result column="company_name" property="companyName" />
        </resultMap>
    
        <!-- 不使用resultType, 使用resultMap -->
        <select id="selectAll" resultMap="brandResultMap">
            select *
            from tb_brand;
        </select>
    
    </mapper>
    
  • 編寫測試方法

    @Test
    public void testSelectAll() throws IOException {
        // 獲取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
        // 獲取sqlSession對象
        SqlSession sqlSession = sqlSessionFactory.openSession();
    
        // 獲取mapper介面的代理對象
        BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
        // 執行方法
        List<Brand> brands = brandMapper.selectAll();
        System.out.println(brands);
    
        // 釋放資源
        sqlSession.close();
    }
    

5.3 查詢

本節要點:

  1. MyBatis的SQL映射文件中,SQL語句如何接收對應參數
  • 使用占位符進行參數傳遞

    • 占位符名稱和參數保持一致

    • 占位符

      • #{占位符名}:會替換為?防止SQL註入,一般用於替換欄位值
      • ${占位符名}:存在SQL註入問題,一般用於執行動態SQL語句,如表名列名不固定的情況(見)
  • 編寫介面方法

    void update(Brand brand);
    
  • SQL映射文件查詢代碼標簽

    <resultMap id="brandResultMap" type="brand">
        <result column="brand_name" property="brandName" />
        <result column="company_name" property="companyName" />
    </resultMap>
    <select id="selectById" resultMap="brandResultMap">
        select *
        from tb_brand where id = #{id};
    </select>
    
  • 測試方法

    @Test
        public void testSelectByCondition() throws IOException {
            // 接收參數
            int status = 1;
            String companyName = "華為";
            String brandName = "華為";
    
            // 獲取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = 
                new SqlSessionFactoryBuilder().build(inputStream);
    
            // 獲取sqlSession對象
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 獲取mapper介面的代理對象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
            // 執行方法
            companyName = "%" + companyName + "%";
            brandName = "%" + brandName + "%";
            List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName);
            System.out.println(brands);
    
            // 釋放資源
            sqlSession.close();
        }
    

5.4 多條件查詢

本節要點:

  1. 多條件查詢:如果有多個參數,需要使用@Paran("SQL參數占位符名稱")註解
  2. 多條件的動態條件查詢:對象屬性名稱要和參數占位符名稱一致
    (詳見5-2解決資料庫欄位和實體類欄位名不同的問題)
  3. 單條件的動態條件查詢:保證key要和參數占位符名稱一致
  • 多條件查詢

    • SQL映射文件

      <!-- resultMap解決資料庫和實體類欄位不同問題 -->
      <resultMap id="brandResultMap" type="brand">
          <result column="brand_name" property="brandName"/>
          <result column="company_name" property="companyName"/>
      </resultMap>
      
      <!-- 條件查詢 -->
      <select id="selectByCondition" resultMap="brandResultMap">
          select *
          from tb_brand
          where status = #{status}
          and company_name like #{companyName}
          and brand_name like #{brandName}
      </select>
      
    • 散裝參數

      • 介面

        // 散裝參數
        List<Brand> selectByCondition(
            @Param("status")int status, 
            @Param("companyName")String companyName, 
            @Param("brandName")String brandName
        );
        
      • 測試方法

        @Test
            public void testSelectByCondition() throws IOException {
                // 接收參數
                int status = 1;
                String companyName = "華為";
                String brandName = "華為";
        
                // 獲取SqlSessionFactory
                String resource = "mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                SqlSessionFactory sqlSessionFactory =
                    new SqlSessionFactoryBuilder().build(inputStream);
        
                // 獲取sqlSession對象
                SqlSession sqlSession = sqlSessionFactory.openSession();
        
                // 獲取mapper介面的代理對象
                BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
        
                // 執行方法
                companyName = "%" + companyName + "%";
                brandName = "%" + brandName + "%";
                List<Brand> brands = brandMapper.selectByCondition(
                    status, companyName, brandName);
                System.out.println(brands);
        
                // 釋放資源
                sqlSession.close();
            }
        
    • 對象參數

      • 介面

        // 對象參數
        List<Brand> selectByCondition(Brand brand);
        
      • 測試方法

        // 細節不表,僅展示執行方法
        // 執行方法
        Brand brand = new Brand();
        brand.setStatus(status);
        brand.setCompanyName("%" + companyName + "%");
        brand.setBrandName("%" + brandName + "%");
        List<Brand> brands = brandMapper.selectByCondition(brand);
        System.out.println(brands);
        
    • map集合參數

      • 介面

        // 集合參數
        List<Brand> selectByCondition(Map map);
        
      • 測試方法

        // 細節不表,僅展示執行方法
        // 執行方法
        Map map = new HashMap();
        map.put("status", status);
        map.put("companyName", "%" + companyName + "%");
        map.put("brandName", "%" + brandName + "%");
        List<Brand> brands = brandMapper.selectByCondition(map);
        System.out.println(brands);
        
  • 多條件動態條件查詢

    優化條件查詢,如頁面上表單存在多個條件選項,但實際填寫表單僅使用部分條件篩選的情況

    • SQL映射文件

      <!-- resultMap解決資料庫和實體類欄位不同問題 -->
      <resultMap id="brandResultMap" type="brand">
          <result column="brand_name" property="brandName"/>
          <result column="company_name" property="companyName"/>
      </resultMap>
      
      <!-- 動態條件查詢 -->
      <select id="selectByCondition" resultMap="brandResultMap">
          select *
          from tb_brand
          <where>
              <if test="status != null">
                  status = #{status}
              </if>
              <if test="companyName != null">
                  and company_name like #{companyName}
              </if>
              <if test="brandName != null">
                  and brand_name like #{brandName}
              </if>
          </where>
      </select>
      

      註:

      1. if標簽的test屬性中可以包含邏輯或等邏輯判斷,使用andor進行連接

      2. 若條件SQL中同時包含AND等連接符

        • 對所有的條件前都加AND,併在WHERE後加任意真判斷,即WHERE 1=1 AND ... AND ...
        • 加入<if></if>判斷標簽造輪子,自行決定添加AND的條件
        • 使用<where></where>標簽替換原SQL中的WHERE關鍵字,MyBatis將自動進行語法修正,如示例所示
  • 單條件的動態條件查詢

    優化條件查詢:如表單中存在多個條件篩選,但僅有其中一個生效的情況

    • 使用標簽
      • choose標簽類似於Java中的switch
      • when標簽類似於Java中的case
      • otherwise標簽類似於Java中的default
    • SQL映射文件

      <!-- resultMap解決資料庫和實體類欄位不同問題 -->
      <resultMap id="brandResultMap" type="brand">
          <result column="brand_name" property="brandName"/>
          <result column="company_name" property="companyName"/>
      </resultMap>
      
      <!-- 單條件動態查詢 -->
      <select id="selectByConditionSingle" resultMap="brandResultMap">
          select *
          from tb_brand
          <where>
              <choose>
                  <when test="status != null">
                      status = #{status}
                  </when>
                  <when test="companyName != null and companyName != ''">
                      company_name like #{companyName}
                  </when>
                  <when test="brandName != null and brandName != ''">
                      brand_name like #{brandName}
                  </when>
              </choose>
          </where>
      </select>
      

5.6 添加數據與MyBatis事務

  • 添加

    • 介面

      // 添加
      void add(Brand brand);
      
    • SQL映射文件

      <insert id="add">
          insert into tb_brand (brand_name, company_name, ordered, description, status)
          values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
      </insert>
      
    • 測試方法

      @Test
      public void testAdd() throws IOException {
          // 接收參數
          int status = 1;
          String companyName = "aaa";
          String brandName = "xxx";
          String description = "這是一段介紹";
          int ordered = 100;
      
          // 獲取SqlSessionFactory
          String resource = "mybatis-config.xml";
          InputStream inputStream = Resources.getResourceAsStream(resource);
          SqlSessionFactory sqlSessionFactory = 
              new SqlSessionFactoryBuilder().build(inputStream);
      
          // 獲取sqlSession對象
          // SqlSession sqlSession = sqlSessionFactory.openSession();
          SqlSession sqlSession = sqlSessionFactory.openSession(true);
      
          // 獲取mapper介面的代理對象
          BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
      
          // 執行方法
          Brand brand = new Brand();
          brand.setStatus(1);
          brand.setBrandName(brandName);
          brand.setCompanyName(companyName);
          brand.setDescription(description);
          brand.setOrdered(ordered);
          brandMapper.add(brand);
          System.out.println("添加成功");
      
          // 提交事務
          // sqlSession.commit();
      
          // 釋放資源
          sqlSession.close();
      }
      
  • Mybatis事務

    MyBatis預設手動事務,執行添加等操作時會自動回滾

    • MyBayis事務處理的方法

      // 方法一:在獲取sqlSession對象時設置參數,開啟自動事務
      SqlSession sqlSession = sqlSessionFactory.openSession(true);
      sqlSession.close();
      // 方法二:手動提交事務
      SqlSession sqlSession = sqlSessionFactory.openSession();
      sqlSession.commit();
      sqlSession.close();
      
  • 添加 - 主鍵返回

    傳入實體類對象進行數據添加,在數據添加完成後,會將id信息寫回該實體類對象

    • SQL映射文件

      <insert id="add" useGeneratedKeys="true" keyProperty="id">
          insert into tb_brand (brand_name, company_name, ordered, description, status)
          values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
      </insert>
      
    • 獲取寫回信息

      Integer id = brand.getId();
      

5.7 修改

  • 修改整條數據

    • 介面

      // 修改,可使用int返回值,返回受影響行數
      void update(Brand brand);
      
    • SQL映射文件

      <update id="update">
          update tb_brand
          set brand_name = #{brandName},
          set company_name = #{companyName},
          set ordered = #{ordered},
          set description = #{description},
          set status = #{status}
          where id = #{id};
      </update>
      
  • 修改部分欄位

    優化上述代碼應對僅修改部分屬性導致其他屬性數據丟失問題

    使用<set></set>標簽替換set關鍵字列表,區別於<where></where>標簽,註意語法

    • SQL映射文件

      <update id="update">
          update tb_brand
          <set>
              <if test="brandName != null and brandName != ''">
                  brand_name = #{brandName},
              </if>
              <if test="companyName != null and companyName != ''">
                  company_name = #{companyName},
              </if>
              <if test="ordered != null">
                  ordered = #{ordered},
              </if>
              <if test="description != null and description != ''">
                  description = #{description},
              </if>
              <if test="status != null">
                  status = #{status},
              </if>
          </set>
          where id = #{id};
      </update>
      
    • 測試代碼

      @Test
      public void testUpdate() throws IOException {
          // 接收參數
          int id = 5;
          int status = 0;
          String companyName = "AAA";
          String brandName = "XXX";
          int ordered = 300;
      
          // 獲取SqlSessionFactory
          String resource = "mybatis-config.xml";
          InputStream inputStream = Resources.getResourceAsStream(resource);
          SqlSessionFactory sqlSessionFactory = 
              new SqlSessionFactoryBuilder().build(inputStream);
      
          // 獲取sqlSession對象
          SqlSession sqlSession = sqlSessionFactory.openSession(true);
      
          // 獲取mapper介面的代理對象
          BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
      
          // 執行方法
          Brand brand = new Brand();
          brand.setId(id);
          brand.setStatus(status);
          brand.setBrandName(brandName);
          brand.setCompanyName(companyName);
          brand.setOrdered(ordered);
          brandMapper.update(brand);
          System.out.println("修改成功");
      
          // 釋放資源
          sqlSession.close();
      }
      

5.8 刪除數據

  • 刪除一條數據

    • 介面

      // 刪除一條數據
      void deleteById(int id);
      
    • SQL映射文件

      <delete id="deleteById">
          delete
          from tb_brand
          where id = #{id};
      </delete>
      
    • 測試

      @Test
      public void testDeleteById() throws IOException {
          // 接收參數
          int id = 5;
      
          // 獲取SqlSessionFactory
          String resource = "mybatis-config.xml";
          InputStream inputStream = Resources.getResourceAsStream(resource);
          SqlSessionFactory sqlSessionFactory = 
              new SqlSessionFactoryBuilder().build(inputStream);
      
          // 獲取sqlSession對象
          SqlSession sqlSession = sqlSessionFactory.openSession(true);
      
          // 獲取mapper介面的代理對象
          BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
      
          // 執行方法
          brandMapper.deleteById(id);
          System.out.println("刪除成功");
      
          // 釋放資源
          sqlSession.close();
      }
      
  • 批量刪除數據

    用於解決刪除時傳入參數為數組的情況

    • 使用<foreach></foreach>標簽代替SQL語句中的id in (?, ?, ..., ?)
      • collection屬性為MyBatis封裝後數組對應的key,封裝後屬性值應為array(見註釋)
        • MyBatis預設會將數組參數封裝為Map集合,其keyarray,即 array = ids
        • 可在介面中對參數數組使用@Param註解,將封裝後的key手動命名,則可在映射文件中使用
      • separator屬性為分隔符
      • openclose屬性分別為在<foreach></foreach>前後拼接字元,主要用於代碼規範,示例中未展示
    • 介面

      // 刪除多個數據
      void deleteByIds(@Param("ids")int[] ids);
      
    • SQL映射文件

      <delete id="deleteByIds">
          delete
          from tb_brand
          where id
          in (
          <!-- <foreach collection="array" item="id"> -->
          <foreach collection="ids" item="id" separator=",">
              #{id}
          </foreach>
          );
      </delete>
      
    • 測試

      @Test
      public void testDeleteByIds() throws IOException {
          // 接收參數
          int[] ids = {6, 7};
      
          // 獲取SqlSessionFactory
          String resource = "mybatis-config.xml";
          InputStream inputStream = Resources.getResourceAsStream(resource);
          SqlSessionFactory sqlSessionFactory = 
              new SqlSessionFactoryBuilder().build(inputStream);
      
          // 獲取sqlSession對象
          SqlSession sqlSession = sqlSessionFactory.openSession(true);
      
          // 獲取mapper介面的代理對象
          BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
      
          // 執行方法
          brandMapper.deleteByIds(ids);
          System.out.println("刪除成功");
      
          // 釋放資源
          sqlSession.close();
      }
      

5.9 MyBatis參數傳遞

  • 概述

  • 多個參數

    設有如下代碼:

    User select(@Param("username") String username,@Param("password") String password);
    

    MyBatis會將散裝的多個參數封裝為Map集合

    • 若不使用@Param註解,則會使用以下命名規則:

      map.put("arg0",參數值1);
      map.put("arg1",參數值2);
      map.put("param1",參數值1);
      map.put("param2",參數值2);
      

      即Map集合中的參數的key分別為arg0, arg1, param1, param2

    • 使用@Param註解會將Map集合中的參數的arg替換為指定內容,增強其可讀性

  • 單個參數

    • POJO類型:直接使用,要求屬性名和參數占位符名稱一致(見 5.2 SQL映射文件)

    • Map集合類型:直接使用,要求key和參數占位符名稱一致(見 5.2 SQL映射文件)

    • Collection集合類型:封裝Map集合,可以使用@Param註解替換Map集合中預設arg鍵名

      map.put("arg0",collection集合);
      map.put("collection",collection集合;
      
    • List集合類型:封裝為Map集合,可以使用@Param註解,替換Map集合中預設的arg鍵名

      map.put("arg0",list集合);
      map.put("collection",list集合);
      map.put("list",list集合);
      
    • Array類型:封裝為Map集合,可以使用@Param註解,替換Map集合中預設的arg鍵名

      map.put("arg0",數組);
      map.put("array",數組);
      
    • 其他類型:直接使用,與參數占位符無關,但儘量見名知意

6、通過註解實現CRUD

  • 概述

    • 用於簡化開發,可以對簡單的查詢使用註解進行操作,以替換xml中的statement
    • 對於複雜的查詢,仍然建議使用xml配置文件,否則代碼會十分混亂
  • 使用方法

    • 註解(部分)

      • 查詢 :@Select
      • 添加 :@Insert
      • 修改 :@Update
      • 刪除 :@Delete
    • 示例

      • 使用註解簡化查詢

        • 原介面

          Brand selectById(int id);
          
        • 原SQL映射文件

          <!-- resultMap解決資料庫和實體類欄位不同問題 -->
          <resultMap id="brandResultMap" type="brand">
              <result column="brand_name" property="brandName"/>
              <result column="company_name" property="companyName"/>
          </resultMap>
          
          <select id="selectById" resultMap="brandResultMap">
              select *
              from tb_brand
              where id = #{id};
          </select>
          
        • 使用註解進行開發

          • 介面

            @ResultMap("brandResultMap")		// 解決資料庫和實體類欄位名稱不同
            @Select("select * from tb_brand where id = #{id}")	// 查詢語句
            Brand selectById(int id);
            
          • SQL映射文件:不再需要原先的statement

            <!-- resultMap解決資料庫和實體類欄位不同問題 -->
            <resultMap id="brandResultMap" type="brand">
                <result column="brand_name" property="brandName"/>
                <result column="company_name" property="companyName"/>
            </resultMap>
            
            <!--
            <select id="selectById" resultMap="brandResultMap">
                select *
                from tb_brand
                where id = #{id};
            </select>
            -->
            

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 《看漫畫學Python:有趣、有料、好玩、好用:全彩版》PDF高清版免費下載地址 內容簡介 · · · · · · Python是一門既簡單又強大的編程語言,被廣泛應用於數據分析、大數據、網路爬蟲、自動化運維、科學計算和人工智慧等領域。Python也越來越重要,成為國家電腦等級考試科目,某些中小學 ...
  • Java泛型01 1.泛型的理解和好處 看一個需求: 請編寫程式,在ArrayList中添加三個Dog對象 Dog對象含有name和age,並輸出name和age(要求使用getXXX()) 先用傳統的方法來解決 >引出泛型 傳統的方法: package li.generic; import jav ...
  • 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 特效 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> O ...
  • 軟體架構 1、C/S架構:客戶端 / 伺服器 QQ,Typora,騰訊會議。 2、B/S架構:瀏覽器 / 伺服器 京東,愛奇藝,B站。 資源分類 靜態資源:所有用戶訪問後,得到的結果都是一樣的。(HTML,CSS,JS,圖片,音頻,視頻...) 動態資源:每個用戶訪問相同的資源,得到的結果可能不一樣 ...
  • 據說,Rust語言語法的高門檻是勸退很多人上手的主要原因。 確實,Rust語言希望解決 C/C++ 手工管理記憶體的問題,但是又不想引入類似golang,java的GC機制。 因此,為了能讓編譯器能夠在編譯階段檢查出潛在的記憶體問題,Rust的語法上就多了一些其他語言所沒有的規則,這些規則讓上手Rust ...
  • “Http協議和RPC協議有什麼區別?” 最近很多人問我這個問題,他們都不知道怎麼回答。 今天我們就來瞭解一下這個問題的高手回答。 另外,我把文字版本的內容整理到了一個15W字的面試文檔里了。 大家可以看文章尾端領取。 下麵看看高手的回答 高手: 這個問題我想從三個層面來回答。 從功能特性來說。 h ...
  • 摘要:JDK1.5及之後的版本中,提供的線程安全的容器,一般被稱為併發容器。與同步容器一樣,併發容器在總體上也可以分為四大類,分別為:List、Set、Map和Queue。 本文分享自華為雲社區《【高併發】要想學好併發編程,這些併發容器的坑是你必須要註意的!!(建議收藏)》,作者:冰 河 。 其實, ...
  • 前言 嗨嘍,大家好呀~這裡是愛看美女的茜茜吶 又到了學Python時刻~激不激動,開不開森 ! 今天我們來實現一個Python採集視頻、彈幕、評論一體的小軟體。 平常咱們都是直接代碼運行,不過今天,我們來把它做成軟體 😝 這樣的話,再也不擔心分享給你朋友,但他是零基礎小白,運行老報錯啦~ 那下麵, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...