MyBatis

ORM

ORM(Object Relational Mapping)是一种将对象模型与关系数据库之间进行映射的技术,它可以让开发者使用面向对象的方式来操作数据库,而无需编写SQL语句。

常见的ORM框架有

  • MyBatis
  • Spring Data JPA

简介

什么是MyBatis?

  • MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。

  • MyBatis原本是 Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

  • 官网:https://mybatis.org/mybatis-3/zh/index.html

什么是持久层?

  • 指的是就是数据访问层(dao),是用来操作数据库的。

image-20220901114951631

什么是框架?

  • 是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。
  • 在框架的基础上进行软件开发更加高效、规范、通用、可拓展。

JDBC和MyBatis对比

原始的JDBC程序操作数据库操作步骤:

  1. 注册驱动
  2. 获取连接对象
  3. 执行SQL语句,返回执行结果
  4. 处理执行结果
  5. 释放资源

直接基于JDBC程序来操作数据库,代码实现非常繁琐,所以在项目开发中,我们很少使用。 在项目开发中,通常会使用Mybatis这类的高级技术来操作数据库,从而简化数据库操作、提高开发效率。

Mybatis框架,就是对原始的JDBC程序的封装。

问题分析

原始的JDBC程序,存在以下几点问题:

  1. 数据库链接的四要素(驱动、链接、用户名、密码)全部硬编码在java代码中
  2. 查询结果的解析及封装操作繁琐
  3. 每一次查询数据库都需要获取连接,操作完毕后释放连接, 资源浪费, 性能降低

image-20221210153407998

技术对比

分析了JDBC的缺点之后,我们再来看一下在mybatis中,是如何解决这些问题的:

  1. 数据库连接四要素(驱动、链接、用户名、密码),都配置在配置文件
  2. 查询结果的解析及封装,由mybatis自动完成映射封装
  3. 在mybatis中使用了数据库连接池技术,从而避免了频繁的创建连接、销毁连接而带来的资源浪费。

image-20210726204849309

入门案例

以前我们是在图形化客户端工具中编写SQL查询代码,发送给数据库执行,数据库执行后返回操作结果。

image-20221209155704203

图形化工具会把数据库执行的查询结果,使用表格的形式展现出来

image-20220901121116813

现在使用Mybatis操作数据库,就是在Mybatis中编写SQL查询代码,发送给数据库执行,数据库执行后返回结果。

image-20221209155904370

Mybatis会把数据库执行的查询结果,使用实体类封装起来(一行记录对应一个实体类对象)

image-20221209161623051

代码实现

  1. 创建mybatis模块,并添加依赖

    <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>8.0.33</version>
        </dependency>
    
        <!--junit 单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
  2. 在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:配置数据库连接环境信息。可以配置多个environment,通过default属性切换不同的environment
        -->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <!--数据库连接信息-->
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql:///mybatis"/>
                    <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.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql:///mybatis"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
           <!--加载sql映射文件-->
           <mapper resource="UserMapper.xml"/>
        </mappers>
    </configuration>
    
  3. 创建mybatis数据库,执行下面的代码创建用户表user,并创建对应的实体类User。

    • 用户表:
    -- 用户表
    create table user(
                         id int unsigned primary key auto_increment comment 'ID',
                         name varchar(100) comment '姓名',
                         age tinyint unsigned comment '年龄',
                         gender tinyint unsigned comment '性别, 1:男, 2:女',
                         phone varchar(11) comment '手机号',
                         update_time datetime comment '修改时间'
    ) comment '用户表';
    
    -- 测试数据
    insert into user(id, name, age, gender, phone,update_time) VALUES (null,'白眉鹰王',55,'1','18800000000',now());
    insert into user(id, name, age, gender, phone,update_time) VALUES (null,'金毛狮王',45,'1','18800000001',now());
    insert into user(id, name, age, gender, phone,update_time) VALUES (null,'青翼蝠王',38,'1','18800000002',now());
    insert into user(id, name, age, gender, phone,update_time) VALUES (null,'紫衫龙王',42,'2','18800000003',now());
    insert into user(id, name, age, gender, phone,update_time) VALUES (null,'光明左使',37,'1','18800000004',now());
    insert into user(id, name, age, gender, phone,update_time) VALUES (null,'光明右使',48,'1','18800000005',now());
    

    image-20220901121116813

    • 实体类

      • 实体类的属性名与表中的字段名一一对应。
    public class User {
        private Integer id;   //id(主键)
        private String name;  //姓名
        private Short age;    //年龄
        private Short gender; //性别
        private String phone; //手机号
        private LocalDateTime updateTime; //修改时间
        
        //省略get、set、toString方法
    }
    

    LocalDateTime类型对应数据表中的datetime类型

    LocalDate类型对应数据表中的date类型

  4. 在模块的 resources 目录下创建映射配置文件 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">
    <mapper namespace="UserMapper">
        <select id="listUser" resultType="com.fs.pojo.User">
            select * from user;
        </select>
    </mapper>
    

    resultType 属性用于配置数据封装的类型(类的全限定名)

功能测试

创建MyBatisTest

public class MyBatisTest {

    @Test
    public void test() throws IOException {
        //加载mybatis核心配置文件,获取SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //获取SqlSession对象,用来执行sql
        SqlSession session = sqlSessionFactory.openSession();

        //执行sql
        //使用映射配置文件中的namespace.id来定位sql语句
        List<User> users = session.selectList("UserMapper.listUser");
        for (User user : users) {
            System.out.println(user);
        }

        //释放资源
        session.close();
    }
}

image-20230816080909832

代理开发

作用:

  • 解决mybatis原生方式中执行sql语句时的硬编码
  • 简化后期执行SQL

代码实现

  1. 创建UserMapper接口

    public interface UserMapper {
        List<User> listUser(@Param("id") Integer id, @Param("age") Integer age, @Param("gender") Integer gender);
    }
    
  2. 修改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>
    
        <typeAliases>
            <!--name属性的值是实体类所在包-->
            <package name="com.fs.pojo"/>
        </typeAliases>
    
        <!--
        environments:配置数据库连接环境信息。可以配置多个environment,通过default属性切换不同的environment
        -->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <!--数据库连接信息-->
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql:///mybatis"/>
                    <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.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql:///mybatis"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <!--加载sql映射文件-->
            <mapper resource="UserMapper.xml"/>
        </mappers>
    </configuration>
    

    如果Mapper接口名称和SQL映射文件名称相同,并且Mapper接口和SQL映射文件在相同的目录层级结构下,则可以使用包扫描的方式简化SQL映射文件的加载。

    <mappers>    
      <!--配置Mapper代理接口包扫描-->
      <package name="com.fs.mapper"/>
    </mappers>
    
  3. 修改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.fs.mapper.UserMapper">
        <select id="listUser" resultType="User">
            select *
            from user
            where id &lt; #{id}
              and age > #{age}
              and gender != #{gender};
        </select>
    </mapper>
    

    可以使用 类型别名(typeAliases)简化 resultType 属性。

    sql语句中特殊字符的处理:

    1. 使用字符实体

      小于号:&lt;
      
    2. <![CDATA[需要转义的字符]]>

      <![CDATA[<]]>
      
  4. 修改MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession();
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            List<User> users = userMapper.listUser(6,37,2);
            for (User user : users) {
                System.out.println(user);
            }
    
            //释放资源
            session.close();
        }
    }
    

    image-20230816080909832

参数占位符

在Mybatis中提供的参数占位符有两种:${…} 、#{…}

  • #{…}

    • 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值,底层使用的是 PreparedStatement
    • 一般在参数传递时使用
  • ${…}

    • 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题,底层使用的是 Statement
    • 一般在对表名、列表进行动态设置时使用

项目开发中,建议使用#{…},生成预编译SQL,防止SQL注入安全。

参数传递

多个参数

在接口方法中定义多个参数时,Mybatis 会将这些参数封装成 Map 集合对象,值就是参数值,而键在没有使用 @Param 注解时有以下命名规则:

  • 以 arg 开头 :第一个参数就叫 arg0,第二个参数就叫 arg1,以此类推。如:

    map.put(“arg0”,参数值1);

    map.put(“arg1”,参数值2);

  • 以 param 开头 : 第一个参数就叫 param1,第二个参数就叫 param2,依次类推。如:

    map.put(“param1”,参数值1);

    map.put(“param2”,参数值2);

接收多个参数使用 @Param 注解后Mybatis 会将默认的键名替换为对应注解的属性值。

代码实现
  1. 修改UserMapper

    public interface UserMapper {
        List<User> listUser(Integer id, Integer age, Integer gender);
    }
    
  2. 修改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.fs.mapper.UserMapper">
        <select id="listUser" resultType="User">
            select *
            from user
            where id &lt; #{param1}
              and age > #{param2}
              and gender != #{param3};
        </select>
    </mapper>
    

    <?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.fs.mapper.UserMapper">
        <select id="listUser" resultType="User">
            select *
            from user
            where id &lt; #{arg0}
              and age > #{arg1}
              and gender != #{arg2};
        </select>
    </mapper>
    

单个参数

POJO 类型参数

直接使用。

要求 属性名参数占位符名称 一致

Map 集合类型

直接使用。

要求 map集合的键名参数占位符名称 一致

Collection 集合类型

Mybatis 会将集合封装到 map 集合中:

  • map.put(“arg0”,collection集合);
  • map.put(“collection”,collection集合;

可以使用 @Param 注解替换map集合中默认的键名。

List 集合类型

Mybatis 会将集合封装到 map 集合中:

  • map.put(“arg0”,list集合);
  • map.put(“collection”,list集合);
  • map.put(“list”,list集合);

可以使用 @Param 注解替换map集合中默认的键名。

Array 类型

Mybatis 会将数组封装到 map 集合中,如下:

  • map.put(“arg0”,数组);
  • map.put(“array”,数组);

可以使用 @Param 注解替换map集合中默认的键名。

基本类型

直接使用。

参数占位符名称 叫什么都可以。尽量做到见名知意

数据封装

如果实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装,如果实体类属性名和数据库表查询返回的字段名不一致,不能自动封装。

起别名

代码实现
  1. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
        <select id="listUser" resultType="User">
            select id, name, age, gender, phone, update_time as updateTime from user;
        </select>
    </mapper>
    

    image-20230816081646062

配置resultMap映射

代码实现
  1. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
    
        <resultMap id="UserResultMap" type="User">
            <result column="update_time" property="updateTime"/>
        </resultMap>
    
        <select id="listUser" resultMap="UserResultMap">
            select *
            from user;
        </select>
    </mapper>
    

    完成主键字段的映射:

    • column:表的列名
    • property:实体类的属性名

    完成一般字段的映射:

    • column:表的列名
    • property:实体类的属性名

    image-20230816081646062

基本使用

删除

代码实现

  1. 修改UserMapper

    public interface UserMapper {
        int deleteById(Integer id);
    }
    
  2. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
    
        <delete id="deleteById">
            delete
            from user
            where id = #{id}
        </delete>
    </mapper>
    
  3. 修改MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession();
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            System.out.println(userMapper.deleteById(6));
    
            //提交事务
            session.commit();
    
            //释放资源
            session.close();
        }
    }
    

    MyBatis的事务默认为手动提交

    SqlSession sqlSession = sqlSessionFactory.openSession(true); //设置自动提交事务
    

添加

代码实现

  1. 修改UserMapper

    public interface UserMapper {
        int insertUser(User user);
    }
    
  2. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
        <insert id="insertUser">
            insert into user (name, age, gender, phone, update_time)
                value (#{name}, #{age}, #{gender}, #{phone}, #{updateTime})
        </insert>
    </mapper>
    
  3. 创建MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession(true);//设置自动提交事务
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            User user = new User();
            user.setName("光明右使");
            user.setAge((short) 48);
            user.setGender((short) 1);
            user.setPhone("18800000005");
            user.setUpdateTime(LocalDateTime.now());
            System.out.println(userMapper.insertUser(user));
    
            //释放资源
            session.close();
        }
    }
    

主键返回

在数据添加成功后,返回插入数据库数据的主键。

代码实现
  1. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
        <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
            insert into user (name, age, gender, phone, update_time)
                value (#{name}, #{age}, #{gender}, #{phone}, #{updateTime})
        </insert>
    </mapper>
    
  2. 修改MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession(true);//设置自动提交事务
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            User user = new User();
            user.setName("光明右使");
            user.setAge((short) 48);
            user.setGender((short) 1);
            user.setPhone("18800000005");
            user.setUpdateTime(LocalDateTime.now());
            System.out.println(userMapper.insertUser(user));
            System.out.println(user);
    
            //释放资源
            session.close();
        }
    }
    

修改

代码实现

  1. 修改UserMapper

    public interface UserMapper {
        int updateUser(User user);
    }
    
  2. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
        <update id="updateUser">
            update user
            set name        = #{name},
                age         = #{age},
                gender      = #{gender},
                phone       = #{phone},
                update_time = #{updateTime}
            where id = #{id}
        </update>
    </mapper>
    
  3. 修改MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession(true);//设置自动提交事务
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            User user = new User();
            user.setId(6);
            user.setName("光明大使");
            user.setAge((short) 58);
            user.setGender((short) 2);
            user.setUpdateTime(LocalDateTime.now());
            System.out.println(userMapper.updateUser(user));
            System.out.println(user);
    
            //释放资源
            session.close();
        }
    }
    

动态SQL

SQL语句会随着用户的输入或外部条件的变化而变化

动态查询

<if>

  • 用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL。

    <if test="条件表达式">
        
    </if>
    

<where>

  • 只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或OR

    <where>
    
    </where>
    

代码实现

  1. 修改UserMapper

    public interface UserMapper {
        List<User> listUser(@Param("id") Integer id, @Param("age") Integer age, @Param("gender") Integer gender);
    }
    
  2. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
        <select id="listUser" resultType="User">
            select *
            from user
            <where>
                <if test="id != null">
                    id &lt; #{id}
                </if>
                <if test="age != null">
                    and age > #{age}
                </if>
                <if test="gender != null">
                    and gender != #{gender}
                </if>
            </where>
        </select>
    </mapper>
    
  3. 修改MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession();
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            List<User> users = userMapper.listUser(null,37,2);
            for (User user : users) {
                System.out.println(user);
            }
    
            //释放资源
            session.close();
        }
    }
    

动态修改

<set>

  • 动态的在SQL语句中插入set关键字,并会删掉额外的逗号。

    <set>
        
    </set>
    

代码实现

  1. 修改UserMapper

    public interface UserMapper {
        int updateUser(User user);
    }
    
  2. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
        <update id="updateUser">
            update user
            <set>
                <if test="name != null">
                    name = #{name},
                </if>
                <if test="age != null">
                    age = #{age},
                </if>
                <if test="gender != null">
                    gender = #{gender},
                </if>
                <if test="phone != null">
                    phone = #{phone},
                </if>
                <if test="updateTime != null">
                    update_time = #{updateTime}
                </if>
            </set>
            where id = #{id}
        </update>
    </mapper>
    
  3. 修改MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession(true);//设置自动提交事务
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            User user = new User();
            user.setId(6);
            user.setName("光明大使");
            user.setAge((short) 58);
            user.setGender((short) 2);
            user.setUpdateTime(LocalDateTime.now());
            System.out.println(userMapper.updateUser(user));
            System.out.println(user);
    
            //释放资源
            session.close();
        }
    }
    

批量删除

foreach

  • 用来迭代任何可迭代的对象(如数组,集合)

    <foreach collection="集合名称" item="集合遍历出来的元素/项" separator="集合项迭代之间的分隔符" 
             open="遍历开始前拼接的片段" close="遍历结束后拼接的片段">
    </foreach>
    

代码实现

  1. 修改UserMapper

    public interface UserMapper {
        int deleteById(@Param("ids") int[] ids);
    }
    
  2. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
    
        <delete id="deleteById">
            delete
            from user
            where id in
            <foreach collection="ids" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
    
        </delete>
    </mapper>
    
  3. 修改MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession();
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            System.out.println(userMapper.deleteById(new int[]{1,2,3}));
    
            //提交事务
            session.commit();
    
            //释放资源
            session.close();
        }
    }
    

sql、include

<sql>

  • 定义可重用的SQL片段

    <sql id="SQL片段id">
    
    </sql>
    

<include>

  • 通过属性refid,指定包含的SQL片段

    <include refid="SQL片段id"></include>
    

代码实现

  1. 修改UserMapper

    public interface UserMapper {
        List<User> listUser(@Param("id") Integer id, @Param("age") Integer age, @Param("gender") Integer gender);
    }
    
  2. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
        <sql id="list">
            select *
            from user
        </sql>
    
        <select id="listUser" resultType="User">
            <include refid="list"></include>
            <where>
                <if test="id != null">
                    id &lt; #{id}
                </if>
                <if test="age != null">
                    and age > #{age}
                </if>
                <if test="gender != null">
                    and gender != #{gender}
                </if>
            </where>
        </select>
    </mapper>
    
  3. 修改MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession();
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            List<User> users = userMapper.listUser(null,37,2);
            for (User user : users) {
                System.out.println(user);
            }
    
            //释放资源
            session.close();
        }
    }
    

注解开发

Mybatis的开发有两种方式:

  1. 注解
  2. XML

注解是用来替换映射配置文件方式配置的,所以使用了注解,就不需要再映射配置文件中书写对应的 statement

使用Mybatis的注解,主要是来完成一些简单的增删改查功能。

代码实现

  1. 修改UserMapper

    public interface UserMapper {
        @Select("select * from user;")
        List<User> listUser();
    }
    

    @Select注解:用于编写select查询操作的SQL语句

    @Delete注解:用于编写delete操作的SQL语句

    @Update注解:用于编写update操作的SQL语句

    @Insert注解:用于编写insert操作的SQL语句

  2. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
    </mapper>
    
  3. 修改MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession();
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            List<User> users = userMapper.listUser();
            for (User user : users) {
                System.out.println(user);
            }
    
            //释放资源
            session.close();
        }
    }
    

主键返回

在Mapper接口中的方法上添加一个@Options注解,并在注解中指定属性useGeneratedKeys=true和keyProperty=“实体类属性名”

代码实现

  1. 修改UserMapper

    public interface UserMapper {
    
        @Options(useGeneratedKeys = true, keyProperty = "id")
        @Insert("insert into user (name, age, gender, phone, update_time)\n" +
                "            value (#{name}, #{age}, #{gender}, #{phone}, #{updateTime})")
        int insertUser(User user);
    }
    
  2. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
    </mapper>
    
  3. 创建MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession(true);//设置自动提交事务
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            User user = new User();
            user.setName("光明右使");
            user.setAge((short) 48);
            user.setGender((short) 1);
            user.setPhone("18800000005");
            user.setUpdateTime(LocalDateTime.now());
            System.out.println(userMapper.insertUser(user));
            System.out.println(user);
    
            //释放资源
            session.close();
        }
    }
    

配置result映射

通过 @Results及@Result进行结果映射

代码实现

  1. 修改UserMapper

    public interface UserMapper {
        @Results({
                @Result(column = "update_time", property = "updateTime")
        })
        @Select("select * from user;")
        List<User> listUser();
    }
    
  2. 修改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">
    <mapper namespace="com.fs.mapper.UserMapper">
    </mapper>
    
  3. 修改MyBatisTest

    public class MyBatisTest {
    
        @Test
        public void test() throws IOException {
            //加载mybatis核心配置文件,获取SqlSessionFactory
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
            //获取SqlSession对象,用来执行sql
            SqlSession session = sqlSessionFactory.openSession();
    
            //执行sql
            //获取UserMapper接口的代理对象
            UserMapper userMapper = session.getMapper(UserMapper.class);
            List<User> users = userMapper.listUser();
            for (User user : users) {
                System.out.println(user);
            }
    
            //释放资源
            session.close();
        }
    }
    

    @Results源代码:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    public @interface Results {
    String id() default "";
    
    Result[] value() default {};  //Result类型的数组
    }
    

    @Result源代码:

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    @Repeatable(Results.class)
    public @interface Result {
    boolean id() default false;//表示当前列是否为主键(true:是主键)
    
    String column() default "";//指定表中字段名
    
    String property() default "";//指定类中属性名
    
    Class<?> javaType() default void.class;
    
    JdbcType jdbcType() default JdbcType.UNDEFINED;
    
    Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;
    
    One one() default @One;
    
    Many many() default @Many;
    }
    

SqlSessionFactory工具类抽取

重复代码:

//加载mybatis核心配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  • 重复代码不利于后期的维护
  • SqlSessionFactory工厂类进行重复创建,资源消耗非常大但性能却非常低。

代码实现

public class SqlSessionFactoryUtils {

    private static SqlSessionFactory sqlSessionFactory;

    static {
        //静态代码块会随着类的加载而自动执行,且只执行一次
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static SqlSessionFactory getSqlSessionFactory(){
        return sqlSessionFactory;
    }
}

工具类抽取以后,以后在对Mybatis的SqlSession进行操作的时候,就可以直接使用

SqlSessionFactory sqlSessionFactory =SqlSessionFactoryUtils.getSqlSessionFactory();
  • 38
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值