MyBatis 是一个优秀的持久层框架,它消除了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程。MyBatis 提供了一个基于 XML 或注解的配置,可以灵活的将 SQL 语句、存储过程与 Java 对象映射起来。相比于 Hibernate 等全自动 ORM 框架,MyBatis 允许开发者手动编写 SQL,控制更灵活。
1. MyBatis 安装
1.1 环境准备
在开始之前,确保你已经配置好 Java 开发环境(JDK 8 或更高版本)并安装了 Maven 或 Gradle 构建工具。还需要有一个数据库环境,比如 MySQL。
1.2 使用 Maven 项目引入 MyBatis
如果你使用的是 Maven 项目,需在项目的 pom.xml
文件中添加 MyBatis 依赖:
<dependencies>
<!-- MyBatis 核心依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version> <!-- 确保使用最新版本 -->
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
</dependencies>
1.3 使用 Gradle 项目引入 MyBatis
如果你使用 Gradle,则需要在 build.gradle
文件中添加以下依赖:
dependencies {
implementation 'org.mybatis:mybatis:3.5.10'
implementation 'mysql:mysql-connector-java:8.0.27'
}
2. MyBatis 配置
2.1 配置 MyBatis 的 mybatis-config.xml
MyBatis 的核心配置文件是 mybatis-config.xml
。你可以在此文件中定义数据库连接信息、全局配置等。文件通常位于 resources
目录下。
示例:
<?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>
<!-- 环境配置 -->
<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/mybatis_db?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
<!-- Mapper XML 配置位置 -->
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>
关键解释:
<environments>
:指定不同的数据库环境配置,如开发环境、测试环境等。这里我们只配置了一个development
环境。<transactionManager>
:选择事务管理器。这里使用 JDBC 提供的事务管理。<dataSource>
:配置数据库连接的基本信息,包括驱动、URL、用户名和密码。<mappers>
:指向 Mapper XML 文件,该文件用于编写 SQL 语句并进行映射。
2.2 配置数据库连接属性
将数据库的连接信息保存在 db.properties
文件中,并在 mybatis-config.xml
中引入。
db.properties
:
db.driver=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/mybatis_db?useSSL=false&serverTimezone=UTC
db.username=root
db.password=password
在 mybatis-config.xml
中引入:
<properties resource="db.properties"/>
3. MyBatis 基本操作
3.1 创建实体类
创建一个 Java 实体类,用于映射数据库中的表。假设我们有一个 User
表,对应的实体类如下:
public class User {
private int id;
private String name;
private String email;
// Getter 和 Setter 方法
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
3.2 创建 Mapper 接口
Mapper 接口用于定义数据库操作方法。下面是 UserMapper
接口的例子:
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User getUserById(int id);
@Select("SELECT * FROM users")
List<User> getAllUsers();
@Insert("INSERT INTO users(name, email) VALUES(#{name}, #{email})")
void insertUser(User user);
@Update("UPDATE users SET name=#{name}, email=#{email} WHERE id=#{id}")
void updateUser(User user);
@Delete("DELETE FROM users WHERE id=#{id}")
void deleteUser(int id);
}
3.3 创建 Mapper XML 文件
Mapper XML 文件中,我们可以定义 SQL 语句。假设我们不使用注解而是使用 XML 配置,UserMapper.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="UserMapper">
<!-- 查询所有用户 -->
<select id="getAllUsers" resultType="User">
SELECT * FROM users
</select>
<!-- 通过 ID 查询用户 -->
<select id="getUserById" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
<!-- 插入新用户 -->
<insert id="insertUser" parameterType="User">
INSERT INTO users(name, email) VALUES(#{name}, #{email})
</insert>
<!-- 更新用户信息 -->
<update id="updateUser" parameterType="User">
UPDATE users SET name=#{name}, email=#{email} WHERE id=#{id}
</update>
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="int">
DELETE FROM users WHERE id=#{id}
</delete>
</mapper>
3.4 MyBatis 主程序
在主程序中加载 MyBatis 配置,并调用 Mapper 执行操作。示例如下:
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MyBatisApp {
public static void main(String[] args) throws IOException {
// 读取 MyBatis 配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 构建 SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 获取 SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
// 插入新用户
User newUser = new User();
newUser.setName("Alice");
newUser.setEmail("alice@example.com");
mapper.insertUser(newUser);
session.commit(); // 提交事务
// 查询所有用户
List<User> users = mapper.getAllUsers();
users.forEach(user -> System.out.println(user.getName() + " - " + user.getEmail()));
}
}
}
4. MyBatis 事务管理
MyBatis 默认的事务管理是自动提交的。为了手动控制事务,你可以在 SqlSession
中使用 commit()
、rollback()
来进行事务管理。
示例:
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.getUserById(1);
user.setName("Updated Name");
mapper.updateUser(user);
session.commit(); // 手动提交事务
} catch (Exception e) {
session.rollback(); // 出现异常时回滚
}
补充:MyBatis 进阶概念
在基础的 MyBatis 使用之外,MyBatis 还提供了高级功能,比如动态 SQL、缓存机制、动态代理机制,以及如何使用注解进行开发。
1. 动态 SQL
动态 SQL 是 MyBatis 强大的功能之一,允许根据不同的条件动态生成 SQL 语句。MyBatis 使用 <if>
、<choose>
、<when>
、<otherwise>
、<foreach>
等标签来实现动态 SQL。
1.1 <if>
标签
根据条件判断是否生成 SQL 片段。
<select id="getUserByConditions" resultType="User">
SELECT * FROM users WHERE 1=1
<if test="name != null">
AND name = #{name}
</if>
<if test="email != null">
AND email = #{email}
</if>
</select>
1.2 <choose>
标签
类似于 Java 中的 switch-case
,根据条件选择执行的 SQL 片段。
<select id="getUserByNameOrEmail" resultType="User">
SELECT * FROM users
<where>
<choose>
<when test="name != null">
name = #{name}
</when>
<when test="email != null">
email = #{email}
</when>
<otherwise>
1 = 1
</otherwise>
</choose>
</where>
</select>
1.3 <foreach>
标签
用于遍历集合,比如 List
、Set
或数组,生成 SQL 语句,常用于 IN
查询。
<select id="getUsersByIds" resultType="User">
SELECT * FROM users WHERE id IN
<foreach collection="idList" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
2. MyBatis 缓存机制
MyBatis 提供了两级缓存机制:一级缓存和二级缓存。
2.1 一级缓存
一级缓存是 SqlSession 级别的缓存,即同一个 SqlSession 执行相同的查询时,结果会被缓存。一级缓存是默认开启的。
- 特点:
- SqlSession 关闭或提交后,一级缓存失效。
- SqlSession 级别的缓存是线程不安全的。
2.2 二级缓存
二级缓存是全局(Mapper 级别)的缓存。多个 SqlSession 可以共享二级缓存。需要在 mybatis-config.xml
中开启二级缓存。
开启二级缓存的步骤:
-
在
mybatis-config.xml
中添加以下配置:<settings> <setting name="cacheEnabled" value="true"/> </settings>
-
在 Mapper XML 文件中启用缓存:
<cache/>
二级缓存的使用案例:
<mapper namespace="UserMapper">
<cache/>
<select id="getUserById" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
</mapper>
当 SQL 执行后,结果会缓存到二级缓存中。注意,如果使用了 insert
、update
或 delete
操作,会清空缓存。
3. MyBatis 动态代理机制
动态代理机制 是 MyBatis 核心的一部分,它通过 Java 的反射和动态代理机制,自动为 Mapper 接口生成实现类,开发者只需定义接口,而不必手动编写实现类。MyBatis 根据 XML 配置或注解生成 Mapper 实现。
动态代理实现的步骤:
-
定义 Mapper 接口,比如
UserMapper
:public interface UserMapper { User getUserById(int id); }
-
通过
SqlSession
动态生成 Mapper 实现类:try (SqlSession session = sqlSessionFactory.openSession()) { UserMapper mapper = session.getMapper(UserMapper.class); User user = mapper.getUserById(1); }
MyBatis 会在运行时通过动态代理为 UserMapper
接口生成实现类。
4. 注解开发
MyBatis 允许通过注解开发,无需 XML 配置文件。注解直接在 Mapper 接口上使用,常用的注解有 @Select
、@Insert
、@Update
、@Delete
等。
4.1 @Select
注解
用于查询操作。
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User getUserById(int id);
}
4.2 @Insert
注解
用于插入操作。
public interface UserMapper {
@Insert("INSERT INTO users(name, email) VALUES(#{name}, #{email})")
void insertUser(User user);
}
4.3 @Update
注解
用于更新操作。
public interface UserMapper {
@Update("UPDATE users SET name=#{name}, email=#{email} WHERE id=#{id}")
void updateUser(User user);
}
4.4 @Delete
注解
用于删除操作。
public interface UserMapper {
@Delete("DELETE FROM users WHERE id=#{id}")
void deleteUser(int id);
}
通过使用注解,可以大大减少 XML 配置文件的数量,简化开发过程,但对于复杂 SQL 还是推荐使用 XML。
总结
- 动态 SQL:MyBatis 提供了灵活的 SQL 生成机制,支持根据不同条件动态生成 SQL。
- 缓存机制:MyBatis 支持一级缓存和二级缓存,能够提高查询效率。一级缓存是默认开启的,二级缓存需要手动配置。
- 动态代理机制:MyBatis 通过动态代理机制为 Mapper 接口生成实现类,开发者只需定义接口即可。
- 注解开发:MyBatis 提供了基于注解的开发方式,简化了 Mapper 接口的实现和 SQL 配置。