【MyBatis学习总结(一),初步理解MyBatis & 简单实现】

it2024-07-19  40

Mybatis

简介

以下引自 Mybatis 官方文档

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

Mybatis 官方文档

以下引自百度百科

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

如何获得MyBatis

maven仓库GitHub

持久层

在解释什么是持久层之前我们先了解一下什么是持久化

持久化就是将程序的数据在持久状态和瞬时状态转化的过程内存有一个特性,就是断电即失,存在于内存中未持久化的数据就叫做瞬时数据将这种存在于内存中的瞬时数据,转化为持久数据(保存到可永久保存的存储设备中,如磁盘、数据库),的过程就是持久化

了解完什么是持久化后我们来说明一下持久层

持久层主要和数据库打交道持久层是一个相对独立的逻辑层面,专注于数据持久化逻辑的实现持久层能够提高操作效率,它提供ORM机制,并封装必要的数据操作方法,提供方法接口…

任何一种企业级Java Web应用,都离不开数据库操作,也就是数据的存储与获取。特别是对于大量数据的高效操作,在大数据时代下尤其被重视。因此,在利用Java开发企业及应用时,如何提高对数据操作的效率,也就成了开发需要考虑的要素之一。 而持久层框架,也就是为此应运而生。 通常来讲,在不使用特定的持久层框架的前提下,Java开发者需要书写大量的重复性代码,并嵌入相关的SQL语句来完成与数据库的交互(主要是基本数据操作业务,如单一数据的CRUD SQL代码,以及JDBC相关的代码)。而使用了特定的持久层框架后,在于数据库连接、交互方面的代码量会显著减少。 其中的一个较为重要原因原因在于持久层框架完成了"面向对象"到"面向关系"的转换。这使得可以通过直接操作Java对象来完成对数据库中对应数据的操作。

以上引自该文章

这种将数据持久化操作在早些年使用JDBC也能够做到,但有点繁杂 于是为了简化(偷懒)开发,Mybatis框架就应运而生了

Mybatis的一些特点

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

实现一个Mybatis程序

搭建环境

创建数据库(各凭喜好,建库建表插数据即可。)

创建一个maven项目

在pom.xml中导入所需的依赖

<dependencies> <!--导入mybatis依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <!--导入MySQL驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.21</version> </dependency> <!--导入junit,方便测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> </dependencies>

在maven侧边栏中,请务必确认依赖成功导入了

从官网将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"> <!--默认使用JDBC事务管理--> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <!--用户登录信息,不建议直接将登录信息写在这里--> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <!--绑定mapper配置文件--> <mappers> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>

到这里我们的环境就准备好了

从xml中构建sqlSessionFactory

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。

从 XML 文件中构建 SqlSessionFactory 的实例非常简单,建议使用类路径下的资源文件进行配置。 但也可以使用任意的输入流(InputStream)实例,比如用文件路径字符串或 file:// URL 构造的输入流。MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,使得从类路径或其它位置加载资源文件更加容易。

String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

不使用xml来配置sqlSessionFactory(不建议)

如果你更愿意直接从 Java 代码而不是 XML 文件中创建配置,或者想要创建你自己的配置建造器,MyBatis 也提供了完整的配置类,提供了所有与 XML 文件等价的配置项。

DataSource dataSource = BlogDataSourceFactory.getBlogDataSource(); TransactionFactory transactionFactory = new JdbcTransactionFactory(); Environment environment = new Environment("development", transactionFactory, dataSource); Configuration configuration = new Configuration(environment); configuration.addMapper(BlogMapper.class); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);

注意该例中,configuration 添加了一个映射器类(mapper class)。映射器类是 Java 类,它们包含 SQL 映射注解从而避免依赖 XML 文件。不过,由于 Java 注解的一些限制以及某些 MyBatis 映射的复杂性,要使用大多数高级映射(比如:嵌套联合映射),仍然需要使用 XML 配置。有鉴于此,如果存在一个同名 XML 配置文件,MyBatis 会自动查找并加载它(在这个例子中,基于类路径和 BlogMapper.class 的类名,会加载 BlogMapper.xml)。具体细节稍后讨论。

SqlSessionFactory的作用

既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。例如:

try (SqlSession session = sqlSessionFactory.openSession()) { Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101); }

编写mybatis工具类

// 该工具类的主要作用是:让其他类通过调用它的getSqlSession方法,得到sqlSession对象 public class MybatisUtils { //5、提升SqlSessionFactory 对象的作用域,方便getSqlSession直接调用其中的方法 private static SqlSessionFactory sqlSessionFactory; //1、放到静态代码块中,让它初始化时就加载 static { try { //2、将配置文件加载进来 String resource = "mybatis-config.xml"; //3、读取核心配置文件,并返回inputStream流对象 InputStream inputStream = Resources.getResourceAsStream(resource); //4、通过inputStream流对象解析出Configuration对象,通过该对象创建SqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //6、写一个能够得到sqlSession实例的方法 public static SqlSession getSqlSession(){ //7、调用openSession方法会返回一个,SqlSession实例 return sqlSessionFactory.openSession(); } }

Mybatis初始化流程

为避免对上述工具类有所疑惑,我会简单的介绍一下mybatis的初始化流程,当然这已经涉及源码不必深究,了解即可。

如果看完反而更有所疑惑,那这个初始化介绍就起反作用了,可以选择性阅读。

MyBatis开始运行后, 先要通过Resources加载核心配置文件, 得到一个输入流。

将输入流作为参数传入SqlSessionFactoryBuilder的buid方法中, 用于创建SqlSessionFactory对象。

在创建SqlSessionFactory对象之前,SqlSessionFactoryBuilder会根据输入流等信息 ,先创建一个XmlConfigBuilder对象,

XmlConfigBuilder这个对象可以被称之为解析器, 用来解析核心配置文件, 解析结果被封装进Configuration对象中。

SqlSessionFactoryBuider根据Configuration对象,会创建一个DefaultSqlSessionFactory对象

工厂对象创建成功后, 程序员可以通过调用openSession方法创建SqlSession对象。

SqlSession对象是MyBatis中的核心对象, 所有的数据库操作都是基于这个对象完成的。

SqlSession作为Mybatis的核心API,它主要用来执行命令,获取映射,管理事务。接收开发人员提供的 Statement Id 和参数,并返回操作结果。

我们看一下SqlSessionFactory的 openSession方法是如何创建SqlSession对象的

从Configuration配置类中拿到Environment数据源;从数据源中获取TransactionFactory和DataSource,并创建一个Transaction连接管理对象;创建Executor(SqlSession只是所有操作的门面,真正要干活的是Executor,它封装了底层JDBC所有的操作细节)执行器, 默认MyBatis使用的是SimpleExecutor接下来基于执行器Executor,创建DefaultSqlSession对象,到此为止SqlSession对象创建成功。程序员可以基于SqlSession调用相应的方法进行数据库的操作

我们来解决一下mybatis配置文件中的数据库登录信息

首先在resources目录下创建一个db.properties文件在db.properties文件中,写死你的driver,url,username和password。 driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/数据库名?serverTimezone=GMT%2B8&useSSL=true&useUnicode=true&characterEncoding=UTF-8 username=用户名 password=密码 # 数据库登录信息, 时区设置为东八区,如果你是使用的8版本驱动就需要设置这个时区(serverTimezone=GMT%2B8)

将db.properties引入到mybatis配置文件中

<!--<propertie>标签它必须置于<configuration>标签内的最顶部,否则会出现异常--> <properties resource="db.properties"/>

在mybatis配置文件中配置登录信息

在property标签value值处,使用$符号和一对大括号,引用db.properties文件中的配置信息,如下。默认从官网复制下来就是这样,不需要改动

<dataSource type="POOLED"> <!--用户登录信息--> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource>

编写实体类

package com.molu.pojo; // 编写实体类 public class User { private int id; private String name; private String pwd; public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public User() {} public int getId() { return id;} public void setId(int id) { this.id = id;} public String getName() { return name;} public void setName(String name) { this.name = name;} public String getPwd() { return pwd;} public void setPwd(String pwd) { this.pwd = pwd;} @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }

通过数据库中的字段我们编写一个实体类,生成一些需要用到的方法,当然你也可以使用Lombok来偷懒,都一样的

编写Mapper接口及配置文件

简单的写一个mapper接口

public interface UserMapper { // 在mapper接口中简单的写一个查询方法 List<User> getUserList(); }

写完接口后,按之前我们应该去写一个接口实现类,来继承这个接口并重写它的方法。但在mybatis中我们不再写接口的实现类,而是写一个mapper配置文件。

mapper配置文件你可以写在recourse目录下,也可以写在自己建的mapper包下,和mapper接口放在一起。

后者的话需要注意一个maven静态资源过滤的问题,你需要将以下配置拷到你的pom.xml中,防止出现这个问题

静态资源过滤异常,可以尝试将此配置放入pom.xml中

<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>

我们开始编写mapper.xml配置文件

首先从官网将mapper.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"> <!--上面是固定的头文件,不用看--> <mapper namespace="org.mybatis.example.BlogMapper"> <select id="selectBlog" resultType="Blog"> select * from Blog where id = #{id} </select> </mapper>

我们从下面这些示例着手

首先,mapper标签中有一个namespace属性,namespace属性用于绑定mapper接口

在mapper标签中我们也可以写一些具体的数据库操作,通过以下标签

从select标签着手,select标签中有id和resultType两个属性可以配置

id 属性用于指定接口中的方法而resultType属性则用于指定方法的返回值类型

select标签体中写具体的sql

明白这些示例后我们动手写自己的mapper配置文件

<?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接口--> <mapper namespace="com.molu.mapper.UserMapper"> <!--id绑定我们接口中的方法--> <!--resultType则写返回的类型, 这个返回的类型要写全限定名。 我们接口查询方法泛型中是User类,我们就写User的全限定名--> <select id="getUserList" resultType="com.molu.pojo.User"> select * from mybatis.user </select> </mapper>

mapper配置文件写好后,我们还要去mybatis的核心配置文件中对其进行绑定

我是将mapper.xml写在resources目录下的,和mybatis配置文件放在一起,所以绑定起来也很简单。

<mappers> <mapper resource="mapper.xml"/> </mappers>

测试类

public class MapperTest { @Test public void test(){ // 由于之前写过生成sqlSession的工具类,所以这边能够直接通过工具类调用方法得到SqlSession实例 SqlSession sqlSession = MybatisUtils.getSqlSession(); // 我们通过 sqlSession 的getMapper方法拿到 mapper接口对象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); // 通过接口对象调用接口中的方法 List<User> userList = mapper.getUserList(); // 遍历返回的数组 for (User user : userList) { System.out.println(user); } // 关闭连接 sqlSession.close(); } }

测试类这块大家应该比较迷糊,我就献丑解释一下原理

首先我们通过写好的工具类直接拿到sqlSession,这一点应该没有疑惑

前文也说到了,这个sqlSession是Mybatis的核心api,我们可以用它来执行sql。而sql存在于mapper.xml配置文件中sqlSession中存在一个getMapper方法,通过这个方法能够拿到接口的对象有了接口的对象就能够使用接口中的方法,当我们调用这个方法时 会进行一个动态代理的操作通过这个动态代理我们就能够拿到mapper.xml中的sql,并执行(其实现原理展开的话篇幅很大,本文不做任何解释,可以移步该博客进行简单了解)执行完sql后,查询结果会被封装到返回的 userList 中,我们只需要注意返回值类型并将其遍历,就能够拿到我们数据库中的数据。

除了使用getMapper的方式来拿到接口对象,我们还可以通过另一种方式。

public class MapperTest { @Test public void test(){ // 由于之前写过生成sqlSession的工具类,所以这边能够直接通过工具类调用方法得到SqlSession实例 SqlSession sqlSession = MybatisUtils.getSqlSession(); // 第二种方式,将我们的接口类和方法写死在sqlSession的方法中,并将返回的Object强转为需要的类型 List<User> userList = sqlSession.selectList("com.molu.mapper.UserMapper.getUserList"); // 遍历返回的数组 for (User user : userList) { System.out.println(user); } // 关闭连接 sqlSession.close(); } }

当然了这种方式并不推荐使用,已经有点过时了。

官网中也有说到更推荐使用getMapper,所以这种方法了解即可

那到这里MyBatis的初步理解和简单实现就告一段落了,关于MyBatis的文章在之后应该也会陆续更新,感谢你能看到这里 如果有帮到你的话 (‾◡◝)


原图地址

画师主页


最新回复(0)