当前位置: 首页 > news >正文

【JavaWeb】MyBatis

1 介绍

什么是MyBatis?

MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。

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

MyBatis官网https://mybatis.org/mybatis-3/zh_CN/index.html

在上面我们提到了两个词:一个是持久层,另一个是框架。

持久层:指的是就是数据访问层(dao),是用来操作数据库的。

框架:是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。在框架的基础上进行软件开发更加高效、规范、通用、可拓展。

通过Mybatis就可以大大简化原生的JDBC程序的代码编写,比如 通过select * from user 查询所有的用户数据,通过JDBC程序操作,需要大量的代码实现,而如果通过Mybatis实现相同的功能,只需要简单的三四行就可以搞定。

1.1 快速入门

需求:使用Mybatis查询所有用户数据 。

1) 创建springboot工程,并导入 mybatis的起步依赖、mysql的驱动包、lombok。

项目工程创建完成后,自动在pom.xml文件中,导入Mybatis依赖和MySQL驱动依赖。如下所示:

2) 数据准备:创建用户表user,并创建对应的实体类User。

用户表 user(如果已经存在,就不用创建了)

create table user(id int unsigned primary key auto_increment comment 'ID,主键',username varchar(20) comment '用户名',password varchar(32) comment '密码',name varchar(10) comment '姓名',age tinyint unsigned comment '年龄'
) comment '用户表';insert into user(id, username, password, name, age) values (1, 'daqiao', '123456', '大乔', 22),(2, 'xiaoqiao', '123456', '小乔', 18),(3, 'diaochan', '123456', '貂蝉', 24),(4, 'lvbu', '123456', '吕布', 28),(5, 'zhaoyun', '12345678', '赵云', 27);

实体类:实体类的属性名与表中的字段名一一对应。 实体类放在 org.exampl.pojo 包下。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private Integer id; //IDprivate String username; //用户名private String password; //密码private String name; //姓名private Integer age; //年龄
}

3) 配置Mybatis

在 application.properties 中配置数据库的连接信息。

#数据库访问的url地址
spring.datasource.url=jdbc:mysql://localhost:3306/web
#数据库驱动类类名
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#访问数据库-用户名
spring.datasource.username=root
#访问数据库-密码
spring.datasource.password=root@1234

4) 编写Mybatis程序:编写Mybatis的持久层接口,定义SQL语句(注解)

在创建出来的springboot工程中,在引导类所在包下,在创建一个包 mapper 。在 mapper 包下创建一个接口 UserMapper ,这是一个持久层接口(Mybatis的持久层接口规范一般都叫 XxxMapper)。

UserMapper接口的内容如下:

import org.exampl.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;@Mapper
public interface UserMapper {/*** 查询全部*/@Select("select * from user")public List<User> findAll();
}

注:

@Mapper注解:表示是mybatis中的Mapper接口

程序运行时,框架会自动生成接口的实现类对象(代理对象),并给交Spring的IOC容器管理

@Select注解:代表的就是select查询,用于书写select查询语句

5) 单元测试

在创建出来的SpringBoot工程中,在src下的test目录下,已经自动帮我们创建好了测试类 ,并且在测试类上已经添加了注解 @SpringBootTest,代表该测试类已经与SpringBoot整合。  

该测试类在运行时,会自动通过引导类加载Spring的环境(IOC容器)。要测试那个bean对象,就可以直接通过@Autowired注解直接将其注入进行,然后就可以测试了。 

测试类代码如下:

@SpringBootTest
class SpringbootMybatisQuickstartApplicationTests {@Autowiredprivate UserMapper userMapper;@Testpublic void testFindAll(){List<User> userList = userMapper.findAll();for (User user : userList) {System.out.println(user);}}
}

注:测试类所在包,需要与引导类所在包相同。

1.2 辅助配置

1.2.1 配置SQL提示

默认在UserMapper接口上加的 @Select 注解中编写SQL语句是没有提示的。 如果想让idea给我们提示对应的SQL语句,需要在IDEA中配置与MySQL数据库的链接。  

如果想让idea给出提示,可以做如下配置:

如果是新版的idea可能已经有配置了,但不是MySQL,可以选择unInject然后再进行上述操作。

配置完成之后,发现SQL语句中的关键字有提示了,但还存在不识别表名(列名)的情况,其原因就是Idea和数据库没有建立连接,不识别表信息。

那么如何在Idea中配置MySQL数据库连接呢?

按照如下方式,来配置当前IDEA关联的MySQL数据库(必须要指定连接的是哪个数据库)。

然后输入数据库名和用户名及密码即可。

此处用的是上文中的web01数据库。

注:该配置的目的,仅仅是为了在编写SQL语句时,有语法提示(写错了会报错),不会影响运行,即使不配置也是可以的。

1.2.2 配置Mybatis日志输出

默认情况下,在Mybatis中,SQL语句执行时,我们并看不到SQL语句的执行日志。 在application.properties加入如下配置,即可查看日志: 

#mybatis的配置
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

打开上述开关之后,再次运行单元测试,就可以看到控制台输出的SQL语句是什么样子的。

1.3 JDBC VS Mybatis

JDBC程序的缺点

  • url、username、password 等相关参数全部硬编码在java代码中。

  • 查询结果的解析、封装比较繁琐。

  • 每一次操作数据库之前,先获取连接,操作完毕之后,关闭连接。 频繁的获取连接、释放连接造成资源浪费。

分析了JDBC的缺点之后,我们再来看一下在mybatis中,是如何解决这些问题的:

  • 数据库连接四要素(驱动、链接、用户名、密码),都配置在springboot默认的配置文件 application.properties中

  • 查询结果的解析及封装,由mybatis自动完成映射封装,我们无需关注

  • 在mybatis中使用了数据库连接池技术,从而避免了频繁的创建连接、销毁连接而带来的资源浪费。

使用SpringBoot+Mybatis的方式操作数据库,能够提升开发效率、降低资源浪费

而对于Mybatis来说,我们在开发持久层程序操作数据库时,需要重点关注以下两个方面:

1. application.properties

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/web01
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234

Mapper接口(编写SQL语句)

@Mapper
public interface UserMapper {@Select("select * from user")public List<User> list();
}

1.4 数据库连接池

在前面所讲解的mybatis中,使用了数据库连接池技术,避免频繁的创建连接、销毁连接而带来的资源浪费

下面就具体的了解下数据库连接池。

1.4.1 介绍

1). 没有数据库连接池的情况

客户端执行SQL语句:要先创建一个新的连接对象,然后执行SQL语句,SQL语句执行后又需要关闭连接对象从而释放资源,每次执行SQL时都需要创建连接、销毁链接,这种频繁的重复创建销毁的过程是比较耗费计算机的性能。

2). 有数据库连接池的情况

数据库连接池是个容器负责分配、管理数据库连接(Connection)

1. 程序在启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象,允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个

2. 客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用)

释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏

3. 客户端获取到Connection对象了,但是Connection对象并没有去访问数据库(处于空闲),数据库连接池发现Connection对象的空闲时间 > 连接池中预设的最大空闲时间,此时数据库连接池就会自动释放掉这个连接对象

数据库连接池的好处

  • 资源重用

  • 提升系统响应速度

  • 避免数据库连接遗漏

1.4.2 产品

要怎么样实现数据库连接池呢?

官方(sun)提供了数据库连接池标准(javax.sql.DataSource接口)

功能:获取连接

public Connection getConnection() throws SQLException;

第三方组织必须按照DataSource接口实现

常见的数据库连接池:C3P0 DBCP Druid Hikari (springboot默认)

现在使用更多的是:Hikari、Druid (性能更优越)

1) Hikari(追光者) [默认的连接池]

从控制台输出的日志,我们也可以看出,springboot底层默认使用的数据库连接池就是 Hikari。

2) Druid(德鲁伊)

Druid连接池是阿里巴巴开源的数据库连接池项目

功能强大,性能优秀,是Java语言最好的数据库连接池之一

参考地址:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter

如果我们想把默认的数据库连接池切换为Druid数据库连接池,只需要完成以下两步操作即可:

1. 在pom.xml文件中引入依赖

<dependency><!-- Druid连接池依赖 --><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.19</version>
</dependency>

2. 在application.properties中引入数据库连接配置

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql://localhost:3306/web
spring.datasource.druid.username=root
spring.datasource.druid.password=1234

配置完毕之后,再次运行单元测试,可以看到控制台输出的日志中,已经将连接池切换为了 Druid连接池。

1.5 增删改查操作

1.5.1 删除

需求:根据ID删除用户信息

SQL:delete from user where id = 5;

Mapper接口方法:

方式一:

/*** 根据id删除*/
@Delete("delete from user where id = 5")
public void deleteById();

这种方式执行删除操作,调用deleteById方法只能删除id为5的用户信息,因为将id直接写死在代码中了,不可取。

方式二:

/*** 根据id删除*/
@Delete("delete from user where id = #{id}")
public void deleteById(Integer id);

在Mybatis中,我们可以通过参数占位符号 #{...} 来占位,在调用deleteById方法时,传递的参数值,最终会替换占位符。

编写单元测试方法进行测试

在单元测试类中,增加如下测试方法.

@Test
public void testDeleteById(){userMapper.deleteById(36);
}

运行之后,在控制台中我们发现,#{...} 占位符,其实最终被替换成了 ?占位符,生成的是预编译的SQL语句。

DML语句执行完毕,是有返回值的,我们可以为Mapper接口方法定义返回值来接收,如下:

/*** 根据id删除*/
@Delete("delete from user where id = #{id}")
public Integer deleteById(Integer id);

Integer类型的返回值,表示DML语句执行完毕影响的记录数

Mybatis的提供的符号,有两个,一个是 #{...},另一个是 ${...},区别如下:

符号说明场景优缺点
#{…}占位符。执行时,会将#{…}替换为?,生成预编译SQL参数值传递安全、性能高 (推荐)
${…}拼接符。直接将参数拼接在SQL语句中,存在SQL注入问题表名、字段名动态设置时使用不安全、性能低

1.5.2 新增

需求:添加一个用户

SQL:insert into user(username,password,name,age) values('zhouyu','123456','周瑜',20);

Mapper接口:

/*** 添加用户*/
@Insert("insert into user(username,password,name,age) values(#{username},#{password},#{name},#{age})")
public void insert(User user);

如果在SQL语句中,我们需要传递多个参数,我们可以把多个参数封装到一个对象中。然后在SQL语句中,我们可以通过 #{对象属性名} 的方式,获取到对象中封装的属性值。

单元测试:

在测试类中添加测试方法,代码如下:

@Test
public void testInsert(){User user = new User();user.setUsername("admin");user.setPassword("123456");user.setName("管理员");user.setAge(30);userMapper.insert(user);
}

1.5.3 修改

需求:根据ID更新用户信息

SQL:update user set username = 'zhouyu', password = '123456', name = '周瑜', age = 20 where id = 1;

Mapper接口方法:

/*** 根据id更新用户信息*/
@Update("update user set username = #{username},password = #{password},name = #{name},age = #{age} where id = #{id}")
public void update(User user);

单元测试:

在测试类中添加测试方法,代码如下:

@Test
public void testUpdate(){User user = new User();user.setId(6);user.setUsername("admin666");user.setPassword("123456");user.setName("管理员");user.setAge(30);userMapper.update(user);
}

1.5.4 查询

需求:根据用户名和密码查询用户信息

SQL:select* fromuser whereusername = 'zhouyu' and password = '123456'

Mapper接口方法:

/*** 根据用户名和密码查询用户信息*/
@Select("select * from user where username = #{username} and password = #{password}")
public User findByUsernameAndPassword(@Param("username") String username, @Param("password") String password);

@param注解的作用是为接口的方法形参起名字的。(由于用户名唯一的,所以查询返回的结果最多只有一个,可以直接封装到一个对象中)

单元测试:

在测试类中添加测试方法,代码如下:

@Test
public void testFindByUsernameAndPassword(){User user = userMapper.findByUsernameAndPassword("admin666", "123456");System.out.println(user);
}

注:基于官方骨架创建的springboot项目中,接口编译时会保留方法形参名,@Param注解可以省略 (#{形参名})。

1.6 XML映射配置

Mybatis的开发有两种方式:

1. 注解

2. XML

1.6.1 XML文件配置规范

使用Mybatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。

在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:

1.XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)

2.XML映射文件的namespace属性为Mapper接口全限定名一致

3.XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。

1.6.2 XML文件配置实现

第1步: 创建XML映射文件

注:由于是目录,因此用 / 分隔

第2步:编写XML映射文件

xml映射文件中的dtd约束,直接从mybatis官网复制即可

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace=""></mapper>

第3步:配置

a. XML映射文件的namespace属性为Mapper接口全限定名

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.exampl.mapper.UserMapper"></mapper>

b. XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.exampl.mapper.EmpMapper"><!--查询操作--><select id="findAll" resultType="org.exampl.pojo.User">select * from user</select></mapper>

resultType 属性的值,与查询返回的单条记录封装的类型一致。

注:一个接口方法对应的SQL语句,要么使用注解配置,要么使用XML配置,切不可同时配置。

1.6.3 MybatisX的使用

MybatisX是一款基于IDEA的快速开发Mybatis的插件,为效率而生。

MybatisX的安装:

左上角files中点击settings -> plugins查找MybatisX并安装

可以通过MybatisX快速定位:

学习了Mybatis中XML配置文件的开发方式了,大家可能会存在一个疑问:到底是使用注解方式开发还是使用XML方式开发?

使用Mybatis的注解,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句。

2 SpringBoot配置文件

2.1 介绍

此前在Spring Boot项目中,一直使用创建时自带的application.properties配置属性。若需配置大量属性,这种key=value的格式会导致配置文件层级结构模糊、内容臃肿。

实际上,Spring Boot支持多种配置方式。除了properties文件外,还可使用YML格式配置文件(如application.yml或application.yaml),两者后缀名不同,但配置语法完全一致。

注:在项目开发中,推荐使用application.yml配置文件来配置信息,简洁、明了、以数据为中心。

2.2 语法

简单的了解过springboot所支持的配置文件,以及不同类型配置文件之间的优缺点之后,接下来我们就来了解下yml配置文件的基本语法:

  • 大小写敏感

  • 数值前边必须有空格,作为分隔符

  • 使用缩进表示层级关系,缩进时,不允许使用Tab键,只能用空格(idea中会自动将Tab转换为空格)

  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

  • #表示注释,从这个字符一直到行尾,都会被解析器忽略

了解完yml格式配置文件的基本语法之后,接下来再来看下yml文件中常见的数据格式。在这里主要介绍最为常见的两类:

1. 定义对象或Map集合

2. 定义数组、list或set集合

对象/Map集合

user:name: zhangsanage: 18password: 123456

 数组/List/Set集合

hobby: - java- game- sport

注:在yml格式的配置文件中,如果配置项的值是以 0 开头的,值需要使用 '' 引起来,因为以0开头在yml中表示8进制的数据。

2.3 案例

熟悉完了yml文件的基本语法后,修改下之前案例中使用的配置文件,变更为application.yml配置方式:

1. 修改application.properties名字为:_application.properties(名字随便更换,只要加载不到即可)

2. 创建新的配置文件: application.yml

原有的 application.properties 配置文件

新建的 application.yml 配置文件

配置文件的内容如下:

#数据源配置
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/web01username: rootpassword: root@****
#mybatis配置
mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

相关文章:

  • SAP-ABAP:SAP的`TRY...CATCH` 异常处理机制详解
  • Jenkins服务器配置密钥对
  • OpenCv高阶(8.0)——答题卡识别自动判分
  • 【LeetCode 热题 100】有效的括号 / 最小栈 / 字符串解码 / 柱状图中最大的矩形
  • Elasticsearch 实战面试题,每个题目都会单独解析
  • 多类型RFID电子标签定制 助力行业精准化管理
  • 在hadoop中实现序列化与反序列化
  • Java EE初阶——定时器和线程池
  • 使用 Navicat 工具管理时,点击某一列,能否查看该列的平均值和最大值等关联信息?
  • 【前端部署】通过 Nginx 让局域网用户访问你的纯前端应用
  • SSH漏洞修复方案
  • GitHub 趋势日报 (2025年05月19日)
  • 机器学习第十九讲:交叉验证 → 用五次模拟考试验证真实水平
  • DataLight(V1.7.12)版本更新发布
  • 进程间通信(IPC):LocalSocket
  • ES(Elasticsearch) 基本概念(一)
  • 开疆智能Profinet转RS485网关连接电磁流量计到西门子PLC配置案例
  • WD5030L CC/CV模式DCDC15A高效同步转换器消费电子工业控制汽车电子优选择
  • Linux X86平台安装ARM64交叉编译器方法
  • LLM大模型工具链
  • 百年前淮北乡村的风俗画卷——读郑重 《九十自述》
  • 哪都“差一点”的《歌手2025》,还能爆吗?
  • 全国治安管理工作视频会召开
  • 破题“省会担当”,南京如何走好自己的路?
  • 上海国际电影节将于6月3日公布排片表,6月5日中午开票
  • 8000余万元黄金投入研发后“不知去向”,咋回事?