一、Mybatis简介

  • Mybatis是一款优秀的持久层框架,用于简化JSBC开发
  • Mybatis官网:Mybatis官网

什么是持久层?

  • 负责将数据保存到数据库的那一层代码
  • JavaEE三层架构:表现层、业务层、持久层

JDBC缺点(关于JDBC,可见我上一篇文章JDBC编程详解以及Druid的使用

  • 硬编码
  1. 注册驱动,获取连接
  2. sql语句
  • 操作繁琐
  1. 手动设置参数
  2. 手动封装数据集在这里插入图片描述

二、Mybatis操作步骤

Mybati使用步骤总结

  1. 配置Mybtis核心配置文件(一般将其命名为 mybatis-config.xml)
  2. 根据核心配置文件创建 SqlSessionFactory 对象
  3. 通过 SqlSessionFactory 对象创建 SqlSession 对象
  4. 通过 SqlSession 对象操作数据库 CRUD
  5. 提交事务
  6. 释放资源
	// 加载 mybatis核心配置文件,获取 SqlSessionFactory
	String resource = "mybatis-config.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	
	// 获取SqlSession 对象, 执行 sql
	SqlSession sqlSession = sqlSessionFactory.openSession();
	
	// 执行 sql
	// "名称空间.id" 是sql映射文件中sql语句的唯一标识
	List<User> users = sqlSession.selectList("名称空间.id");
	
	// 释放资源
	sqlSession.close();

①核心配置文件

从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。XML 配置文件中包含了对 MyBatis系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。通过核心配置文件,我们可以替换连接信息,解决硬编码问题。这里先给出一个简单的示例:

<?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>
    <!--    
        加载配置文件信息,主要是数据源的连接信息
    -->
    <properties resource="db.properties"/>
    <!--
        类型别名,可简写 resultType,省略包名
    -->
    <typeAliases>
        <package name="com.tyt.pojo"/>
    </typeAliases>
    <!--
        environments:配置数据库连接环境信息。可以配置多个environment,通过default切换不同的environment
    -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--连接信息-->
                <property name="driver" value="${driverClassName}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--加载sql映射文件-->
        <mapper resource="com/tyt/mapper/UserMapper.xml"/>
    </mappers>
</configuration>

其中数据源的连接信息将其写在db.properties中,详情如下:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useSSL=false
username=root
password=****

②SQL映射文件

SQL映射文件可统一管理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="test">
    <insert id="add" useGeneratedKeys="true" keyColumn="id">
        insert into tb_brand (companyName, brandName,  ordered, description, status)
        values (#{companyName}, #{brandName},  #{ordered}, #{description}, #{status});
    </insert>

    <delete id="deleteById">
        delete from tb_brand where id = #{id};
    </delete>
    
    <update id="update">
        update tb_brand
        set
            brandName = #{brandName},
            companyName = #{companyName},
            ordered = #{ordered},
            description = #{description},
            status = #{status}
        where id = #{id};
    </update>

    <select id="selectAll" resultType="Brand">
        select * from tb_brand;
    </select>
</mapper>

③参数符号

在这里插入图片描述
SQL映射文件中的sql语句有两个占位符,分别是: #{}${}
我们一般采用 #{}#{}在Mybatis会被解析为?,就是JDBC中的PreparedStatement中的?占位符,说明它也有预编译的功能。

 * 参数占位符:
         1: #{}: 将其替换为'?' , 防止 sql 注入
         2: ${}: 拼 sql, 存在 sql 注入
         3. 使用时机:
            * 参数传递时: #{}
            * 表名或列名不固定时: ${}
         * 参数类型: parameterType 可省略
         * 特殊字符处理
            1、转义字符:
            2. CDATA: <1[CDATA[ 符号 ]]>

④映射失败的解决方案

当数据库表列名与实体类属性名不一致时,不能自动封装数据。例如,在数据库中,使用下划线命名方式;在实体类中,使用驼峰命名。在此,提供了三种解决方案,其中第三个使用reultMap最为广泛使用。
我这里有一个表tb_brand并定义了实体类Brand,可以发现,在数据库中使用的下划线命名,在实体类中使用的驼峰命名。
在这里插入图片描述

  • 方法一:起别名(在sql语句中,对不一样的列名起别名,别名与属性名一致)
    在这里插入图片描述
    缺点:繁琐,每次查询都要起别名
  • 方法二:定义sql片段
    在这里插入图片描述缺点:一个sql片段仅针对一种情况,不够灵活
  • 方法三:resultMap
    在这里插入图片描述

三、Mapper代理开发

目的

  • 解决原生方式(即二、Mybatis操作步骤)的硬编码
  • 简化后期执行sql
    在这里插入图片描述
    在这里插入图片描述
  1. 定义与SQL映射文件同名的Mapper接口,并将其Mapper接口和SQL映射文件放置在同一目录
  2. 设置SQL映射文件的namespace属性为Mapper接口限定全名
  3. 在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
  4. 编码
    ① 通过SqlSession的getMapper方法获取Mapper接口的代理对象
    ② 调用对应方法完成sql的执行

注:如果Mapper接口名称与SQL映射文件名称相同,并在同一目录,则可使用包扫描的方式简化SQL映射文件的加载
在这里插入图片描述

①SQL映射文件与SQL映射文件同名的Mapper接口
在这里插入图片描述在这里插入图片描述
② 设置SQL映射文件的namespace属性为Mapper接口限定全名
在这里插入图片描述

四、注解开发

如果不习惯用xml配置文件,则可以考虑使用注解的开发方式。注解的开发方式,会将sql语句写入代码,缺点是后续可维护性与拓展性不强(若想修改sql语句,需要更改代码,重新打包部署,但使用xml方式,只需修改xml文件,并用新的文件替代原xml文件即可)


这里是引用

  • 查询:@Select
  • 添加:@Insert
  • 修改:@Update
  • 删除:@Delete

提示

  • 注解完成简单功能
  • 配置文件完成复杂功能

五、SQL映射文件中sql语句高级

1、参数传递

Mybatis中SQL语句有3种方式可以设置参数:

散装参数:需要使用@Param(“SQL中的参数占位符名称”)
在这里插入图片描述
实体类封装参数:需要保证SQL中的参数名与实体类的属性名对应上
在这里插入图片描述
Map集合需要保证SQL中的参数名与Map集合中的键的名称对应上
在这里插入图片描述

2、动态SQL

SQL语句随着用户输入或外部条件的变化而变化,我们称为动态SQL

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

① if
if 标签通常用于 WHERE 语句、UPDATE语句、INSERT语句,通过判断参数值来决定是否使用某个查询条件、判断是否更新或插入某一字段的值。
在这里插入图片描述


② choose
有时候需求并不需要应用所有条件,而只是想从多选型中选择一个。Mybatis提供了<choose>标签(类似Java的switch),按顺序判断<when>标签(类似Java的case)中条件,若条件都不满足,执行<otherwise>标签(类似Java的default)的语句。
在这里插入图片描述


③trim

  • where
    当 if 标签过多,以下组合可能会报错。
    在这里插入图片描述
    这是因为当status为null时,查询语句会出现...where and ...的情况。
    在这里插入图片描述
    解决方法可将 where 更改为 where 1 = 1,也可以利用<where>标签。
    在这里插入图片描述
  • set
    下面的组合中,当brandName为空时,也会报错。
    在这里插入图片描述
    这是因为当brandName为null时,查询语句会出现..., where ...的情况。
    在这里插入图片描述
    解决方法可以利用<set>标签。
    在这里插入图片描述

④foreach标签
<foreach>标签主要用于构建in条件,可在sql语句中对集合进行迭代。也可用于批量删除、添加等操作中。
在这里插入图片描述
属性介绍

  • collection:collection 属性的值有三个分别是 list、array、map 三种,分别对应的参数类型为:List、数组、map 集合。
  • item :表示在迭代过程中每一个元素的别名
  • separator :分隔符,表示迭代时每个元素之间以什么分隔
  • open :前缀
  • close :后缀
  • index :表示在迭代过程中每次迭代到的位置(下标)

3、添加数据主键返回

在某些需求中,需要在数据添加成功后,获取插入数据库数据的主键的值。
只需要在<insert>标签中添加两个数据即可。useGeneratedKeys="true" keyProperty="主键列名"
在这里插入图片描述

六、其他

1、SqlSessionFactory工具类抽取

  • 创建SqlSessionFactory代码优化
 // 加载 mybatis核心配置文件,获取 SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  • 缺点及解决
  1. 代码重复:使用工具类
  2. SqlSessionFactory工厂只创建一次,不能重复创建:使用静态代码块

使用方法:
①定义获取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;
    }
}

②获取SqlSessionFactory对象

SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();

2、分页插件

①引入maven依赖

<dependency>
	<groupId>com.github.pagehelper</groupId>
	<artifactId>pagehelper</artifactId>
	<version>5.2.0</version>
</dependency>

②加入plugin配置
在mybatis核心配置文件中(mybatis-config.xml)配置PageHelper插件

<plugins>
	<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

③代码

  • sql语句
<select id="selectByPage" resultType="Brand" >
	select * from tb_brand
</select>
  • java测试用例
	// 加载 mybatis核心配置文件,获取 SqlSessionFactory
	String resource = "mybatis-config.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	// 获取SqlSession 对象, 执行 sql
	SqlSession sqlSession = sqlSessionFactory.openSession();
	
	// 设置分页相关参数 当前页 + 每页显示的条数
	PageHelper.startPage(1, 2);
	
	BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
	List<Brand> brands = brandMapper.selectByPage();
	System.out.println(brands);
	sqlSession.close();
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐