小白手把手教学用spring框架实现mybatis和mysql以及工作原理

Maven_Mybatis_Mysql

什么是Mybatis

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

简单来说,MyBatis是一个开源的持久层框架,它提供了一种简单且强大的方式来与关系型数据库进行交互。MyBatis通过使用XML或注解来定义数据库操作,并通过原生的SQL查询语句与数据库进行交互。

持久化

持久化是将程序数据在持久状态和瞬时状态间转换的机制。

  • 即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中等等。
  • JDBC就是一种持久化机制。文件IO也是一种持久化机制。
  • 在生活中 : 将鲜肉冷藏,吃的时候再解冻的方法也是。将水果做成罐头的方法也是。

为什么需要持久化服务呢?那是由于内存本身的缺陷引起的

  • 内存断电后数据会丢失,但有一些对象是无论如何都不能丢失的,比如银行账号等,遗憾的是,人们还无法保证内存永不掉电。
  • 内存过于昂贵,与硬盘、光盘等外存相比,内存的价格要高2~3个数量级,而且维持成本也高,至少需要一直供电吧。所以即使对象不需要永久保存,也会因为内存的容量限制不能一直呆在内存中,需要持久化来缓存到外存。

为什么需要Mybatis?

  • Mybatis就是帮助程序猿将数据存入数据库中 , 和从数据库中取数据 .

  • 传统的jdbc操作 , 有很多重复代码块 .比如 : 数据取出时的封装 , 数据库的建立连接等等… , 通过框架可以减少重复代码,提高开发效率 .

  • MyBatis 是一个半自动化的ORM框架 (Object Relationship Mapping) —>对象关系映射

  • 所有的事情,不用Mybatis依旧可以做到,只是用了它,所有实现会更加简单!技术没有高低之分,只有使用这个技术的人有高低之别

  • MyBatis的优点

    • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件就可以了,易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
    • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
    • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
    • 提供xml标签,支持编写动态sql。

工作原理

我们知道,JDBC有四个核心对象:
(1)DriverManager,用于注册数据库连接
(2)Connection,与数据库连接对象
(3)Statement/PrepareStatement,操作数据库SQL语句的对象
(4)ResultSet,结果集或一张虚拟表

而MyBatis也有四大核心对象:
(1)SqlSession对象,该对象中包含了执行SQL语句的所有方法。类似于JDBC里面的Connection 。
(2)Executor接口,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。类似于JDBC里面的Statement/PrepareStatement。
(3)MappedStatement对象,该对象是对映射SQL的封装,用于存储要映射的SQL语句的id、参数等信息。
(4)ResultHandler对象,用于对返回的结果进行处理,最终得到自己想要的数据格式或类型。可以自定义返回类型

在JDBC中,Connection不直接执行SQL方法,而是利用Statement或者PrepareStatement来执行方法。在使用JDBC建立了连接之后,可以使用Connection接口的createStatement()方法来获取Statement对象,也可以调用prepareStatement()方法获得PrepareStatement对象,通过executeUpdate()方法来执行SQL语句。而在MyBatis中,SqlSession对象包含了执行SQL语句的所有方法,但是它是委托Executor执行的。从某种意义上来看,MyBatis里面的SqlSession类似于JDBC中的Connection,他们都是委托给其他类去执行。

image-20241030173317584

  1. 从配置文件中读取信息,mybatis-config.xml为MyBatis的全局配置文件,用于配置数据库连接信息。

    <?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/mybatis?serverTimezone=UTC"/>
                    <property name="username" value="root"/>
                    <property name="password" value="xxxxx"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="Mapper/UserMapper.xml"/>
        </mappers>
    </configuration>
    
  2. 加载映射文件。映射文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。

    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.ivanlee.pojo.User">
        <select id="findById" parameterType="int" resultType="com.ivanlee.pojo.User">
            select * from users where uid = #{id}
        </select>
    </mapper>
    
  3. 构造会话工厂。通过MyBatis的环境配置信息构建会话工厂SqlSessionFactory。SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);

  4. 创建会话对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。SqlSession session = sqlMapper.openSession();

  5. Executor执行器。MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。

  6. MappedStatement对象。在Executor接口的执行方法中有一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等信息。

  7. 输入参数映射。输入参数类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。

  8. 输出结果映射。输出结果类型可以是Map、List等集合类型,也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程。

POJO

POJO是“Plain Old Java Object”的缩写,直译为“简单老式Java对象”。这个术语最早出现在Java社区中,用以描述那些没有遵循特定设计模式、没有继承特定类、也没有实现特定接口的普通Java对象。简而言之,POJO类就是最基础的Java类,也可以理解为普通的Java类。例如如下代码:

public class User {
    private int uid;
    private String uname;
    private int uage;
    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public int getUage() {
        return uage;
    }
    public void setUage(int uage) {
        this.uage = uage;
    }
}

在与数据库交互时,POJO类可以作为持久化对象,将数据库中的表映射为Java对象,方便程序员进行数据库操作。为什么说POJO的设计更能简化开发?其实本质上就是我们在开发中先定义核心的POJO,比如上面的User类,它与我们的业务相关,它是关于用户数据承载的类,但我们只是简单的基于面向对象设计理念,将用户抽象为一个User类,它具有用户相关的属性描述,此时基于面向对象OO、基本的Java语言规范以及基本的开发规范(属性private、对外getter、setter)就完成了一个基本的POJO。其他人一看,它就是一个纯粹的Java对象罢了,它有基本的属性和方法。

代码样例

image-20241031110933721

这是整个的代码结构,根据前面讲到的mybatis配置设定这种目录结构,会比较清晰。首先我们先建一个数据库,然后用idea连接上。

image-20241030113434304

image-20241030113534231

image-20241030113922690

连接好以后就可以写一下数据库的配置文件,db.properties

mysql.driver=com.mysql.cj.jdbc.Driver
mysql.username=root
mysql.password=xxxxx
mysql.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
package com.ivanlee.test;
import com.ivanlee.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 org.junit.Test;
import java.io.Reader;
import java.io.IOException;

public class UserTest {
    @Test
    public void userFindByTest() {
        String resources = "mybatis-config.xml";
        Reader reader = null;
        try {
            reader = Resources.getResourceAsReader(resources);
        }catch (IOException e) {
            e.printStackTrace();
        }
        SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = sqlMapper.openSession();
        User user = session.selectOne("findById",1);
        System.out.println("姓名\t年龄");
        System.out.println(user.getUname()+"\t"+user.getUage());
        session.close();
    }
}

新建一个user类用来进行测试,"findById" 是一个 SQL 语句的标识符,它通常定义在一个 MyBatis 的映射文件(XML 文件或注解方式)中。这个标识符对应于一个具体的 SQL 查询语句,用于从数据库中查询数据。1 是传递给 SQL 语句的参数,表示你要查找的记录的主键值。image-20241031112712516

这里的findById是我们在mapper映射里定义好的方法,不是java库定义的

如果想打印更多的信息,我们还可以继续添加搜索方式,写到mapper里面。image-20241031114828054

List<User> users = session.selectList("findAll");
System.out.println("姓名\t年龄");
for(User user: users){
    System.out.println(user.getUname()+"\t"+user.getUage());
}

image-20241031114858280

posted @ 2024-10-31 11:53  ivanlee717  阅读(159)  评论(0编辑  收藏  举报