MyBatis详解

文章目录

  • 引言
  • 1. 什么是MyBatis
  • 2. JDBC介绍
    • 2.1 介绍
      • 2.1.1 主要组件
      • 2.1.2 基本流程
      • 2.1.3 示例代码
      • 2.1.4 问题分析
      • 2.1.5 技术对比
  • 3. 数据库连接池
    • 3.1 介绍
    • 3.2 常用数据库连接池
    • 3.3 使用示例(Hikari)
  • 4. Lombok
    • 4.1 定义和目的
    • 4.2 常用注解
    • 4.3 使用
  • 5. Mybatis基础操作
    • 5.1 查询
      • 5.1.1 根据主键 ID 查询
      • 5.1.2 条件查询
    • 5.2 新增
    • 5.3 更新
    • 5.4 删除
      • 5.4.1 根据主键 ID 删除
      • 5.4.2 根据主键 ID 批量删除
  • 6. Mybatis的XML配置文件
    • 6.1 XML配置文件规范
    • 6.2 XML配置文件实现
    • 6.3 MybatisX的使用
  • 7. Mybatis动态SQL
    • 7.1 动态 SQL - if 元素
      • 7.1.1 基本用法
      • 7.1.2 高级用法
    • 7.2 动态SQL-foreach
      • 7.2.1 基本用法
      • 7.2.2 高级用法
    • 7.3 动态SQL-sql&include
      • 7.3.1 sql 元素
      • 7.3.2 include 元素
      • 7.3.3 高级用法
      • 7.3.4 注意事项

引言

MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

在学习MySQL数据库时,都是利用图形化客户端工具(如:idea、datagrip),来操作数据库的。

在客户端工具中,编写增删改查的SQL语句,发给MySQL数据库管理系统,由数据库管理系统执行SQL语句并返回执行结果。
增删改操作:返回受影响行数
查询操作:返回结果集(查询的结果)

做为后端程序开发人员,通常会使用Java程序来完成对数据库的操作。Java程序操作数据库,现在主流的方式是:Mybatis。

1. 什么是MyBatis

  • MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。
  • MyBatis本是 Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
  • 官网:https://mybatis.org/mybatis-3/zh/index.html
  • 持久层:指的是就是数据访问层(dao),是用来操作数据库的。

MyBatis详解_第1张图片

2. JDBC介绍

虽然说通过Mybatis可以很方便的进行数据库的访问操作。但是大家要明白,其实java语言操作数据库呢,只能通过一种方式:使用sun公司提供的 JDBC 规范。而Mybatis框架,就是对原始的JDBC程序的封装。

2.1 介绍

JDBC: ( Java DataBase Connectivity ),就是使用Java语言操作关系型数据库的一套API。用于连接和执行查询以访问不同类型的数据库。JDBC 提供了一个标准库,用于建立数据库连接、执行 SQL 语句以及处理查询结果。它作为 Java 应用程序和各种关系数据库之间的桥梁,使得数据库操作可以在 Java 中以一种平台无关的方式进行。
MyBatis详解_第2张图片

2.1.1 主要组件

  • 驱动程序(Driver): 数据库厂商提供的 JDBC 驱动允许 Java 应用程序与数据库建立连接。
  • Connection: 一旦驱动程序加载,程序员可以利用 Connection 对象与数据库建立连接。
  • Statement: Statement 对象用于执行 SQL 命令。
  • ResultSet: 执行查询后,结果保存在 ResultSet 对象中。

2.1.2 基本流程

  1. 加载数据库驱动
  2. 建立到数据库的连接
  3. 创建一个 StatementPreparedStatement 对象
  4. 执行 SQL 查询或更新
  5. 处理结果(如果有)
  6. 关闭连接和释放资源

2.1.3 示例代码

以下是使用 JDBC 连接 MySQL 数据库的 Java 示例代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class JdbcExample {
    public static void main(String[] args) {
        try {
            // 第一步:加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            
            // 第二步:建立数据库连接
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testDB", "用户名", "密码");
            
            // 第三步:创建 Statement 对象
            Statement stmt = conn.createStatement();
            
            // 第四步:执行 SQL 查询
            ResultSet rs = stmt.executeQuery("SELECT * FROM employees");
            
            // 第五步:处理查询结果
            while (rs.next()) {
                System.out.println(rs.getString("name") + ", " + rs.getInt("age"));
            }
            
            // 第六步:关闭资源
            rs.close();
            stmt.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

DriverManager(类):数据库驱动管理类。

  • 作用:
  1. 注册驱动
  2. 创建java代码和数据库之间的连接,即获取Connection对象

Connection(接口):建立数据库连接的对象

  • 作用:用于建立java程序和数据库之间的连接

Statement(接口): 数据库操作对象(执行SQL语句的对象)。

  • 作用:用于向数据库发送sql语句

ResultSet(接口):结果集对象(一张虚拟表)

  • 作用:sql查询语句的执行结果会封装在ResultSet中

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

2.1.4 问题分析

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

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

2.1.5 技术对比

分析在mybatis中,是如何解决这些问题的:

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

而对于Mybatis来说,我们在开发持久层程序操作数据库时,需要重点关注以下两个方面:

  1. application.properties
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234
  1. Mapper接口(编写SQL语句)
@Mapper
public interface UserMapper {
    @Select("select id, name, age, gender, phone from user")
    public List<User> list();
}

3. 数据库连接池

3.1 介绍

数据库连接池是个容器,负责分配、管理数据库连接(Connection)

没有使用数据库连接池:

  • 客户端执行SQL语句:要先创建一个新的连接对象,然后执行SQL语句,SQL语句执行后又需要关闭连接对象从而释放资源,每次执行SQL时都需要创建连接、销毁链接,这种频繁的重复创建销毁的过程是比较耗费计算机的性能。

使用了数据库连接池
MyBatis详解_第3张图片

  • 程序在启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象
    允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
  • 客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用)释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏
  • 客户端获取到Connection对象了,但是Connection对象并没有去访问数据库(处于空闲),数据库连接池发现Connection对象的空闲时间 > 连接池中预设的最大空闲时间,此时数据库连接池就会自动释放掉这个连接对象

3.2 常用数据库连接池

  • C3P0
  • Druid(德鲁伊)
  • Hikari(追光者) [默认的连接池]

3.3 使用示例(Hikari)

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

public class HikariCPExample {
    public static void main(String[] args) {
        // 配置 HikariCP
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/testDB");
        config.setUsername("用户名");
        config.setPassword("密码");

        // 创建连接池
        HikariDataSource ds = new HikariDataSource(config);

        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        
        try {
            // 从连接池中获取连接
            conn = ds.getConnection();

            // 创建 Statement 对象
            stmt = conn.createStatement();

            // 执行 SQL 查询
            rs = stmt.executeQuery("SELECT * FROM employees");

            // 处理查询结果
            while (rs.next()) {
                System.out.println(rs.getString("name") + ", " + rs.getInt("age"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            try {
                if (rs != null) rs.close();
                if (stmt != null) stmt.close();
                if (conn != null) conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 关闭连接池
        ds.close();
    }
}

4. Lombok

4.1 定义和目的

Lombok 是一个 Java 库,旨在通过注解(Annotations)减少 Java 代码的样板代码(Boilerplate Code)。Lombok 可以帮助开发者自动生成诸如 getter、setter、equals、hashCode 和 toString 方法等常用代码。这样不仅减少了代码量,还提高了代码的可读性和维护性。

4.2 常用注解

注解 作用
@Getter/@Setter 为所有的属性提供get/set方法
@ToString 会给类自动生成易阅读的 toString 方法
@EqualsAndHashCode 根据类所拥有的非静态字段自动重写 equals 方法和 hashCode 方法
@Data 提供了更综合的生成代码功能(@Getter + @Setter + @ToString + @EqualsAndHashCode)
@NoArgsConstructor 为实体类生成无参的构造器方法
@AllArgsConstructor 为实体类生成除了static修饰的字段之外带有各参数的构造器方法

4.3 使用

第1步:在pom.xml文件中引入依赖


<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
dependency>

第2步:在实体类上添加注解

import lombok.Data;

@Data
public class User {
    private Integer id;
    private String name;
    private Short age;
    private Short gender;
    private String phone;
}

在实体类上添加了@Data注解,那么这个类在编译时期,就会生成getter/setter、equals、hashcode、toString等方法。
MyBatis详解_第4张图片

说明:@Data注解中不包含全参构造方法,通常在实体类上,还会添加上:全参构造、无参构造

import lombok.Data;

@Data //getter方法、setter方法、toString方法、hashCode方法、equals方法
@NoArgsConstructor //无参构造
@AllArgsConstructor//全参构造
public class User {
    private Integer id;
    private String name;
    private Short age;
    private Short gender;
    private String phone;
}

Lombok的注意事项:

  • Lombok会在编译时,会自动生成对应的java代码
  • 在使用lombok时,还需要安装一个lombok的插件(新版本的IDEA中自带)

MyBatis详解_第5张图片

5. Mybatis基础操作

MyBatis 是一个开源的 SQL 映射框架,它允许你直接使用 SQL 语句,而不需要像 JPA 那样使用 HQL 或 JPQL。MyBatis 可以与 Java 对象模型 (POJOs) 直接映射 SQL 数据库记录,为开发者提供更多的灵活性。

5.1 查询

查询是数据库交互中非常常见的一种操作。在 MyBatis 中,我们可以通过多种方式来进行查询。

5.1.1 根据主键 ID 查询

XML 配置
在 XML 映射文件中,你可以像下面这样定义一个根据 ID 查询的 SQL 语句:

<select id="getEmployeeById" parameterType="int" resultType="com.example.Employee">
  SELECT * FROM employee WHERE id = #{id}
select>

Java 代码
在 Java 代码中,你可以这样使用:

try (SqlSession session = sqlSessionFactory.openSession()) {
  EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
  Employee employee = mapper.getEmployeeById(1);
  System.out.println(employee);
}

5.1.2 条件查询

XML 配置
条件查询通常更复杂,但也可以通过 MyBatis 的 XML 配置来实现:

<select id="findEmployees" resultType="com.example.Employee">
  SELECT * FROM employee
  <where>
    <if test="name != null">
      name = #{name}
    if>
    <if test="age != null">
      AND age = #{age}
    if>
  where>
select>

Java 代码

try (SqlSession session = sqlSessionFactory.openSession()) {
  EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
  List<Employee> employees = mapper.findEmployees("John", 30);
  for (Employee employee : employees) {
    System.out.println(employee);
  }
}

5.2 新增

XML 配置

<insert id="insertEmployee" parameterType="com.example.Employee">
  INSERT INTO employee (name, age) VALUES (#{name}, #{age})
insert>

Java 代码

try (SqlSession session = sqlSessionFactory.openSession()) {
  EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
  Employee newEmployee = new Employee("John", 30);
  mapper.insertEmployee(newEmployee);
  session.commit();
}

5.3 更新

XML 配置

<update id="updateEmployee" parameterType="com.example.Employee">
  UPDATE employee SET name = #{name}, age = #{age} WHERE id = #{id}
update>

Java 代码

try (SqlSession session = sqlSessionFactory.openSession()) {
  EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
  Employee existingEmployee = new Employee(1, "Jane", 25);
  mapper.updateEmployee(existingEmployee);
  session.commit();
}

5.4 删除

删除操作通常需要小心进行,以避免误删数据。

5.4.1 根据主键 ID 删除

XML 配置

<delete id="deleteById" parameterType="int">
  DELETE FROM employee WHERE id = #{id}
delete>

Java 代码

try (SqlSession session = sqlSessionFactory.openSession()) {
  EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
  mapper.deleteById(1);
  session.commit();
}

5.4.2 根据主键 ID 批量删除

XML 配置

<delete id="deleteByIds" parameterType="list">
  DELETE FROM employee WHERE id IN
  <foreach item="item" index="index" collection="list" open="(" separator="," close=")">
    #{item}
  foreach>
delete>

Java 代码

try (SqlSession session = sqlSessionFactory.openSession()) {
  EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
  List<Integer> ids = Arrays.asList(1, 2, 3);
  mapper.deleteByIds(ids);
  session.commit();
}

6. Mybatis的XML配置文件

6.1 XML配置文件规范

使用Mybatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。

在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:

  1. XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)
  2. XML映射文件的namespace属性为Mapper接口全限定名一致
  3. XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。

MyBatis详解_第6张图片