news 2026/5/12 2:00:02

Mybatis基础使用教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Mybatis基础使用教程

什么是MyBatis?

• MyBatis是⼀款优秀的 持久层 框架,⽤于简化JDBC的开发。

• MyBatis本是 Apache的⼀个开源项⽬iBatis,2010年这个项⽬由apache迁移到了google code,并 且改名为MyBatis 。2013年11⽉迁移到Github.

• 官⽹:MyBatis中⽂⽹ 在上⾯我们提到⼀个词:持久层

• 持久层:指的就是持久化操作的层, 通常指数据访问层(dao), 是⽤来操作数据库的.

简单来说 MyBatis 是更简单完成程序和数据库交互的框架,也就是更简单的操作和读取数据库⼯具

MyBatis入门

mybatis操作数据库的步骤:

1. 准备工作(创建springboot工程,数据库表准备,实体类等)

2. 引入mybatis相关依赖,配置mybatis数据库连接信息

3. 通过注解或者XML文件编写SQL语句

4. 测试

准备工程

为了了导入mybatis,必须加入mybatis framework和数据区driver,如果是MySQL,则加入MySQLdriver。

项⽬⼯程创建完成后,⾃动在pom.xml⽂件中,导⼊Mybatis依赖和MySQL驱动依赖

配置数据库连接字符串

为了通过mybatis连接数据库,需要数据库配置以下相关参数:

1. MySQL启动类

2. 用户名

3. 密码

4. 数据库连接字符串

我自己的配置信息: spring: datasource: url: jdbc:mysql://localhost:3306/mybatis_test?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8 username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: configuration: map-underscore-to-camel-case: true mapper-locations: classpath:mapper/UserInfoMapperXML.xml

持久层代码

持久层代码放在mapper中,这也就是我们Dao层的另一种写法。

其中,resource文件夹中的mapper,为src文件夹中mapper的xml文件映射。一个数据库操作接口对应着XML文件中的一条sql语句。我们在后面详细介绍。

两种Mybatis的操作方法

1. 使用注解

通过注解直接操作数据库

package com.spring.mybatis.mapper; import com.spring.mybatis.model.UserInfo; import org.apache.ibatis.annotations.*; import org.springframework.stereotype.Component; import java.util.List; @Mapper public interface UserInfoMapper { @Select("select * from user_info") List<UserInfo> selectAll(); @Select("select * from User_info where id=#{id}") UserInfo selectById(int id); @Options(useGeneratedKeys = true, keyProperty = "id") @Insert("insert into user_info(username, password, age) values(#{username}, #{password}, #{age})") Integer insertUser(UserInfo userInfo); @Delete("delete from user_info where id=#{id}") Integer deleteUser(int id); @Update("update user_info set delete_flag =#{delete_flag},phone=#{phone} where id=#{id}") Integer updateUser(int id, int delete_flag, String phone); }

例如:@Select用于操作select语句,@Delete用于操作delete语句。在注解的括号中直接写入SQL语句,放在接口中定义的抽象方法上。

对于调用这个接口的其他类(层),只需要实例化这个接口,然后调用相关抽象方法即可。

package com.spring.mybatis.service; import com.spring.mybatis.mapper.UserInfoMapper; import com.spring.mybatis.model.UserInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service //service层 public class UserService { @Autowired private UserInfoMapper userInfoMapper; //实例化mapper接口 public List<UserInfo> getAllUsers() { //调用接口中的方法 return userInfoMapper.selectAll(); } public UserInfo selectById(int id) { //调用接口中的方法 return userInfoMapper.selectById(id); } public Integer insertUser(UserInfo userInfo) { //调用接口中的方法 System.out.println(userInfo.getId()); return userInfoMapper.insertUser(userInfo); } }

2. XML文件

XML文件实现Mybatis操作原理如下,interface方法定义和xml方法实现相互映射,共同组成数据持久层mapper:

import com.example.demo.model.UserInfo; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper public interface UserInfoXMlMapper { List<UserInfo> queryAllUser(); }

操作

首先,配置连接字符串和Mybatis

application.yml⽂件, 配置内容如下

# 数据库连接配置 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/mybatis_test? characterEncoding=utf8&useSSL=false username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver # 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件 mybatis: mapper-locations: classpath:mapper/**Mapper.xml #这里是xml文件的位置

随后,添加mapper接口

import com.example.demo.model.UserInfo; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper public interface UserInfoXMlMapper { List<UserInfo> queryAllUser(); }

随后,添加UserInfoXMLMapper.xml文件,放在resource文件夹中的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="com.spring.mybatis.mapper.UserInfoMapperXML"> </mapper>

注意:xml文件位置要和yml配置文件中定义的路径相对应

Mybatis的操作技巧

1. 打印日志

在yml配置文件中配置如下代码,即可打印日志

mybatis: configuration: # 配置打印 MyBatis⽇志 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

看到SQL的执行内容,参数传递和执行结果:

2. 参数传递

一般而言,SQL语句中的内容不能写成固定值,因为如果这样写每次查找都要修改值,例如查找id=4的用户,对应的SQL就是:select * from user_info where id=4。但是这样的话, 只能查找id=4 的数据, 所以SQL语句中的id值不能写成固定数值

解决方案:在queryById方法中添加⼀个参数(id),将方法中的参数,传给SQL语句

@Select("select username, `password`, age, gender, phone from user_info where id= #{id} ") //此处用的是传值,而非固定值 UserInfo queryById(Integer id);

也可以通过 @Param , 设置参数的别名, 如果用 @Param 设置别名, #{...}的属性名必须和 @Param 设置的⼀样

@Select("select username, `password`, age, gender, phone from user_info where id= #{userid} ") UserInfo queryById(@Param("userid") Integer id);

利用对象传递参数

如果设置了 @Param 属性, #{...} 需要使⽤ 参数.属性 来获取

@Insert("insert into user_info (username, `password`, age, gender, phone) values (#{userInfo.username},#{userInfo.password},#{userInfo.age},# {userInfo.gender},#{userInfo.phone})") //因为使用了@Param,在SQL获取参数时需要加上"userInfo." Integer insert(@Param("userInfo") UserInfo userInfo);

使用对象传递参数的好处

好处1:自动匹配参数

@Insert("insert into user_info (username, `password`, age, gender, phone) values (#{username},#{password},#{age},#{gender},#{phone})") Integer insert(UserInfo userInfo); 直接传入UserInfo类,自动匹配参数

好处2:返回主键

Insert 语句默认返回的是 受影响的⾏数。但有些情况下, 数据插⼊之后, 还需要有后续的关联操作, 需要获取到新插⼊数据的id

如果想要拿到自增id, 需要在Mapper接口的方法上添加⼀个Options的注解

@Options(useGeneratedKeys = true, keyProperty = "id") @Insert("insert into user_info (username, age, gender, phone) values (# {userInfo.username},#{userInfo.age},#{userInfo.gender},#{userInfo.phone})") Integer insert(@Param("userInfo") UserInfo userInfo);

useGeneratedKeys:这会令 MyBatis 使⽤ JDBC 的 getGeneratedKeys ⽅法来取出由数据库内 部⽣成的主键(⽐如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的⾃动递增字 段),默认值:false.

keyProperty:指定能够唯⼀识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)

注意事项:如果SQL中的字段和我们类属性名称不一致,将会发生匹配不上字段的情况。

如下图,框中的三个参数长相不同,无法相互匹配

解决方案:

1. 起别名

直接在SQL语句中起别名

@Select("select id, username, `password`, age, gender, phone, delete_flag as deleteFlag, " + "create_time as createTime, update_time as updateTime from user_info") public List<UserInfo> queryAllUser();

2. 结果映射

@Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from user_info") //此处进行结果映射,id = "resultMap"指的是这条结果映射的id名为resultMap,其他地方如果需要同样的映射,可以直接调用 @Results(id = "resultMap",value = { @Result(column = "delete_flag",property = "deleteFlag"), @Result(column = "create_time",property = "createTime"), @Result(column = "update_time",property = "updateTime") }) List<UserInfo> queryAllUser(); @Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time " + "from user_info where id= #{userid} ") //此处直接调用上文定义的结果映射id @ResultMap(value = "resultMap") UserInfo queryById(@Param("userid") Integer id);

3. 配置文件开启驼峰命名(推荐)

mybatis: configuration: map-underscore-to-camel-case: true #配置驼峰⾃动转换

3. #{} 和 ${}

直接说差别:#{}为预编译SQL,${}为直接字符串拼接SQL(即时SQL)

预编译SQL可以提高效率,编译⼀次之后会将编译后的SQL语句缓存起来,后面再次执行这条语句时,不会再次编译 (只是输⼊的参数不同), 省去了解析优化等过程, 以此来提⾼效率

预编译SQL可以防止SQL注入。比如sql 注入代码: ' or 1='1,如果使用${}就会被sql注入,而#{}就不会。

4. 切换数据库连接池

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用⼀个现有的数据库连接,而不是再重新建⼀个.

常⻅的数据库连接池: C3P0,DBCP,Druid,Hikari

Mybatis操作数据库进阶

1. 动态SQL

if标签

注册分为两种字段:必填字段和非必填字段,那如果在添加用户的时候有不确定的字段传入,程序应该如何实现呢?这个时候就需要使⽤动态标签 来判断了,如添加的时候性别 gender 为非必填字段,具体实现如下:

<insert id="insertUserByCondition"> INSERT INTO userinfo ( username, `password`, age, <if test="gender != null"> gender, </if> phone) VALUES ( #{username}, #{age}, <if test="gender != null"> #{gender}, </if> #{phone}) </insert>

trim标签

之前的插入用户功能,只是有⼀个 gender 字段可能是选填项,如果有多个字段,⼀般考虑使用标签结合标签,对多个字段都采取动态生成的方式。

标签中有如下属性:

• prefix:整个语句块,以prefix的值作为前缀

• suffix:整个语句块,以suffix的值作为后缀

• prefixOverrides:整个语句块要去除掉的前缀

• suffixOverrides:整个语句块要去除掉的后缀

还有如:

where标签

set标签

foreach标签

include标签

等,在这里不再详细讲解。

总之,这些标签可以让SQL语句更加灵活,适应不同的操作条件。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/11 8:07:13

MiniCPM-V2.5微调中的CUDA依赖问题解决

MiniCPM-V2.5微调中的CUDA依赖问题解决 在实际参与多个基于MiniCPM-V系列的视觉-语言模型微调项目时&#xff0c;我们反复遇到一个看似简单却极具破坏性的问题&#xff1a;训练脚本还没跑起来&#xff0c;编译阶段就失败了。最常见的报错信息来自DeepSpeed——fatal error: cu…

作者头像 李华
网站建设 2026/5/11 18:47:50

调整pose Z方向的朝向

pose_to_hom_mat3d (Pose, HomMat3D) affine_trans_point_3d (HomMat3D, [0, 0], [0, 0], [0, 1], Qx, Qy, Qz) halcon是这么做的 「 if (Qz[1] - Qz[0] > 0) Pose[4] : Pose[4] 180 Pose[5] : -Pose[5] endif 」 另外一种容易理解的方式 「 …

作者头像 李华
网站建设 2026/5/10 15:24:17

使用两个栈来实现一个队列

在 Java 中&#xff0c;利用两个栈实现队列的核心思路是通过栈的“后进先出”特性模拟队列的“先进先出”特性&#xff1a;将一个栈&#xff08;stackIn&#xff09;作为“入队栈”&#xff0c;专门处理入队操作&#xff1b;另一个栈&#xff08;stackOut&#xff09;作为“出队…

作者头像 李华
网站建设 2026/5/4 3:36:09

时序数据库 or 实时数据库?TDengine以双引擎+AI彻底破局

在物联网设备爆发、工业数字化深化的今天&#xff0c;数据处理领域正面临一场特殊的"选择困难症"&#xff1a;当每秒百万级的传感器数据涌入系统&#xff0c;既要满足长期存储后的趋势分析需求&#xff0c;又要保障毫秒级的实时决策响应&#xff0c;该选择时序数据库…

作者头像 李华
网站建设 2026/5/11 8:28:42

SQL条件中WHERE 1=1 的功能

在SQL语句中使用 WHERE 11 是一种常见的编程技巧。主要有以下几个原因&#xff1a;1. 动态SQL构建的便利性这是最主要的原因。当需要根据不同的条件动态构建SQL查询时&#xff0c;WHERE 11 提供了一个"占位符"&#xff0c;让后续的条件可以统一用 AND 连接。不使用 W…

作者头像 李华
网站建设 2026/5/4 20:52:08

Langchain-Chatchat能否导出问答记录?

Langchain-Chatchat 能否导出问答记录&#xff1f; 在企业逐步将大语言模型&#xff08;LLM&#xff09;引入内部知识管理的今天&#xff0c;一个看似简单却至关重要的问题浮出水面&#xff1a;用户和 AI 助手之间的对话&#xff0c;能不能留下来&#xff1f; 比如&#xff0…

作者头像 李华