写给新手看的 MyBatis 入门

目录

  • MyBatis 使用前的准备
    • 什么是 MyBatis
    • 使用Maven 进行 MyBatis 开发环境搭建
  • MyBatis 入门
    • 项目整体结构一览
    • MyBatis 的简单生命周期
      • 1.获取 SqlSessionFactory
      • 2.通过 SqlSession 实例和映射器 mapper 执行 sql 语句

最近新接触了 MyBatis,这里主要参考网上各个博客以及官网的文档以及个人的一些理解,讲一下对 MyBatis 实现简单增删改查的方法。

MyBatis 使用前的准备

什么是 MyBatis

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

使用Maven 进行 MyBatis 开发环境搭建

要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于 classpath 中即可。

如果使用 Maven 来构建项目,则需将下面的 dependency 代码置于 pom.xml 文件中:


  org.mybatis
  mybatis
  x.x.x

一般来说,在我们开发过程中会使用 IDEA 来开发,我们要搭建一个 MyBatis 和 MySql 的项目,只要简单地 NewProject -> Maven 选择新建一个空的 Maven 项目,然后在 pom.xml 中将上面的 dependcy 丢进去就好,允许右下角 maven 的 enable auto-import ,IDEA 就会帮我们自动下载相关的 jar 包了。作为新手,如果不明白如何使用 Maven,那么这篇文章可能对你作用有限,作为一个广泛使用的工具,强烈建议没接触过的小伙伴去学习一下如何使用。

这里给出一个示例的 pom.xml :



    4.0.0

    com.studymybatis
    MyBatisStudy
    1.0-SNAPSHOT

    
    
        
            org.mybatis
            mybatis
            3.3.0
        

        
        
            junit
            junit
            4.12
        

        
            mysql
            mysql-connector-java
            8.0.12
        

        
            org.slf4j
            slf4j-api
            1.7.12
        
        
            org.slf4j
            slf4j-log4j12
            1.7.12
        
        
            log4j
            log4j
            1.2.17
        
        
            tk.mybatis
            mapper
            4.1.5
            test
        

    

MyBatis 入门

项目整体结构一览

这里我们先通过在 Java 代码中使用 MyBatis 的 demo 来讲解 MyBatis 入门所需的知识。

首先看看整体的项目结构

写给新手看的 MyBatis 入门_第1张图片

使用到的数据库表结构

写给新手看的 MyBatis 入门_第2张图片

下面是一个新建的 MyBatisDemo 类,main 方法中使用了构建好的 MyBatis 来访问数据库:

import entity.User;
import mapper.UserMapper;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**
 * mybatis demo
 *
 * @author Byight
 */
public class MyBatisDemo {
    public static void main(String[] args) {
        /**
         * 第一步:要先获取 SqlSessionFactory, MyBatis 的每一个操作都以 SqlSessionFactory 为核心
         *
         * SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。
         * 而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例。
         */
        // 比较推荐的是我们代码中使用的第一种方法;即使用 xml 来构建,如下文使用的代码
        // 设置 mybatis 的 xml 配置文件路径
        String xmlConfigResource = "conf.xml";
        // 使用MyBatis 的 Resources 的工具类,从指定 classpath 或其他位置加载资源文件更加容易
        // 在这里使用 Resources 从指定 classpath 加载了 xml 配置文件
        InputStream resourceAsStream = MyBatisDemo.class.getClassLoader().getResourceAsStream(xmlConfigResource);
        // 构建sqlSession的工厂
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        /**
         * 有了 session 工厂后就可以创建 session 实例,然后使用 session 实例来使用映射器(map)执行 sql 语句了
         * 同样有两种方式,但我们强烈推荐后面的方法
         * 使用正确描述每个语句的参数和返回值的接口(比如 BlogMapper.class)
         * 不仅可以执行更清晰和类型安全的代码,而且还不用担心易错的字符串字面值以及强制类型转换。
         */
        // 不推荐的方法
        /*
        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 映射sql的标识字符串
            String statement = "mapper.UserMapper.queryUserById";
            // 执行查询返回一个唯一user对象的sql
            User user = session.selectOne(statement, 2);
            System.out.println(user);
        }
        */
        // 第二种方法有很多优势
        // 首先它不依赖于字符串字面值,会更安全一点;
        // 其次,如果你的 IDE 有代码补全功能,那么代码补全可以帮你快速选择已映射的 SQL 语句。
        try (SqlSession session = sqlSessionFactory.openSession()) {
            UserMapper mapper = session.getMapper(UserMapper.class);
            User user = mapper.queryUserById(2);
            System.out.println(user);
        }
    }
}

上面的代码有很详细的注释。我们以上面的代码为基础,将整个生命周期分为:1.获取 SqlSessionFactory 对象和2.使用 SqlSession 示例及映射器 mapper 执行 Sql 语句这两部分来讲解。

MyBatis 的简单生命周期

1.获取 SqlSessionFactory

对于 MyBatis 的使用,我们首先要知道,MyBatis 的每一个操作都以 SqlSession 为核心:对于 MyBatis ,可以认为它是通过 SqlSession 来执行 Sql 的相关语句。

在 MyBatis 中,我们需要使用 SqlSessionFactory 来获取 SqlSession 的实例,相当于 SqlSession 这种对象的制造工厂,能够通过其方法返回给使用者 SqlSession 的实例。当使用时我们要先构建 一个 SqlSeesionFactory 来获取 SqlSession 对象。

SqlSessionFactory 的实例需要通过 SqlSessionFactoryBuilder 获得。SqlSessionFactoryBuilder 需要给定它 MyBatis 的 xml 配置文件进行解析(或者是一个已经设定好的 Configuration 的实例),这样它能够为我们返回一个按照我们配置要求的 SqlSessionFactory 的实例。

我们有两种方法使用,我们推荐使用 xml 构建:

        // 比较推荐的是我们代码中使用的第一种方法;即使用 xml 来构建,如下文使用的代码
        // 设置 mybatis 的 xml 配置文件路径
        String xmlConfigResource = "conf.xml";
        // 使用MyBatis 的 Resources 的工具类,从指定 classpath 或其他位置加载资源文件更加容易
        // 在这里使用 Resources 从指定 classpath 加载了 xml 配置文件
        InputStream resourceAsStream = MyBatisDemo.class.getClassLoader().getResourceAsStream(xmlConfigResource);

        // 构建sqlSession的工厂
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

1.1 Resource 加载指定的配置文件

在执行前面代码中的MyBatisDemo.class.getClassLoader().getResourceAsStream(xmlConfigResource)`时,Resource的工具类会寻找对应的 xml 配置文件进行加载

这里我们是指定的配置文件是 conf.xml





   
   
   

   
       
       
       
       
   

   
   
       
           
           

           
           
           
           
           
               
               
               
               
               
           
       
   

   
       
       
       
       
   

如果对应路径找不到相应的 xml 配置文件的话,getResourceAsStream 方法便会报错,成功的话则会继续执行代码,通过 SqlSessionFactionBuilder 来对配置文件进行解析。

1.2 SqlSessionFactionBuilder 解析 xml 配置文件

SqlSessionFactionBuilder 会自上而下地对 xml 配置文件进行可行性的校验,除了 xml 文件开头固定的两行外,主要是看标签中的配置。

自上而下地查看 configuration 的标签体信息,我们会首先看到标签,它与后面的 enviroments 标签体中的datasource文件相结合来对数据库连接相关属性进行配置。

对于最先看到的mysql.properties,这里也给出了一个示例,大家使用的时候记得替换成自己的信息,这里等号 = 左边的属性名即是和上面 xml 文件的 datasource 的 property 标签中的 value 值:

jdbc.databaseurl=jdbc:mysql://服务器配置地址:默认为3306的数据库端口号/数据库名称?serverTimezone=GMT%2B8
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.username=数据库账号
jdbc.password=数据库密码

Alias 标签体是在后面会提到的 mapper 映射中产生作用,这里不理解也没有关系,知道它是写在 xml 配置文件就好了。

第一次使用 MyBatis 的同学可能会对mappers这个标签产生疑惑,它是指 MyBatis 中一种映射,在入门时我们可以简单理解为是用于执行 Sql 语句的特殊语法,接下去我们对它进行一定的说明。

1.3 SqlSessionFactionBuilder 校验 xml 配置文件中的 mapper 映射文件是否存在

在前面代码的标签中,我们可以看到里面有不同的映射文件路径:

    
        
        
        
        
    

xml 配置文件会以项目根目录为基础路径(注意并不是 xml 配置文件的相对路径)来寻找制定的 mapper 映射,其中项目根目录即是 java 和 resources 目录下的文件。

假设这里我们的文件树结构是这样的(这里为了示例将 conf.xml 放在了 mpper 包里,实际上不符合代码规范):

写给新手看的 MyBatis 入门_第3张图片

这里虽然 conf.xml 是在 mapper 目录下而不是根路径,与需要的 userMapper.xml 在同一个包中,但在指定其路径我们仍然需要指定其路径为mapper/userMapper.xml

1.4 校验 mapper 映射文件配置(命名空间)的正确性

我们看一下前面指定的 mapper 映射文件,这里我直接贴出项目中的 userMapper.xml 文件:







    
    
    
    
    

    
    

这里我们可以先不用关注 SELECT * FROM users WHERE id=#{id}

第一种方法中,我们声明了一个 statement 字符串,字符串的内容其实是一个类似于调用方式的指令:

mapper.UserMapper.queryUserById,它会在后面 session 执行 selectOne 方法时(因为 Sql 语句实际上是返回一个记录的 SELECT 语句,其它方法这里不再举例)。实际上就是通过mapper.Usermapper这个字段(注意这个字段和 userMapper.xml 的命名空间相同),告诉 session 在配置文件 conf.xml 的 mapper 标签体中遍历映射器,找到其中命名空间与这个字段相同的映射器 mapper(所以在这里它会找到 userMapper.xml),然后去执行后面的字段queryUserById,也就是寻找到了我们写的 select 标签(因为它的标签 id 是这个),执行其中的 Sql 语句。它只要求前面列出的命名空间是唯一且能找到的,所以上面的第一种方法去掉注释后也可以运行。

接下去我们讲讲第二种方法,这是 MyBatis 官方推荐的写法:

        try (SqlSession session = sqlSessionFactory.openSession()) {
            UserMapper mapper = session.getMapper(UserMapper.class);
            User user = mapper.queryUserById(2);
            System.out.println(user);
        }

同时为了方便理解,这里再次贴出项目的结构图:

写给新手看的 MyBatis 入门_第4张图片

很明显,在 try 语句中首先定义了一个 UserMapper 接口,前面文章有认真看的小伙伴可以发现,前面 userMapper 的命名空间定义就是与此有关,没注意的可以稍微往上看看 userMapper.xml 的代码注释。其实就是相当于将 userMapper.xml 这个映射器和 UserMapper 接口相绑定了,当我们这样使用时,MyBatis 就知道代码应该找到 userMapper.xml 这个映射器来执行 Sql 语句。

既然相互绑定,那么 UserMapper 这个接口要怎么写呢?其实很简单,只要和映射器 userMapper.xml 中的 sql 语句 id 相对应就可以了:

package mapper;

import entity.User;

/**
 * 与 userMapper.xml 相绑定
 * 
 * @author Bylight
 */
public interface UserMapper {
    User queryUserById(int id);
}

可以看到,我们只要保证其中方法和 userMapper 相对应。但我们怎么确定它的返回值和参数,又怎么保证传入参数被正确的放在 Sql 语句中呢?我们接下来简单的介绍一下 Sql 语句相关的知识。

2.2 在映射器 mapper 中写 Sql 语句

在这里我们吧 userMapper.xml 中的 select 标签单独拎出来看看:

    

我们需要关注以下几个东西:

  • 标签名:这里是 select,也就是表示这个 Sql 语句是一个查询语句。其他的还有 updata、insert 和 delete,各自对应数据库的增删改查操作。

  • id:设置 select 标签的id属性为 queryUserById,id属性值必须是唯一的,不能重复。这里的 id 就是对应的接口中代表这个语句的方法名,也是使用第一种方法时调用这个 Sql 语句的句柄。

  • parameterType:指明传入的参数类型,这里我们需要传入的是 id,属于 int 类型。

  • resultType:指明 Sql 语句返回的结果集类型,表示将查询结果封装成一个User类的对象返回。

    这里我们是定义了一个和表结构相符合的 User 实体类,它仅具备 getter 和 setter 以及 toString 方法,具体代码会在后面贴出。

    但当前路径中找不到User,所以在加载时,会去往加载的配置文件中查找对应的 alias 对应的资源路径(type),这里就知道前面我们在 conf.xml 中的 alias 标签的作用了:

        
            
            
            
            
        

    这样我们就可以在 resultType 中直接使用 User 了,如果没有使用别名,那么我们每次都要使用 entity.User。

  • #{id}:这表示传入的int参数是放在这的,我们在 UserMapper 中也要传入相同名称的参数。

    这里关于 # 占位符,有必要特别说明一下 # 和 $ 的区别:

    一般能用#{}的就别用${}

    #{}会将sql语句编译好并使用占位符?然后再进行取值(值转换成字符串)很大的程度防止sql注入

    ${}先取值(不做任何处理直接引用)然后再去编译sql语句,无法防止sql注入,一般用于传入数据库对象,例如传入表名。

好了,到这里一个基础的 MyBatis 实现增删改查就可以实现了。更多的参数和 Sql 语句的其它操作可以看官网的说明,这里就不多说了。

你可能感兴趣的:(写给新手看的 MyBatis 入门)