Mybatis
- [Mybatis 简介](#Mybatis 简介)
- [1.Mybatis 基础使用](#1.Mybatis 基础使用)
-
- [1.1 安装依赖](#1.1 安装依赖)
- [1.2 从 XML 中构建 SqlSessionFactory](#1.2 从 XML 中构建 SqlSessionFactory)
- [1.3 从 SqlSessionFactory 中获取 SqlSession 执行sql](#1.3 从 SqlSessionFactory 中获取 SqlSession 执行sql)
- [2.基于 Spring Boot 使用 Mybatis](#2.基于 Spring Boot 使用 Mybatis)
-
- [2.1 创建 Spring Boot demo 项目](#2.1 创建 Spring Boot demo 项目)
- [2.2 编写相关代码](#2.2 编写相关代码)
- [3.Mybatis 增删改查](#3.Mybatis 增删改查)
-
- [3.1 查(select)](#3.1 查(select))
- [3.2 增](#3.2 增)
- [3.3 删](#3.3 删)
- [3.4 改](#3.4 改)
- [4. 动态SQL](#4. 动态SQL)
Mybatis 简介
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
1.Mybatis 基础使用
1.1 安装依赖
xml
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.1</version>
</dependency>
1.2 从 XML 中构建 SqlSessionFactory
每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例
java
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。
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"。 -->
<environments default="development">
<!-- 在<environments>元素内部,<environment>元素用于定义具体的环境,这里只有一个名为"development"的环境。 -->
<environment id="development">
<!-- 指定事务管理器 还有 JTA(Java Transaction API)事务管理器等 -->
<transactionManager type="JDBC"/>
<!-- <dataSource>元素定义数据源,类型为"POOLED",表示使用连接池。-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="120125hzy."/>
</dataSource>
</environment>
</environments>
<mappers>
<!--<mappers>元素用于配置MyBatis的映射器(mapper)。-->
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
1.3 从 SqlSessionFactory 中获取 SqlSession 执行sql
既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。
创建 UserMapper.java
java
public interface UserMapper {
// @Param 是 MyBatis 中用于给方法参数起别名的注解。这个注解主要用于在 XML 映射文件中引用参数时,提供一个明确的名称。
User selectUser(@Param("id") int id);
}
创建 UserMapper.xml
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.hzy.mybatis.UserMapper">
<select id="selectUser" resultType="com.hzy.mybatis.User">
select * from user where id=${id}
</select>
</mapper>
UserMapper.java 与 UserMapper.xml 是一一对应的
获取 SqlSession 执行sql
java
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectUser(1);
System.out.println(user);
}
}
与 上篇文章 讲的 JDBC 的操作流程:
txt
1. 创建数据库连接池 DataSource
2. 通过 DataSource 获取数据库连接 Connection
3. 编写要执行带 ? 占位符的 SQL 语句
4. 通过 Connection 及 SQL 创建操作命令对象 Statement
5. 替换占位符:指定要替换的数据库字段类型,占位符索引及要替换的值
6. 使⽤ Statement 执行 SQL 语句
7. 查询操作:返回结果集 ResultSet,更新操作:返回更新的数量
8. 处理结果集
9. 释放资源
相比,Mybatis 简单了许多,但还是要手动配置一些核心组件如如 SqlSessionFactory
、DataSource
、TransactionManager
等。
所以我们一般基于 SpringBoot 使用 Mybatis 来简化开发。
2.基于 Spring Boot 使用 Mybatis
Spring Boot 是一个现代的、约定大于配置的框架,通过 Spring Boot 的自动配置和约定来简化整体架构,大大减少了手动配置的需求,提高了开发效率。
在 Spring Boot 中,只需在配置文件中指定数据库连接等少量信息,Spring Boot 将会根据约定自动配置 MyBatis 相关组件,包括创建 SqlSessionFactory
、DataSource
、TransactionManager
等。
2.1 创建 Spring Boot demo 项目
选择数据库修改依赖
2.2 编写相关代码
配置文件
yml
Spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 120125hzy.
type: com.alibaba.druid.pool.DruidDataSource
mybatis:
type-aliases-package: com.hzy.demo.pojos # 指定MyBatis实体类的包路径,使得在XML文件中可以直接使用类名而不是全限定名。
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志
map-underscore-to-camel-case: true # 将数据库字段的下划线命名方式映射为Java驼峰命名方式
pojos.User
java
@Data
public class User {
private int id;
private String name;
private Double balance;
private String homeAddr;
}
mapper.UserMapper
java
@Mapper
public interface UserMapper {
User selectUser(@Param("id") int id);
}
UserMapper.xml
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.hzy.demo.mapper.UserMapper">
<!--resultType="User" 这里不需要写全限定名。-->
<select id="selectUser" resultType="User">
select * from user2 where id=${id}
</select>
</mapper>
测试代码
java
@Test
void test01(){
User user = userMapper.selectUser(1);
System.out.println(user);
}
当前的目录结构
需要注意的是 UserMapper 和 UserMapper.xml 文件的路径要相同,不同会报错
或者在配置文件中指定 Mapper.xml 文件的目录
yml
mybatis:
mapper-locations: classpath:/mybatis/mappers/*.xml
3.Mybatis 增删改查
3.1 查(select)
MyBatis 使用 <select>
元素来定义查询语句。查询可以返回单个实体对象、集合对象或基本类型的值。
xml
<!-- User selectUser(@Param("id") int id); -->
<select id="selectUser" parameterType="int" resultType="User">
select * from user2 where id=${id}
</select>
selectUser
是查询语句的唯一标识符,parameterType
指定了传递给查询的参数类型,resultType
指定了查询结果的返回类型。
对于简单 sql 语句可以直接使用@Select()
注解实现
java
@Select("select * from user2 where id=${id}")
User selectUser(@Param("id") int id);
测试
java
@Test
void test01(){
User user = userMapper.selectUser(1);
System.out.println(user);
}
3.2 增
MyBatis 使用 <insert>
元素来定义插入语句。
xml
<!-- int addUser(User user); -->
<insert id="addUser" parameterType="User">
insert into user2(name,balance,home_addr) values(#{name},#{balance},#{homeAddr})
</insert>
insertUser
是插入语句的唯一标识符,parameterType
指定了传递给插入语句的参数类型,name,balance,homeAddr是 User 的属性
同样也可以使用@Insert()
注解实现:
java
@Insert("insert into user2(name,balance,home_addr) values(#{name},#{balance},#{homeAddr})")
int addUser(User user);
测试
java
@Test
void test03(){
User user = new User();
user.setName("李四");
user.setBalance(1200.0);
user.setHomeAddr("cq");
int i = userMapper.addUser(user);
assert i == 1;
}
3.3 删
MyBatis 使用 <delete>
元素来定义删除语句。
xml
<!-- int removeUserById(@Param("id") int id); -->
<delete id="removeUserById" parameterType="int">
delete from user2 where id = #{id}
</delete>
MyBatis 使用 <delete>
元素来定义删除语句。
同样也可以使用@Insert()
注解实现:
java
@Delete("delete from user2 where id = #{id}")
int removeUserById(@Param("id") int id);
测试
java
@Test
void test04(){
int i = userMapper.removeUserById(4);
assert i == 1;
}
3.4 改
MyBatis 使用 <update>
元素来定义更新语句。
xml
<!--int updateUserById(User user);-->
<update id="updateUserById" parameterType="User">
update user2 set name=#{name},balance=#{balance},home_addr=#{homeAddr} where id = #{id}
</update>
同样使用@Update()
注解也行
java
@Update("update user2 set name=#{name},balance=#{balance},home_addr=#{homeAddr} where id = #{id}")
int updateUserById(User user);
测试
java
@Test
void test05(){
User user = new User();
user.setId(4);
user.setName("哈哈哈");
user.setBalance(1000.0);
user.setHomeAddr("sh");
int i = userMapper.updateUserById(user);
assert i == 1;
}
因为前面已经删除id为4的数据所以这里断言未通过
4. 动态SQL
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
4.1 if
判断一个参数是否有值的,如果没值,那么就会隐藏 if 中的 sql
xml
<!-- List<User> selectUsers(@Param("id") Integer id); -->
<select id="selectUsers" resultType="User">
select * from user2
<if test="id != null">
where id=#{id}
</if>
</select>
测试
java
@Test
void test06(){
List<User> users = userMapper.selectUsers(null);
for(User user: users){
System.out.println(user);
}
}
通常情况下 if 标签会和 where 标签一起用,不然有可能出现 select * from user2 where 这样的语句。
xml
<!--List<User> selectUsers(User user);-->
<select id="selectUsers" resultType="User">
select * from user2
<where>
<if test="name != null and name != '' ">
and name like concat('%',#{name},'%')
</if>
<if test="homeAddr != null and homeAddr != '' ">
and home_addr = #{homeAddr}
</if>
</where>
</select>
测试
java
@Test
void test06(){
User user = new User();
List<User> users = userMapper.selectUsers(user);
for(User u: users){
System.out.println(u);
}
System.out.println("不带参查询");
user.setName("s");
user.setHomeAddr("sh");
users = userMapper.selectUsers(user);
for(User u: users){
System.out.println(u);
}
System.out.println("带参查询");
}
4.2 choose、when、otherwise 标签
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
xml
<!--List<User> selectUsers(User user);-->
<select id="selectUsers" resultType="User">
select * from user2 where
<choose>
<when test="name != null and name != '' ">
name like concat('%',#{name},'%')
</when>
<when test="homeAddr != null and homeAddr != '' ">
home_addr = #{homeAddr}
</when>
<otherwise>
id = 1
</otherwise>
</choose>
</select>
测试
java
@Test
void test06(){
User user = new User();
List<User> users = userMapper.selectUsers(user);
for(User u: users){
System.out.println(u);
}
System.out.println("不带参查询");
user.setName("s");
user.setHomeAddr("sh");
users = userMapper.selectUsers(user);
for(User u: users){
System.out.println(u);
}
System.out.println("带参查询");
}
虽然传入两个参数只生效了一个参数
4.3 foreach 标签
<foreach>
元素用于迭代集合或数组,动态生成 SQL 片段。这在处理 IN 子句中的多个参数时非常有用。
java
// 批量删除
int removeUserByIds(@Param("ids") List<Integer> ids);
xml
<delete id="removeUserByIds">
delete
from user2
where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
foreach 标签中主要属性介绍:
txt
collection:绑定方法参数中的集合,如List, Set, Map或数组对象
item:遍历时的每一个对象
open:语句块开头的字符串
close:语句块结束的字符串
separator:每次遍历之间间隔的字符串
测试
java
@Test
void test07(){
int i = userMapper.removeUserByIds(Arrays.asList(3,5,6));
assert i == 3;
}
4.4 where trim set
trim
<trim>
标签:<trim>
标签用于处理字符串拼接时可能出现的空格问题。它包含了四个属性:prefix
、suffix
、prefixOverrides
、suffixOverrides
,用于在SQL语句的拼接时添加前缀、后缀,或者移除多余的前缀、后缀。
修改前面的修改语句
xml
<update id="updateUserById" parameterType="User">
update user2
<trim prefix="SET" suffixOverrides=",">
<if test="name != null" >
name = #{name},
</if>
<if test=" balance != null">
balance = #{balance},
</if>
<if test="home_addr != null">
home_addr = #{homeAddr},
</if>
</trim>
where id = #{id}
</update>
在上述例子中,<trim>
标签用于处理SET
关键字后可能出现的多余逗号。
set
<set>
标签:<set>
标签用于处理UPDATE语句中SET关键字后可能出现的多余逗号,并且可以灵活地处理更新字段。
xml
<update id="updateUserById" parameterType="User">
update user2
<set>
<if test="name != null" >
name = #{name},
</if>
<if test=" balance != null">
balance = #{balance},
</if>
<if test="home_addr != null">
home_addr = #{homeAddr},
</if>
</set>
where id = #{id}
</update>
这个和语句和上面 <trim>
标签实现的功能一样,区别在于使用<trim>
标签,手动指定了SET关键字和可能的多余逗号的处理方式。
而<set>
标签,它自动处理了SET关键字后可能出现的多余逗号,确保生成的SQL语句是合法的。
两者相比<set>
标签更直观,而<trim>
标签更加灵活,允许你手动指定前缀和后缀。
where
<where>
标签:<where>
标签用于将WHERE关键字加到SQL语句中,并且能够智能处理条件语句的连接。如果条件语句中的第一个条件是AND或OR,<where>
标签会自动将其去除。
前面提到过。