MyBatis 详细教程

·  阅读 385
MyBatis 详细教程

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

MyBatis

  • 目录树

  • tb_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', '男', '西安');
    INSERT INTO tb_user VALUES (4, '赵六', '111', '女', '上海');
    
  • pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.ruochen</groupId>
        <artifactId>mybatis-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
    
        <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>
            <!--解决报错:Failed to load class “org.slf4j.impl.StaticLoggerBinder-->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-nop</artifactId>
                <version>1.7.5</version>
            </dependency>
    
        </dependencies>
    
    </project>
    
  • logback.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <!--
            CONSOLE :表示当前的日志信息是可以输出到控制台的。
        -->
        <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>[%level] %blue(%d{HH:mm:ss.SSS}) %cyan([%thread]) %boldGreen(%logger{15}) - %msg %n</pattern>
            </encoder>
        </appender>
    
        <logger name="com.ruochen" level="DEBUG" additivity="false">
            <appender-ref ref="Console"/>
        </logger>
    
    
        <!--
    
          level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
         , 默认debug
          <root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。
          -->
        <root level="DEBUG">
            <appender-ref ref="Console"/>
        </root>
    </configuration>
    
  • 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">
                    <!--数据库连接信息-->
                    <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="ruochen666"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <!--加载sql映射文件-->
            <mapper resource="com/ruochen/mapper/UserMapper.xml"/>
        </mappers>
    </configuration>
    
  • UserMapper.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <!--
        namespace:名称空间
    -->
    <mapper namespace="com.ruochen.mapper.UserMapper">
        <select id="selectAll" resultType="com.ruochen.pojo.User">
            select * from tb_user;
        </select>
    </mapper>
    
  • MyBatisDemo.java
    package com.ruochen;
    
    import com.ruochen.pojo.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    /**
     * MyBatis 快速入门代码
     */
    public class MyBatisDemo {
    
        public static void main(String[] args) throws IOException {
            // 1. 加载 MyBatis 的核心配置文件,获取 SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
    
            // 2. 获取 SqlSession 对象,用它来执行 sql
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 3. 执行 sql 语句
            List<User> users = sqlSession.selectList("test.selectAll");
    
            System.out.println(users);
    
            // 4. 释放资源
            sqlSession.close();
        }
    
    }
    
      [User{id=1, username='zhangsan', password='123', gender='男', addr='北京'}, User{id=2, username='李四', password='234', gender='女', addr='天津'}, User{id=3, username='王五', password='11', gender='男', addr='西安'}, User{id=4, username='赵六', password='111', gender='女', addr='上海'}]
    

Mapper 代理

  • 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下

  • 设置SQL映射文件的namespace属性为Mapper接口全限定名

  • 在 Mapper 接口中定义方法,方法名就是SQL映射文件中SQL语句的id,并保持参数类型和返回值类型一致
    package com.ruochen.mapper;
    
    import com.ruochen.pojo.User;
    
    import java.util.List;
    
    public interface UserMapper {
    
        List<User> selectAll();
    }
    
    
  • 编码测试
    package com.ruochen;
    
    import com.ruochen.mapper.UserMapper;
    import com.ruochen.pojo.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    /**
     * Mapper 代理开发
     */
    public class MyBatisDemo2 {
    
        public static void main(String[] args) throws IOException {
            // 1. 加载 MyBatis 的核心配置文件,获取 SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
    
            // 2. 获取 SqlSession 对象,用它来执行 sql
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 3. 执行 sql 语句
            // List<User> users = sqlSession.selectList("test.selectAll");
            // 3.1 获取 UserMapper 接口的代理对象
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            List<User> users = userMapper.selectAll();
    
            System.out.println(users);
    
            // 4. 释放资源
            sqlSession.close();
        }
    
    }
    
      [User{id=1, username='zhangsan', password='123', gender='男', addr='北京'}, User{id=2, username='李四', password='234', gender='女', addr='天津'}, User{id=3, username='王五', password='11', gender='男', addr='西安'}, User{id=4, username='赵六', password='111', gender='女', addr='上海'}]
    
  • 如果Mapper接口名称和SQl映射文件名称相同,并在同一目录下,则可以使用包扫描的方式简化SQL映射文件的加载

案例 - 配置文件完成增删改查

准备工作

  • 数据库表:tb_brand.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;
    
  • 实体类:Brand.java
    package com.ruochen.pojo;
    
    /**
     * 品牌
     *
     * alt + 鼠标左键:整列编辑
     *
     * 在实体类中,基本数据类型建议使用其对应的包装类型
     */
    
    public class Brand {
        // id 主键
        private Integer id;
        // 品牌名称
        private String brandName;
        // 企业名称
        private String companyName;
        // 排序字段
        private Integer ordered;
        // 描述信息
        private String description;
        // 状态:0:禁用  1:启用
        private Integer status;
    
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getBrandName() {
            return brandName;
        }
    
        public void setBrandName(String brandName) {
            this.brandName = brandName;
        }
    
        public String getCompanyName() {
            return companyName;
        }
    
        public void setCompanyName(String companyName) {
            this.companyName = companyName;
        }
    
        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 +
                    ", brandName='" + brandName + '\'' +
                    ", companyName='" + companyName + '\'' +
                    ", ordered=" + ordered +
                    ", description='" + description + '\'' +
                    ", status=" + status +
                    '}';
        }
    }
    
    
  • 测试用例:test 中新建 com.ruochen.test.MyBatisTest.java
  • 安装 MyBatisX 插件
    • XML 和 接口方法 相互跳转
    • 根据接口方法生成 statement

查询

1. 查询所有数据

  • 编写接口方法:Mapper接口
    • 参数:无
    • 结果:List<Brand>
    package com.ruochen.mapper;
    
    import com.ruochen.pojo.Brand;
    
    import java.util.List;
    
    public interface BrandMapper {
    
        /**
         * 查询所有
         */
        public List<Brand> selectAll();
    }
    
  • 编写 SQL 语句:SQL映射文件
        <select id="selectAll" resultType="brand">
            select *
            from tb_brand;
        </select>
    
  • 执行方法,测试
        @Test
        public void TestSelectAll() throws IOException {
            // 1. 获取 SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            // 2. 获取SqlSession对象 
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 3. 获取 Mapper 接口代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
            // 4. 执行方法
            List<Brand> brands = brandMapper.selectAll();
            System.out.println(brands);
    
            // 5. 释放资源
            sqlSession.close();
        }
    

数据库的字段名称和实体类的属性名称不一样,则不能自动封装数据

  • 起别名:对不一样的列名起别名,让别名和实体类的属性名一样
    • 缺点:每次查询都要定义一次别名
    • 解决方案:可以使用sql 片段(缺点:不灵活)

在这里插入图片描述

  • resultMap
    • 定义 <resultMap> 标签
    • 在 <select> 标签中,使用 resultMap 属性替换 resultType 属性

在这里插入图片描述

2. 根据Id查询

  • 编写接口方法:Mapper接口
    • 参数:id
    • 结果:Brand
        /**
         * 查看详情:根据Id查询
         */
        Brand selectById(int id);
    
  • 编写 SQL 语句:SQL映射文件
        <select id="selectById" resultMap="brandResultMap">
            select *
            from tb_brand where id = #{id};
        </select>
    
  • 执行方法,测试
        @Test
        public void TestSelectById() throws IOException {
            // 接收参数
            int id = 1;
    
            // 1. 获取 SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            // 2. 获取SqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 3. 获取 Mapper 接口代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
            // 4. 执行方法
            Brand brand = brandMapper.selectById(id);
            System.out.println(brand);
    
            // 5. 释放资源
            sqlSession.close();
        }
    

参数占位符:

  • #{}:会将其替换为?,为了防止 SQL 注入
  • ${}:拼接 SQL,会存在 SQL 注入问题
  • 使用时机:
    • 参数传递的时候:${}
    • 表名或者列名不固定的情况:${}

 

参数类型:parameterType:可以省略   特殊字符处理:

  • 转义字符:eg:< 对应 &lt;
  • CDATA区:

在这里插入图片描述

3. 多条件查询

  • 编写接口方法:Mapper接口
    • 参数:所有查询条件
    • 结果:List<Brand>
        /**
         * 条件查询
         * * 参数接收
         * 1. 散装参数:如果方法中有多个参数,需要使用 @Param("SQL参数占位符名称")
         * 2. 对象参数:对象的属性的名称要和参数占位符名称一致
         * 3. map集合参数
         *
         * @param status
         * @param companyName
         * @param brandName
         * @return
         */
    //    List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName, @Param("brandName") String brandName);
    
    //    List<Brand> selectByCondition(Brand brand);
        List<Brand> selectByCondition(Map map);
    
  • 编写 SQL 语句:SQL 映射文件
        <select id="selectByCondition" resultMap="brandResultMap">
            select *
            from tb_brand
            where status = #{status}
              and company_name like #{companyName}
              and brand_name like #{brandName};
        </select>
    
  • 执行方法,测试
        /**
         * 多条件查询
         * @throws IOException
         */
        @Test
        public void TestSelectByCondition() throws IOException {
            // 接收参数
            int status = 1;
            String companyName = "华为";
            String brandName = "华为";
    
            // 处理参数
            companyName = "%" + companyName + "%";
            brandName = "%" + brandName + "%";
    
            // 封装对象
    //        Brand brand = new Brand();
    //        brand.setStatus(status);
    //        brand.setCompanyName(companyName);
    //        brand.setBrandName(brandName);
    
            Map map = new HashMap();
            map.put("status", status);
            map.put("companyName", companyName);
            map.put("brandName", brandName);
    
            // 1. 获取 SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            // 2. 获取SqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 3. 获取 Mapper 接口代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
            // 4. 执行方法
    //        List<Brand> brands = brandMapper.selectByCondition(status, companyName, brandName);
    //        List<Brand> brands = brandMapper.selectByCondition(brand);
            List<Brand> brands = brandMapper.selectByCondition(map);
            System.out.println(brands);
    
            // 5. 释放资源
            sqlSession.close();
        }
    

中文查询不到结果可将 jdbc 修改为如下 <property name="url" value="jdbc:mysql:///mybatis?useSSl=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>

4. 多条件查询 - 动态条件查询

  • 修改 SQL 语句即可
        <!--
            动态SQL
                * if:条件判断
                    * test:逻辑表达式
                * 问题:第一个条件不满足时,SQL 语法错误
                    * 恒等式 where 后面加 1 = 1,条件都加上 and
                    * <where> 替换 where 关键字
        -->
        <select id="selectByCondition" resultMap="brandResultMap">
            select *
            from tb_brand
            <!-- where -->
            <where>
                <if test="status != null">
                    and status = #{status}
                </if>
                <if test="companyName!= null and companyName != ''">
                    and company_name like #{companyName}
                </if>
                <if test="brandName!= null and brandName != ''">
                    and brand_name like #{brandName};
                </if>
            </where>
        </select>
    

5. 单条件查询 - 动态条件查询

  • Mapper 接口
        /**
         * 单条件动态查询
         * @param brand
         * @return
         */
        List<Brand> selectByConditionSingle(Brand brand);
    
    
  • SQL 映射文件
        <!--
            单条件查询
        -->
        <select id="selectByConditionSingle" resultMap="brandResultMap">
            select *
            from tb_brand
            where
            <choose><!-- 相当于switch -->
                <when test="status != null"><!-- 相当于 case-->
                    status = #{status}
                </when>
                <when test="companyName != null and companyName != ''"><!-- 相当于 case-->
                    company_name like #{companyName}
                </when>
                <when test="brandName != null and brandName != ''"><!-- 相当于 case-->
                    brand_name like #{brandName};
                </when>
                <otherwise> <!-- 类似于 default -->
    				1 = 1
    			</otherwise>
            </choose>
        </select>
    
    可不使用 <otherwise>,使用 <where> 标签
        <select id="selectByConditionSingle" resultMap="brandResultMap">
            select *
            from tb_brand
            <where>
                <choose><!-- 相当于switch -->
                    <when test="status != null"><!-- 相当于 case-->
                        status = #{status}
                    </when>
                    <when test="companyName != null and companyName != ''"><!-- 相当于 case-->
                        company_name like #{companyName}
                    </when>
                    <when test="brandName != null and brandName != ''"><!-- 相当于 case-->
                        brand_name like #{brandName};
                    </when>
                </choose>
            </where>
        </select>
    
  • 执行方法,测试
        /**
         * 单条件查询
         *
         * @throws IOException
         */
        @Test
        public void TestSelectByConditionSingle() throws IOException {
            // 接收参数
            int status = 1;
            String companyName = "华为";
            String brandName = "华为";
    
            // 处理参数
            companyName = "%" + companyName + "%";
            brandName = "%" + brandName + "%";
    
            // 封装对象
            Brand brand = new Brand();
            brand.setStatus(status);
    //        brand.setCompanyName(companyName);
    //        brand.setBrandName(brandName);
    
            // 1. 获取 SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            // 2. 获取SqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 3. 获取 Mapper 接口代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
            // 4. 执行方法
            List<Brand> brands = brandMapper.selectByConditionSingle(brand);
            System.out.println(brands);
    
            // 5. 释放资源
            sqlSession.close();
        }
    

添加

  • 编写接口方法:Mapper 接口
    • 参数:除了 id 之外的所有数据
    • 结果:void
        /**
         * 添加
         * @param brand
         */
        void add(Brand brand);
    
  • 编写 SQL 语句:SQL 映射文件
        <!--
            添加
        -->
        <insert id="add">
            insert into tb_brand (brand_name, company_name, ordered, description, status)
            values (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
        </insert>
    
  • 执行方法,测试
        /**
         * 添加
         *
         * @throws IOException
         */
        @Test
        public void TestAdd() throws IOException {
            // 接收参数
            int status = 1;
            String companyName = "波导手机";
            String brandName = "波导";
            String description = "手机中的战斗机";
            int ordered = 100;
    
            // 处理参数
            companyName = "%" + companyName + "%";
            brandName = "%" + brandName + "%";
    
            // 封装对象
            Brand brand = new Brand();
            brand.setStatus(status);
            brand.setCompanyName(companyName);
            brand.setBrandName(brandName);
            brand.setDescription(description);
            brand.setOrdered(ordered);
    
            // 1. 获取 SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            // 2. 获取SqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 3. 获取 Mapper 接口代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
            // 4. 执行方法
            brandMapper.add(brand);
    
            // 5. 释放资源
            sqlSession.close();
        }
    

运行后发现并没有添加到数据库中,这就要说到MyBatis的事务

  • 添加 sqlSession.commit(); 即可
  • 或者 SqlSession sqlSession = sqlSessionFactory.openSession(true); 设置为自动提交事务(关闭事务)

添加 - 主键返回

  • 在数据添加成功后,需要获取插入数据库数据的主键的值
  • SQL 映射文件:<insert id="add" useGeneratedKeys="true" keyProperty="id">
  • 测试文件中直接获取即可:Integer id = brand.getId();

修改

1. 修改全部字段

  • 编写接口方法:Mapper 接口
    • 参数:所有数据
    • 结果:void
        /**
         * 修改
         * @param brand
         * @return
         */
        int update(Brand brand);
    
  • 编写 SQL 语句:SQL 映射文件
        <!--
            修改
        -->
        <update id="update">
            update tb_brand
            set brand_name  = #{brandName},
                company_name= #{companyName},
                ordered     = #{ordered},
                description = #{description},
                status      = #{status}
            where id = #{id};
        </update>
    
  • 执行方法,测试
        /**
         * 修改
         *
         * @throws IOException
         */
        @Test
        public void TestUpdate() throws IOException {
            // 接收参数
            int status = 1;
            String companyName = "波导手机";
            String brandName = "波导";
            String description = "波导手机,手机中的战斗机";
            int ordered = 200;
            int id = 6;
    
            // 封装对象
            Brand brand = new Brand();
            brand.setStatus(status);
            brand.setCompanyName(companyName);
            brand.setBrandName(brandName);
            brand.setDescription(description);
            brand.setOrdered(ordered);
            brand.setId(id);
    
            // 1. 获取 SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            // 2. 获取SqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 3. 获取 Mapper 接口代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
            // 4. 执行方法
            int count = brandMapper.update(brand);
            System.out.println(count);
    
            // 提交事务
             sqlSession.commit();
    
            // 5. 释放资源
            sqlSession.close();
        }
    

2. 修改动态字段

  • 编写 SQL 语句: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 and stauts != ''">
                    status = #{status}
                </if>
            </set>
            where id = #{id};
        </update>
    

删除

1. 删除一个

  • 编写接口方法:Mapper 接口
    • 参数:id
    • 结果:void
        /**
         * 根据Id 删除
         * @param id
         */
        void deleteById(int id);
    
  • 编写 SQL 语句:SQL 映射文件
        <!--
            删除 - 删除一条
        -->
        <delete id="deleteById">
            delete
            from tb_brand
            where id = #{id};
        </delete>
    
  • 执行方法,测试
        /**
         * 根据Id 删除
         *
         * @throws IOException
         */
        @Test
        public void TestDeleteById() throws IOException {
            // 接收参数
            int id = 6;
    
            // 1. 获取 SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            // 2. 获取SqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 3. 获取 Mapper 接口代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
            // 4. 执行方法
            brandMapper.deleteById(id);
    
            // 提交事务
            sqlSession.commit();
    
            // 5. 释放资源
            sqlSession.close();
        }
    

2. 批量删除

  • 编写接口方法:Mapper 接口
    • 参数:id数组
    • 结果:void
        /**
         * 批量删除
         * @param ids
         */
        void deleteByIds(@Param("ids") int[] ids);
    
  • 编写 SQL 语句:SQL 映射文件
        <!--
            批量删除
            MyBatis 会将数组参数,封装为一个 Map 集合
                * 默认:array = 数组
                * 使用 @Param 注解 改变 Map 集合的默认 key 的名称
        -->
    
        <delete id="deleteByIds">
            delete from tb_brand where id in
            <foreach collection="ids" item="id" separator="," open="(" close=")">
                ${id}
            </foreach>
        </delete>
    
  • 执行方法,测试
        /**
         * 批量删除
         *
         * @throws IOException
         */
        @Test
        public void TestDeleteByIds() throws IOException {
            // 接收参数
            int[] ids = {7, 8};
    
            // 1. 获取 SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            // 2. 获取SqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            // 3. 获取 Mapper 接口代理对象
            BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
    
            // 4. 执行方法
            brandMapper.deleteByIds(ids);
    
            // 提交事务
            sqlSession.commit();
    
            // 5. 释放资源
            sqlSession.close();
        }
    

MyBatis 参数传递

  • MyBatis 提供了 ParamNameResolver 类来进行参数封装
  • 单个参数
    • POJO类型:直接使用,属性名 和 参数占位符名称 一致
    • Map集合:直接使用,键名 和 参数占位符名称 一致
    • 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("array", 数组)
      map.put("arg0", 数组)
      
    • 其他类型:直接使用
  • 多个参数:封装为 Map 集合,可以使用@Param注解,替换Map集合中默认的arg键名
    map.put("arg0", 参数值1)
    map.put("param1", 参数值1)
    map.put("arg1", 参数值2)
    map.put("param2", 参数值2)
    ---------------@Param("username")
    map.put("username", 参数值1)
    map.put("param1", 参数值1)
    map.put("arg1", 参数值2)
    map.put("param2", 参数值2)
    

注解完成增删改查

  • 查询:@Select
  • 添加:@Insert
  • 修改:@Update
  • 删除:@Delete
@Select("select * from tb_user where id = #{id}")
public User selectById(int id);

【注】

  • 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
  • 选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。 换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。
分类:
后端
标签:
分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改