第6章 初识MyBatis
学习目标
● 了解MyBatis的基础知识
● 熟悉MyBatis的工作原理
● 掌握MyBatis入门程序的编写
6.1 什么是MyBatis
MyBatis(前身是iBatis)是一个支持普通SQL查询、存储过程以及高级映射的持久层框架,它消除了几乎所有的JDBC代码和参数的手动设置以及对结果集的检索,并使用简单的XML或注解进行配置和原始映射,用以将接口和Java的POJO(Plain Old Java Object,普通Java对象)映射成数据库中的记录,使得Java开发人员可以使用面向对象的编程思想来操作数据库。
MyBatis框架也被称之为ORM(Object/Relational Mapping,即对象关系映射)框架。所谓的ORM就是一种为了解决面向对象与关系型数据库中数据类型不匹配的技术,它通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的表中。ORM框架的工作原理如图6-1所示。

使用ORM框架后,应用程序不再直接访问底层数据库。
· Hibernate:是一个全表映射的框架。通常开发者只需定义好持久化对象到数据库表的映射关系,就可以通过Hibernate提供的方法完成持久层操作。开发者并不需要熟练地掌握SQL语句的编写,Hibernate会根据制定的存储逻辑,自动的生成对应的SQL,并调用JDBC接口来执行,所以其开发效率会高于MyBatis。然而Hibernate自身也存在着一些缺点,例如它在多表关联时,对SQL查询的支持较差;更新数据时,需要发送所有字段;不支持存储过程;不能通过优化SQL来优化性能等。这些问题导致其只适合在场景不太复杂且对性能要求不高的项目中使用。
· MyBatis:是一个半自动映射的框架。这里所谓的“半自动”是相对于Hibernate全表映射而言的,MyBatis需要手动匹配提供POJO、SQL和映射关系,而Hibernate只需提供POJO和映射关系即可。与Hibernate相比,虽然使用MyBatis手动编写SQL要比使用Hibernate的工作量大,但MyBatis可以配置动态SQL并优化SQL,可以通过配置决定SQL的映射规则,它还支持存储过程等。对于一些复杂的和需要优化性能的项目来说,显然使用MyBatis更加合适。
6.2 MyBatis的下载和使用

如果底层采用的是MySQL数据库,那么还需要将MySQL数据库的驱动JAR包添加到应用程序的类路径中;如果采用其他类型的数据库,则同样需要将对应类型的数据库驱动包添加到应用程序的类路径中。
6.3 MyBatis的工作原理

(1)读取MyBatis配置文件mybatis-config.xml。配置了MyBatis的运行环境等信息,其中主要内容是获取数据库连接。
(2)加载映射文件Mapper.xml。即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在mybatis-config.xml中加载才能执行。mybatis-config.xml可以加载多个配置文件,每个配置文件对应数据库中的一张表。
(3)构建会话工厂。通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。
(4)创建SqlSession对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL的所有方法。
(5)MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
(6)在Executor接口的执行方法中,包含一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等。Mapper.xml文件中一个SQL对应一个MappedStatement对象,SQL的id即是MappedStatement的id。
(7)输入参数映射。在执行方法时,MappedStatement对象会对用户执行SQL语句的输入参数进行定义(可以定义为Map、List类型、基本类型和POJO类型), Executor执行器会通过MappedStatement对象在执行SQL前,将输入的Java对象映射到SQL语句中。这里对输入参数的映射过程就类似于JDBC编程中对preparedStatement对象设置参数的过程。(8)输出结果映射。在数据库中执行完SQL语句后,MappedStatement对象会对SQL执行输出的结果进行定义(可以定义为Map和List类型、基本类型、POJO类型), Executor执行器会通过MappedStatement对象在执行SQL语句后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于JDBC编程中对结果的解析处理过程。
6.4 MyBatis入门程序
6.4.1 查询客户
1.根据客户编号查询客户信息
1.建表
2.加mybatis依赖

3.创建log4j.properties文件【在MyBatis使用手册中的Logging小节】
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.itheima=DEBUG
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
4.持久化类
持久化类Customer与普通的JavaBean并没有什么区别,只是其属性字段与数据库中的表字段相对应。
5.CustomerMapper. xml【MyBatis使用手册中Getting started(入门指南)下的2.1.5小节Exploring Mapped SQL Statements中,即可找到映射文件的约束信息】
<?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表示命名空间,通常会设置成“包名+SQL映射文件名 -->
<mapper namespace="com.itheima.mapper.CustomerMapper">
<!--根据客户编号获取客户信息 parameterType指定传入参数的类型-->
<select id="findCustomerById" parameterType="Integer"
<!--resultType属性用于指定返回结果的类型 -->
resultType="com.itheima.po.Customer">
<!--“#{}”用于表示一个占位符,相当于“? ”“#{id}”表示该占位符待接收参数的名称为id-->
select * from t_customer where id = #{id}
</select>
</mapper>
mapper namespace爆红未解决
6.mybatis-config.xml【在MyBatis使用手册mybatis-3.4.2.pdf的2.1.2小节中,已经给出了配置模板(包含约束信息)】
<?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>
<!-- 配置环境,默认的环境id为mysql-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/mybatis?characterEncoding=utf8&useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 配置Mapper的位置-->
<mappers>
<mapper resource="com/itheima/mapper/CustomerMapper.xml"/>
</mappers>
</configuration>
如报错Document root element "configuration", must match DOCTYPE root "mapper".或者必须声明元素 configration,检查命名空间
7.测试类
@Test
public void findCustomerByIdTest() throws IOException {
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 根据配置文件构建sqlsessionfactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 通过sqlsessionfactory创建sqlsession
SqlSession sqlSession = sqlSessionFactory.openSession();
// sqlsession执行映射文件中定义的sql并返回映射结果
Customer customer = sqlSession.selectOne("com.itheima.mapper.CustomerMapper.findCustomerById", 1);
System.out.println(customer);
// 关闭sqlsession
sqlSession.close();
}
selectOne()方法的第1个参数表示映射SQL的标识字符串,它由CustomerMapper.xml中<mapper>元素的namespace属性值+<select>元素的id属性值组成<mapper>元素的namespace属性值+<select>元素的id属性值组成
Could not find resource com/itheima/mapper/CustomerMapper.xml
如果是idea创建的maven工程,mapper文件应放在resource目录下
2.根据客户名模糊查询客户信息
mapper.xml
在使用“${}”进行SQL字符串拼接时,无法防止SQL注入问题。concat()函数进行字符串拼接防止SQL注入
<!-- 根据客户名模糊查询信息列表-->
<select id="findCustomerByName" parameterType="string"
resultType="com.itheima.po.Customer">
-- select *
-- from t_customer where username like '%${value}%';
select *
from t_customer where username like concat('%',#{value},'%')
</select>
测试类
@Test
public void findCustomerByNameTest() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Customer> customers = sqlSession.selectList("com.itheima.mapper.CustomerMapper.findCustomerByName", "j");
for (Customer customer: customers) {
System.out.println(customer);
}
sqlSession.close();
}
总结
(1)读取配置文件。(2)根据配置文件构建SqlSessionFactory。(3)通过SqlSessionFactory创建SqlSession。(4)使用SqlSession对象操作数据库(包括查询、添加、修改、删除以及提交事务等)。(5)关闭SqlSession。
6.4.2 添加客户
<!-- 提那家客户信息-->
<insert id="addCustomer" parameterType="com.itheima.po.Customer">
insert into t_customer(username,jobs,phone)
values(#{username},#{jobs},#{phone})
</insert>
@Test
public void addCustomerTest() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
Customer customer = new Customer();
customer.setUsername("rose");
customer.setJobs("student");
customer.setPhone("123132135456");
int rows = sqlSession.insert("com.itheima.mapper.CustomerMapper.addCustomer", customer);
if(rows > 0){
System.out.println(rows+" item success");
}else
{
System.out.println("false");
}
sqlSession.commit();
sqlSession.close();
}
6.4.3 更新客户
<update id="updateCustomer" parameterType="com.itheima.po.Customer">
update t_customer set
username=#{username},jobs=#{jobs},phone=#{phone}
where id = #{id}
</update>
customer.setId(4);
customer.setUsername("luca");
customer.setJobs("student");
customer.setPhone("1132135456");
int rows = sqlSession.update("com.itheima.mapper.CustomerMapper.updateCustomer",customer);
6.4.4 删除客户
<delete id="deleteCustomer" parameterType="Integer">
delete
from t_customer
where id = #{id};
</delete>
int rows = sqlSession.delete("com.itheima.mapper.CustomerMapper.deleteCustomer", 4);
【思考题】
1.请简述MyBatis框架与Hibernate框架的区别。
M是半ORM框架H是全ORM框架
M一部分sql语句需要程序员编写H不需要
M灵活性更高H多表联查困难
M可移植性差H可移植性好可兼容多种数据库
M适合新型大型互联网项目H适合以往常规项目
2.请简述MyBatis的工作执行流程。
创建数据库
创建mapper映射文件
创建配置文件
根据配置文件创建inputstream,根据is创建sqlsessionfactory,开启session,调用增删改查方法,提交事务,关闭session
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?