首页 > 其他分享 >MyBatis实战指南(二):工作原理与基础使用详解

MyBatis实战指南(二):工作原理与基础使用详解

时间:2024-01-10 17:33:41浏览次数:23  
标签:指南 映射 接口 详解 SQL MyBatis 加载 延迟

MyBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。那么,它是如何工作的呢?又如何进行基础的使用呢?本文将带你了解MyBatis的工作原理及基础使用。

一、MyBatis的工作原理

1.1 MyBatis的工作原理

工作原理图示: image.png

1、读取MyBatis配置文件

mybatis-config.xml为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,例如数据库连接信息。

2、加载映射文件(SQL映射文件,一般是XXXMapper.xml)

该文件中配置了操作数据库的SQL语句,需要在MyBatis配置文件mybatis-config.xml中加载。

XXXMapper.xml可以在mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表。

3、构造会话工厂

通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。

4、创建会话对象

由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。

5、Executor执行器

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

6、MappedStatement对象

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

7、输入参数映射

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

8、输出结果映射

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

1.2 MyBatis架构

image.png

API接口层

提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。

MyBatis和数据库的交互有两种方式:使用传统的MyBatis提供的API、使用Mapper接口。

1)使用传统的MyBatis提供的API 这是传统的传递Statement Id和查询参数给SqlSession对象,使用SqlSession对象完成和数据库的交互; image.png MyBatis提供了非常方便和简单的API,供用户实现对数据库的增删改查数据操作,以及对数据库连接信息和MyBatis自身配置信息的维护操作。 示例:

SqlSession session = sqlSessionFactory.openSession();
Category c = new Category();
c.setName("新增加的Category");
session.insert("addCategory",c);

上述使用MyBatis的方法,是创建一个和数据库打交道的SqlSession对象,然后根据Statement Id和参数来操作数据库,这种方式固然很简单和实用,但是它不符合面向对象语言的概念和面向接口编程的编程习惯。

2)使用Mapper接口

MyBatis将配置文件中的每一个<mapper>节点抽象为一个Mapper接口,而这个接口中声明的方法和跟<mapper>节点中的<select|update|delete|insert>节点项对应,即<select|update|delete|insert>节点的id值为Mapper接口中的方法名称,parameterType值表示Mapper对应方法的入参类型,而resultMap值则对应了Mapper接口表示的返回值类型或者返回结果集的元素类型。

示例:

SqlSession session = sqlSessionFactory.openSession();
CategoryMapper mapper = session.getMapper(CategoryMapper.class);
List<Category> cs = mapper.list();
for (Category c : cs) {
     System.out.println(c.getName());
 }

根据MyBatis的配置规范配置后,通过SqlSession.getMapper(XXXMapper.class)方法,MyBatis会根据相应的接口声明的方法信息,通过动态代理机制生成一个Mapper实例。 image.png

使用Mapper接口的某一个方法时,MyBatis会根据这个方法的方法名和参数类型,确定Statement Id,底层还是通过SqlSession.select(“statementId”,parameterObject)或者SqlSession.update(“statementId”,parameterObject)等等来实现对数据库的操作。

MyBatis引用Mapper接口这种调用方式,纯粹是为了满足面向接口编程的需要。

数据处理层

负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。

1)参数映射和动态SQL语句生成

动态语句生成可以说是MyBatis框架非常优雅的一个设计,MyBatis通过传入的参数值,使用OGNL表达式来动态地构造SQL语句,使得MyBatis有很强的灵活性和扩展性。 image.png 参数映射指的是对于Java数据类型和JDBC数据类型之间的转换,这里包括两个过程:

  • 查询阶段,我们要将java类型的数据,转换成JDBC类型的数据,通过preparedStatement.setXXX()来设值;

  • 另一个就是对ResultSet查询结果集的JdbcType 数据转换成Java数据类型。

2)SQL语句的执行以及封装查询结果集成List< E>

动态SQL语句生成之后,MyBatis将执行SQL语句并将可能返回的结果集转换成List<E> 。

MyBatis 在对结果集的处理中,支持结果集关系一对多和多对一的转换,并且有两种支持方式,一种为嵌套查询语句的查询,还有一种是嵌套结果集的查询。

基础支撑层

负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

MyBatis层次结构

image.png

1.3 Executor执行器

Executor的类别

Mybatis有三种基本的Executor执行器:SimpleExecutor、ReuseExecutor和BatchExecutor。

image.png

1、SimpleExecutor

每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

2、ReuseExecutor

执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map<String, Statement>内,供下一次使用。简言之,就是重复使用Statement对象。

3、BatchExecutor

执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

作用范围: Executor的这些特点,都严格限制在SqlSession生命周期范围内。

Executor的配置

指定Executor方式有两种:

1、在配置文件中指定

<settings>
    <setting name="defaultExecutorType" value="BATCH" />
</settings>

2、在代码中指定

在获取SqlSession时设置,需要注意的时是,如果选择的是批量执行器时,需要手工提交事务(默认不传参就是SimpleExecutor)。

示例:

// 获取指定执行器的sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
// 获取批量执行器时, 需要手动提交事务
sqlSession.commit();

1.4 Mybatis是否支持延迟加载

延迟加载是什么

MyBatis中的延迟加载,也称为懒加载,是指在进行表的关联查询时,按照设置延迟规则推迟对关联对象的select查询。

例如在进行一对多查询的时候,只查询出一方,当程序中需要多方的数据时,mybatis再发出sql语句进行查询,这样子延迟加载就可以的减少数据库压力。

MyBatis 的延迟加载只是对关联对象的查询有迟延设置,对于主加载对象都是直接执行查询语句的。

假如Clazz 类中有子对象HeadTeacher。两者的关系:

public class Clazz {
private Set<HeadTeacher> headTeacher;
//...
}

是否查出关联对象的示例:

@Test
     public void testClazz() {
        ClazzDao clazzDao = sqlSession.getMapper(ClazzDao.class);
        Clazz clazz = clazzDao.queryClazzById(1);
        //只查出主对象
        System.out.println(clazz.getClassName());            
        //需要查出关联对象
        System.out.println(clazz.getHeadTeacher().size());   
  }

延迟加载的设置

在Mybatis中,延迟加载可以分为两种:延迟加载属性和延迟加载集合,association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。

在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。

1)延迟加载的全局设置

延迟加载默认是关闭的。如果需要打开,需要在mybatis-config.xml中修改:

<settings>
         
 <setting name="lazyLoadingEnabled" value="true" />
         
 <setting name="aggressiveLazyLoading" value="false"/>
</settings>

比如class班级与student学生之间是一对多关系。在加载时,可以先加载class数据,当需要使用到student数据时,我们再加载 student 的相关数据。

  • 侵入式延迟加载: 指的是只要主表的任一属性加载,就会触发延迟加载,比如:class的name被加载,student信息就会被触发加载。

  • 深度延迟加载: 指的是只有关联的从表信息被加载,延迟加载才会被触发。通常,更倾向使用深度延迟加载。

2)延迟加载的局部设置

如果设置了全局加载,但是希望在某一个sql语句查询的时候不适用延时策略,可以配置局部的加载策略。

示例:

 <association
     property="dept" select="com.test.dao.DeptDao.getDeptAndEmpsBySimple"
     column="deptno" fetchType="eager"/>

etchType值有2种,

  • eager:立即加载;

  • lazy:延迟加载。

由于局部的加载策略的优先级高于全局的加载策略。指定属性后,将在映射中忽略全局配置参数lazyLoadingEnabled,使用属性的值。

延迟加载的原理

MyBatis使用Java动态代理来为查询对象生成一个代理对象。当访问代理对象的属性时,MyBatis会检查该属性是否需要进行延迟加载。如果需要延迟加载,则MyBatis将再次执行SQL查询,并将查询结果填充到代理对象中。

二、MyBatis基础使用示例

1、添加MyBatis依赖

首先,我们需要在项目中添加MyBatis的依赖。如果你使用的是Maven项目,可以在pom.xml文件中添加以下依赖:

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
</dependency>

2、创建实体类

假设我们有一个用户表(user),我们可以创建一个对应的实体类User:

public class User {
    private int id;
    private String name;
    private int age;
    // getter和setter方法省略
}

3、创建映射文件UserMapper.xml

在MyBatis的映射文件中,我们需要定义一个与实体类对应的接口。例如,我们可以创建一个名为UserMapper的接口:

<?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">
<mapper namespace="com.example.UserMapper">
    <select id="getUserById" parameterType="int" resultType="com.example.User">
        SELECT * FROM user WHERE id = #{id}
    </select>
</mapper>

4、创建接口UserMapper.java

接下来,我们需要创建一个与映射文件对应的接口。例如,我们可以创建一个名为UserMapper的接口:

package com.example;

import com.example.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

public interface UserMapper {
    @Select("SELECT * FROM user WHERE id = #{id}")
    User getUserById(@Param("id") int id);
}

5、使用MyBatis进行数据库操作

最后,我们可以在业务代码中使用MyBatis进行数据库操作。例如,我们可以在一个名为UserService的类中调用UserMapper接口的方法:

public class UserService {
    public User getUserById(int id) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserById(id);
        sqlSession.close();
        return user;
    }
}

总结:

MyBatis是一个非常强大的持久层框架,它可以帮助我们简化数据库操作,提高开发效率。在实际开发中,我们还可以使用MyBatis进行更复杂的数据库操作,如插入、更新、删除等。希望这篇文章能帮助你更好地理解和使用MyBatis。

标签:指南,映射,接口,详解,SQL,MyBatis,加载,延迟
From: https://blog.51cto.com/u_15791283/9183166

相关文章

  • 美国服务器配置参数详解:了解其硬件及规格
    ​美国服务器提供的配置规格范围广泛。现成型号具有不同的存储容量、存储技术(例如HDD、SSD)、内存大小、CPU、内核和带宽速度。选择错误的规格可能意味着您的服务器无法完成您想要的任务,或者您最终会为一台比您需要的功能更强大的机器付出太多代价。因此,在寻找美国服务器前,建......
  • MyBatis实战指南(二):工作原理与基础使用详解
    MyBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。那么,它是如何工作的呢?又如何进行基础的使用呢?本文将带你了解MyBatis的工作原理及基础使用。一、MyBatis的工作原理1.1MyBatis的工作原理工作原理图示:1、读取MyBatis配置文件mybatis-config.xml为MyBa......
  • iOS 应用上架指南:资料填写及提交审核
    ​ iOS应用上架指南:资料填写及提交审核摘要本文提供了iOS新站上架资料填写及提交审核的详细指南,包括创建应用、资料填写-综合、资料填写-IOSApp和提交审核等步骤。通过本指南,您将了解到如何填写正确的资料,并顺利通过苹果公司的审核。引言在开发iOS应用后,将其上架到AppSto......
  • MyBatis中使用#{}和${}占位符传递参数的各种报错信息处理
    在Mapper层使@Select注解进行SQL语句查询时,往往需要进行参数传入和拼接,一般情况下使用两种占位符#{参数名}和${参数名},两者的区别为:一、两种占位符的区别1、参数传入方式的区别#{}是预编译处理,后台输出的日志会将SQL语句中的#{}占位符输出为?,将传入的Parameter传入SQL语句。${}......
  • 腾讯大牛深入浅出详解云原生
    腾讯大牛深入浅出详解云原生 本文介绍目前业界非常火热的“云原生(CloudNative)”相关知识结构,包括微服务、DevOps、持续交付、服务网格、Serverless等相关知识点。“云原生”通过提供一套完整的技术体系和方法论来指导我们在云环境下,在系统功能越来越复杂的情况下,还能够做到敏......
  • 2024年1月Java项目开发指南1:环境与工具准备
    准备工作基础能力开发能力的事咱先不谈,有两个基础技能要学一下。1.学习使用Markdown编写文档2.学会使用git拉取代码和提交代码软件准备电脑需要安装以下软件:IDEA2023.2及其以上(Java开发统一使用IDEA)Webstorm2023.2及其以上(也可以使用VScode或者Hbuilder或者Dreamweav......
  • 2024年1月Java项目开发指南2:项目设计
    确定软件架构1.前端用什么技术,什么框架,什么版本2.后端用什么技术,什么框架,什么版本3.用些什么软件,软件版本?比如:前端:vue3+Element-Plus+Axios后端:Java17SpringbootMyBatis-plusMaven3数据库:MySQL5.5后端开发工具:IDEA2023.2.2前端开发工具:Webstorm2023.2.2接口管理......
  • 支付宝小程序备案流程详解(必看!)
    为什么要小程序备案2023年8月4日,工信部发布了《工业和信息化部关于开展移动互联网应用程序备案工作的通知》,为了落实《中华人民共和国反电信网络诈骗法》《互联网信息服务管理办法》以及《非经营性互联网信息服务备案管理办法》等法律法规要求,在中华人民共和国境内从事互......
  • Next.js 开发指南 路由篇 | 动态路由、路由组、平行路由和拦截路由
     前言实际项目开发的时候,有的路由场景会比较复杂,比如数据库里的文章有很多,我们不可能一一去定义路由,此时该怎么办?组织代码的时候,有的路由是用于移动端,有的路由是用于PC端,该如何组织?如何有条件的渲染页面,比如未授权的时候显示登录框?如何让同一个路由根据情况不同展示不同的内......
  • 程序员建议指南
    IDEA代码质量检查工具插件插件名称作用建议程度IDEA自带插件规范编译器警告强制SonarLint代码质量检查强制CodeMetric代码复杂度提醒建议MetricsReloaded代码复杂度计算建议AlibabaJavaCodingGuidelines代码规范建议/部分规范不建议代码......