MyBatis笔记
MyBatis
1.1 简介
什么是MyBatis?
- MyBatis是一款优秀的持久层框架,用于简化JDBC开发
- MyBatis本是Apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了google code,并且改名为MyBatis。2013年11月迁移到Github
- 官网:https://mybatis.org/mybatis-3/zh/index.html
持久层:
- 负责将数据保存到数据库的那一层代码
- JavaEE三层架构:表现层、业务层、持久层
持久层的含义:就是将数据进行持久化的一层(存进数据库就长久保存,所以持久)
框架:
- 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型
- 在框架的基础上构建软件编写更加高效、规范、通用、可扩展
JDBC的缺点 ---> MyBatis的优点:
-
硬编码 ---> MyBatis使用配置文件
-
注册驱动,获取链接
-
SQL语句
-
-
操作繁琐 ---> MyBatis自动完成
- 手动设置参数
- 手动封装结果集
1.2 快速入门
例:查询user表中的信息
- 创建user表,添加数据
-
创建模板,导入坐标
<!-- MyBatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.29</version> </dependency>
-
编写MyBatis核心配置文件 --> 替换连接信息,解决硬编码问题
-
创建mybatis-config.xml文件位于resources文件夹下
-
编写mybatis-config.xml配置信息,可在官网获取
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <!-- 连接信息 --> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"/> <property name="username" value="${username}"/> <!--数据库用户名--> <property name="password" value="${password}"/> <!--密码--> </dataSource> </environment> </environments> <mappers> <!-- 加载sql映射文件 --> <mapper resource="User.xml"/> </mappers> </configuration>
-
-
编写SQL映射文件 --> 统一管理sql语句,解决硬编码问题
-
在resources文件夹下创建UserMapper.xml文件
-
编写UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace:名称空间 --> <mapper namespace="test"> <select id="selectAll" resultType="com.hqa.pojo.User"> select * from user </select> </mapper>
-
-
编码
- 定义POJO类(pojo文件夹中创建User的JavaBean类)
//1.加载mybatis的核心配置文件,获取SqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //2.获取SqlSession对象,用它来执行Sql SqlSession sqlSession = sqlSessionFactory.openSession(); //3.执行sql List<User> users = sqlSession.selectList("test.selectAll"); System.out.println(users); //4.释放资源 sqlSession.close();
1.3 Mapper 代理开发
使用Mapper代理开发的目的:
- 解决原生方式中的硬编码
- 简化后期执行SQL
同上一章的例子:
-
定义与SQL映射文件同名的Mapper接口,并且将Mapper接口和SQL映射文件放置在同一目录下
因为resource目录在编译后就和java文件一样都存在classes目录下,所以只需在resource目录下创建和Mapper接口的目录结构相同的文件夹即可
-
设置SQL映射文件的namespace属性为Mapper接口为全限定名
-
在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致
public interface UserMapper { List<User> selectAll(); //返回值为一个Userd对象集合 }
-
编码
-
通过SqlSession的getMapper方法获取Mapper接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
-
调用对应方法完成sql的执行
List<User> users = userMapper.selectAll(); System.out.println(users);
-
1.4 MyBatis 核心配置文件
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
配置各个标签时,需要遵守以上列表的前后顺序
常用配置:
-
类型别名
<typeAliases> <package name="domain.blog"/> <!--包名--> </typeAliases>
这样可以省略映射文件中返回类型的缩写
<!--原来的--> <select id="selectAll" resultType="com.hqa.pojo.User"> select * from user </select> <!--使用别名--> <select id="selectAll" resultType="user"> select * from user </select>
1.5 字段映射
查询结果NULL,出现这个问题一般是数据库字段名与实体类名不相符,使用resultMap字段映射可解决这个问题
resultMap中标签有两种类型:
- id:完成主键字段的映射
- column:表的列名
- property:实体类的属性名
- result:完成一般字段的映射
- column:表的列名
- property:实体类的属性名
1.6 MyBatis 细节
1.6.1 占位符
MyBatis的参数占位符有两种:
- #{}:会将其替换为 ? ,为了防止SQL注入。(一般用这个)
- ${}:拼接sql,会存在SQL注入问题
- 使用时机:
- 参数传递时,用#{}
- 表名或者列名不固定的情况下,用${}
1.6.2 特殊字符处理
-
转义符
例: < 的转义字符为
<
-
CDATA区
例:
<![CDATA[内容]]>
IDEA中打CD后即可自动补全
1.6.3 参数传递方式
mybatis参数的传递有三种方式:
- 散装参数
- 需要使用@Param("SQL中的参数占位符名称")
- 对象参数
- 只需要保证SQL中的参数名和实体类属性名对应上,即可设置成功
- map集合参数
- 只需要保证SQL中的参数名和map集合的键的名称对应上,即可设置成功
1.6.4 主键返回
在添加数据成功后,需要获取插入数据库数据的主键的值,这时候就需要使用主键返回
开启主键返回方法:
在insert标签里添加useGeneratedKeys="true"和keyProperty="id"在两个属性
<!-- 插入数据 -->
<insert id="addAll" useGeneratedKeys="true" keyProperty="id">
insert into tb_brand(brand_name, company_name, ordered, description, status)
value (#{brandName}, #{companyName}, #{ordered}, #{description}, #{status});
</insert>
1.7 动态SQL
SQL语句会随用户的输入或外部条件的变化而变化,我们称为动态SQL
-
MyBatis对动态sql有很强大的支撑
-
if
-
choose (when, otherwise)
-
trim (where, set)
-
foreach
-
1.7.1 动态条件查询
<!-- 条件查询 -->
<select id="selectByCondition" resultMap="BrandResultMap">
select * from tb_brand
where status like #{status}
and company_name like #{companyName}
and brand_name like #{brandName}
</select>
<!-- 动态条件查询 where -->
<select id="selectByCondition" resultMap="BrandResultMap">
select * from tb_brand
<where>
<if test="status != null">
and status like #{status}
</if>
<if test="companyName != null and companyName != ''">
and company_name like #{companyName}
</if>
<if test="brandName != null and brandName != ''">
and brand_name like #{brandName}
</if>
</where>
</select>
<!-- 动态条件查询 choose -->
<select id="selectByCondition" resultMap="BrandResultMap">
select * from tb_brand
<where>
<choose>
<when test="status != null">
and status like #{status}
</when>
<when test="companyName != null and companyName != ''">
and company_name like #{companyName}
</when>
<when test="brandName != null and brandName != ''">
and brand_name like #{brandName}
</when>
<otherwise>
1 = 1
</otherwise>
</choose>
</where>
</select>
1.7.2 动态修改字段
<!-- 修改数据 -->
<update id="updateAll">
update tb_brand
set brand_name = #{brandName},
company_name = #{companyName},
ordered = #{ordered},
description = #{description},
status = #{status}
where
id = #{id}
</update>
<!--
使用上面的修改数据,如果用户只修改其中一条数据,那么其他数据可能会跟着被修改,所以使用动态修改会更加安全
-->
<!-- 动态修改数据 -->
<update id="updateAll">
update tb_brand
<set>
<if test="brandName != null and brandName != ''">
brand_name = #{brandName},
</if>
<if test="companyName != null and companyName != ''">
company_name = #{companyName},
</if>
<if test="ordered != null">
ordered = #{ordered},
</if>
<if test="description != null and description != ''">
description = #{description},
</if>
<if test="status != null">
status = #{status}
</if>
</set>
where id = #{id}
</update>
1.7.2 批量删除数据
mapper:
void deleteByIds(@Param("ids")int[] ids);
@Param 注解修改key名
<!-- 删除单条数据 -->
<delete id="deleteById">
delete from tb_brand where id = #{id}
</delete>
<!-- 批量删除数据 -->
<delete id="deleteByIds">
delete from tb_brand
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
foreach标签中:separator 分隔符 open 起始符 open 结束符
1.8 MyBatis 参数传递
MyBatis 接口方法中可以接收各种各样的参数,MyBatis 底层对于这些参数进行不同的封装处理方式
-
单个参数
-
POJO类型:直接使用,实体类属性名和参数占位符名称一致
-
Map类型:直接使用,键名和参数占位符名称一致
-
Collection:封装为Map集合
map.put("collection", collection集合); map.put("agr0", collection集合);
-
List:封装为Map集合
map.put("collection", list集合); map.put("list", list集合); map.put("arg0", list集合);
-
Array:封装为Map集合
map.put("array", 数组); map.put("arg0", 数组);
-
其他类型:直接使用
-
多个参数:封装为Map集合
map.put("agr0", 参数值1); map.put("param1", 参数值1); map.put("agr1", 参数值2); map.put("param2", 参数值2);
将来都用@Param注解来修改Map集合中默认的键名,并使用修改后的名称来取值,这样可读性更高,如:
void deleteByIds(@Param("ids")int[] ids);
-
1.9 注解开发
- 查询:@Select
- 添加:@Insert
- 修改:@Update
- 删除:@Delete
如:
package org.mybatis.example;
public interface BlogMapper {
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}
使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。
也就是注解完成简单功能,配置文件完成复杂功能
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了