notebook notebook
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)

学习笔记

啦啦啦,向太阳~
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)
  • Java开发

    • My

    • Posts

    • Java SE

    • Java 并发编程

    • JVM

    • JDBC

    • Java Web

    • Spring 与 SpringMVC

    • Spring Boot

    • Spring Cloud

    • Spring Security

    • Netty

    • MyBatis

      • 动力节点课程-MyBatis

        • MyBatis 概述与入门
          • 1. MyBatis 概述
            • 1.1 JDBC 的不足
            • 1.2 了解 MyBatis
          • 2. MyBatis 入门程序
            • 2.1 引入的依赖
            • 2.2 MyBatis 中两个主要的配置文件
            • 2.3 编写 MyBatis 程序
            • 2.4 MyBatis 中的事务管理机制
          • 3. 使用 JUnit
          • 4. 引入日志框架 LogBack
            • 4.1 MyBatis 支持的日志组件
            • 4.2 引入 Logback 的步骤
          • 5. MyBatis 工具类 SqlSessionUtil 的封装
        • 使用 MyBatis 完成 CRUD
        • MyBatis 核心配置文件详解
        • MVC 中使用 MyBatis
        • MyBatis 使用小技巧
        • 参数处理、查询返回与动态 SQL
        • MyBatis 的高级映射和缓存机制
  • Python开发

  • Golang开发

  • Git

  • 软件设计与架构

  • 大数据与分布式系统

  • 区块链

  • Nginx

  • 开发
  • Java开发
  • MyBatis
  • 动力节点课程-MyBatis
yubin
2023-08-05
目录

MyBatis 概述与入门

# 1. MyBatis 概述

# 1.1 JDBC 的不足

一个 JDBC 的示例程序如下:

String sql = "INSERT INTO t_user(...) ...";
PreparedStatement ps = conn.prepareStatement(sql);
...
int count = ps.executeUpdate();
1
2
3
4

或者:

String sql = "SELECT * FROM t_user";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
    String id = rs.getString("id");
    ...
}
1
2
3
4
5
6
7

JDBC 存在的不足:

  • SQL 语句写死在 Java 程序中,改动 SQL 的话就要改 Java 代码,违背了开闭原则;
  • 书写复杂,Java 对象与 SQL 的交互十分繁琐,能不能自动化?

# 1.2 了解 MyBatis

以 jar 包的形式存在,本质上就是对 JDBC 的封装,是对 SQL 的一种 mapper,在 MVC 中负责数据持久化。

# 2. MyBatis 入门程序

软件版本:

  • MySQL 8.0.30
  • MySQL driver:8.0.30
  • MyBatis:3.5.10
  • JDK 17
  • JUnit 4.13.2
  • Logback 1.2.11

以下的内容可以结合 MyBatis 官方文档 (opens new window) 来看。

# 2.1 引入的依赖

Maven 中需要引入的依赖:

  • MyBatis 依赖
  • MySQL 驱动依赖

# 2.2 MyBatis 中两个主要的配置文件

  1. mybatis-config.xml:核心配置文件,主要配置连接数据库的信息等,只有一个
  2. XxxMapper.xml:专门用来编写 SQL 语句的配置文件,往往一个表一个

# 2.2.1 mybatis-config.xml

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.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/powernode"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--sql映射文件创建好之后,需要将该文件路径配置到这里-->
        <mapper resource="org/mybatis/example/CarMapper.xml"/>
    </mappers>
</configuration>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

这个文件用来构建一个 SqlSessionFactory 对象。

结尾处的 <mapper resource=""/> 这行代码用来指定 XxxMapper.xml 文件的路径,且自动从类的根路径下开始查找资源。

# 2.2.2 XxxMapper.xml

一个 CarMapper.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="org.mybatis.example.CarMapper">
    <!--insert sql:保存一个汽车信息-->
    <insert id="insertCar">
        insert into t_car
            (id,car_num,brand,guide_price,produce_time,car_type) 
        values
            (null,'102','丰田mirai',40.30,'2014-10-05','氢能源')
    </insert>
</mapper>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  • id 是这条 SQL 语句的唯一标识。

# 2.3 编写 MyBatis 程序

在 MyBatis 中,SqlSession 对象负责执行 SQL 语句,它是一个 Java 程序和数据库之间的一次会话。

  • 要想获得 SQLSession 对象,需要先获取 SqlSessionFactory 对象,然后用它来生产 SqlSession 对象。
  • 怎么获取 SqlSesionFactory 对象呢?需要先获取 SqlSessionFactoryBuilder 对象,再使用 builder 的 build() 方法来获取一个 SqlSessionFactory 对象。

因此,MyBatis 的核心对象包括:

  • SqlSessionFactoryBuilder
  • SqlSessionFactory
  • SqlSession

一个比较完整的 MyBatis 程序:

package com.powernode.mybatis;

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;

/**
 * 比较完整的第一个 mybatis 程序写法
 */
public class MyBatisCompleteCodeTest {
    public static void main(String[] args) {
        SqlSession sqlSession = null;
        try {
            // 1.创建SqlSessionFactoryBuilder对象
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            // 2.创建SqlSessionFactory对象
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
            // 3.创建SqlSession对象
            sqlSession = sqlSessionFactory.openSession();
            // 4.执行SQL
            int count = sqlSession.insert("insertCar");  // 这里传入的是 SQL 语句的 id
            System.out.println("更新了几条记录:" + count);
            // 5.提交
            sqlSession.commit();
        } catch (Exception e) {
            // 回滚
            if (sqlSession != null) {
                sqlSession.rollback();
            }
            e.printStackTrace();
        } finally {
            // 6.关闭
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

注意点:

  • 在这里 SqlSession 需要手动提交,即需要手动调用 commit() 方法
  • 传入 SqlSession 进行调用的是在 mapper.xml 中编写的 SQL 的 id,不是一个 SQL 语句

关于第一个 MyBatis 程序的小细节:

  • mapper.xml 中的 SQL 语句的结尾的分号可写可不写
  • Resources.getResourceAsStream
    • 小技巧:以后凡是遇到 resource 这个单词,大部分情况下这种加载资源的方式就是从类的根路径下开始加载(或开始查找)
  • mybatis 核心配置文件的名字不一定非得是 mybatis-config.xml,而且它存放的路径也不一定非得是在类的根路径下
    • 当然,mapper.xml 也是如此
    • 但最好还是遵循约定
  • 加载资源的 Resources.getResourceAsStream() 方法本质上还是在调用类加载的 ClassLoader.getSystemClassLoader().getResourceAsStream() 方法

# 2.4 MyBatis 中的事务管理机制

在 mybatis-config.xml 文件中,可以通过以下的配置来进行 MyBatis 的事务管理:<transactionManager type="JDBC"/>

其中 type 属性的值包括两个,对应了 MyBatis 提供的两种事务管理机制:

  • JDBC:JDBC 事务管理器
  • MANAGED:MANAGED 事务管理器

type 的值只有以上两个值可选,不区分大小写

# 2.4.1 JDBC 事务管理器

表示 MyBatis 框架自己管理事务,自己采用原生的 JDBC 代码去管理事务:

conn.setAutoCommit(false);  // 开启事务
...业务处理...
conn.commit();  // 手动提交事务
1
2
3

使用 JDBC 事务管理器的话,底层创建的事务管理器对象:JdbcTransaction 对象。

如果你编写的代码是:SqlSession sess = sqlSessionFactory.openSession(true);,那表示没有开启事务,因为这样 MyBatis 就不会执行 conn.setAutoCommit(false)。

在 JDBC 事务中,没有执行 conn.setAutoCommit(false) 就默认 autoCommit 为 true,而如果 autoCommit 为 true,那就表示没有开启事务,这样只要执行任意一条 DML 语句就会 commit 一次。因此不推荐这样的做法,而是应该开启事务。

# 2.4.2 MANAGED 事务管理器

表示 MyBatis 不再负责事务的管理了,而是把事务管理交给其他容器来负责,比如 Spring 容器。

如果我们只是单纯使用 MyBatis 库,且配置为 MANAHED 事务,那么事务这块就没人管了,没人管理事务就表示事务压根不会开启,即没有事务了。

重点

以后注意,只要你的 autoCommit 是 true,就表示没有开启事务。只有你的 autoCommit 是 false 的时候,才表示开启了事务。

# 3. 使用 JUnit

JUnit 是做单元测试的,这里使用 JUnit 只是为了验证我们的程序,避免写过多的 main 方法,而不是为了单元测试。

JUnit 依赖:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>
1
2
3
4
5
6

编写单元测试类:

// 测试用例
public class CarMapperTest{
    
    // 测试方法
    @Test
    public void testInsert(){}
    
    @Test
    public void testUpdate(){}
    
}
1
2
3
4
5
6
7
8
9
10
11

# 4. 引入日志框架 LogBack

MyBatis 集成日志组件可以让我们调试起来更加方便。

# 4.1 MyBatis 支持的日志组件

MyBatis 常见的集成的日志组件有哪些呢?这可以参考文档中的配置项:

20230805173239

其中 STDOUT_LOGGING 是标准日志,MyBatis 已经实现了这种标准日志,我们只要开启即可。

开启的方式就是在 mybatis-config.xml 中使用 settings 标签进行配置开启:

<settings>
  <setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
1
2
3

标准日志也可以用,可以看到 SQL 语句是怎样的、连接对象什么时候创建的等信息,但是配置不够灵活,也看不到详细的日期、线程名字等。如果想使用更加丰富的配置,可以继承第三方的 log 组件。

SLF4J(沙拉风)也是一个日志标准,而且 logback 实现了 SLF4J 规范。Logback 是目前日志框架中性能较好的、较流行的,所以我们选择它。

# 4.2 引入 Logback 的步骤

Logback 实现了 SLF4J 标准。

第一步:引入 logback 依赖:

<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.2.11</version>
  <scope>test</scope>
</dependency>
1
2
3
4
5
6

第二步:引入 logback 相关配置文件

  • 这个配置文件的名字必须叫做 logback.xml 或者 logback-test.xml,不能是其他的名字
  • 这个配置文件必须放到类的根路径下,不能是其他位置

logback.xml 如下(可以直接 copy 然后使用),用来配置格式等:

<?xml version="1.0" encoding="UTF-8"?>

<configuration debug="false">
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>100MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <!--mybatis log configure-->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>

    <!-- 日志输出级别,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR -->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE"/>
    </root>

</configuration>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

这时候再去执行 mybatis 程序,就可以看到输出中有实际执行的 SQL 语句了。

# 5. MyBatis 工具类 SqlSessionUtil 的封装

由于每次获取 SqlSession 对象的代码太繁琐了,所以这里封装一个工具类,用来获取 SqlSession:

package com.powernode.mybatis.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**
 * MyBatis工具类
 */
public class SqlSessionUtil {
    private static SqlSessionFactory sqlSessionFactory;

    /**
     * 类加载时初始化sqlSessionFactory对象
     */
    static {
        try {
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 每调用一次openSession()可获取一个新的会话,该会话支持自动提交。
     *
     * @return 新的会话对象
     */
    public static SqlSession openSession() {
        return sqlSessionFactory.openSession(true);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
编辑 (opens new window)
上次更新: 2023/08/05, 11:51:22
Netty 优化
使用 MyBatis 完成 CRUD

← Netty 优化 使用 MyBatis 完成 CRUD→

最近更新
01
Deep Reinforcement Learning
10-03
02
误删数据后怎么办
04-06
03
MySQL 一主多从
03-22
更多文章>
Theme by Vdoing | Copyright © 2021-2024 yubincloud | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×