java mybatis(超详细)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在 Java 生态系统中,数据库操作始终是开发的核心任务之一。随着企业级应用的复杂度提升,开发者需要一种灵活且高效的工具,来简化 SQL 与 Java 对象之间的映射工作。Java MyBatis 正是这样一个轻量级的持久层框架,它通过“半自动化”的方式,帮助开发者在不牺牲灵活性的前提下,快速实现数据持久化。本文将从基础概念到实战案例,逐步解析 MyBatis 的核心原理与使用技巧,并通过具体示例帮助读者掌握其核心功能。
一、MyBatis 的核心概念
1.1 什么是 MyBatis?
MyBatis 是一个基于 Java 的持久层框架,它专注于 SQL 语句的执行与结果映射。与传统的 ORM(对象关系映射)框架(如 Hibernate)不同,MyBatis 采用“半自动化”策略:开发者需要手动编写 SQL 语句,但 MyBatis 能自动将查询结果转换为 Java 对象。这种设计既保留了对 SQL 的精细控制,又避免了纯 JDBC 编程的繁琐性。
1.2 核心组件解析
- SqlSessionFactory:数据库会话的工厂类,类似于 JDBC 的 ConnectionFactory,负责创建 SqlSession 对象。
- SqlSession:与数据库交互的核心接口,提供执行 SQL、管理事务等方法。
- Mapper:定义 SQL 语句的接口或 XML 文件,是 MyBatis 的核心配置单元。
比喻:可以将 MyBatis 想象为一座桥梁,它连接着 Java 代码(上层建筑)与数据库(下层基础设施)。开发者只需专注于如何“过桥”(编写 SQL 和映射逻辑),而桥梁本身(MyBatis 内部机制)则自动处理连接、事务等底层细节。
二、环境搭建与配置
2.1 依赖引入
在 Maven 项目中,需添加 MyBatis 的核心依赖:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
2.2 配置 mybatis-config.xml
MyBatis 的全局配置文件 mybatis-config.xml
定义了框架的运行规则,例如数据源、类型别名、映射文件路径等。以下是一个基础配置示例:
<?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/mydb"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
2.3 初始化 SqlSessionFactory
通过 SqlSessionFactoryBuilder
加载配置文件,创建会话工厂:
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
三、CRUD 操作实战
3.1 创建(Create)
假设有一个 User
实体类:
public class User {
private Integer id;
private String name;
private Integer age;
// 构造方法、Getter 和 Setter 省略
}
在 UserMapper.xml
中定义插入语句:
<insert id="insertUser" parameterType="User">
INSERT INTO users (name, age)
VALUES (#{name}, #{age})
</insert>
调用代码示例:
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User("Alice", 25);
mapper.insertUser(user);
session.commit(); // 提交事务
}
3.2 查询(Retrieve)
通过 select
标签实现查询操作:
<select id="selectUserById" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
调用方式:
try (SqlSession session = sqlSessionFactory.openSession()) {
User user = session.selectOne("selectUserById", 1);
System.out.println(user.getName()); // 输出 "Alice"
}
3.3 更新与删除(Update & Delete)
更新操作示例:
<update id="updateUser" parameterType="User">
UPDATE users
SET name = #{name}, age = #{age}
WHERE id = #{id}
</update>
删除操作示例:
<delete id="deleteUserById" parameterType="int">
DELETE FROM users WHERE id = #{id}
</delete>
四、动态 SQL 与条件构建
在实际开发中,SQL 语句的条件可能根据参数动态变化。MyBatis 提供了 <if>
、<choose>
、<where>
等标签,帮助开发者构建动态 SQL。
4.1 基础条件判断
<select id="selectUserByCondition" resultType="User">
SELECT * FROM users
WHERE 1=1
<if test="name != null">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="age != null">
AND age >= #{age}
</if>
</select>
4.2 复合条件选择
<choose>
<when test="age > 30">
AND age BETWEEN 30 AND 50
</when>
<otherwise>
AND age < 30
</otherwise>
</choose>
4.3 自动处理 WHERE 子句
使用 <where>
标签可自动忽略冗余的 AND
或 OR
关键字:
<select id="selectUserByCondition" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">
name LIKE CONCAT('%', #{name}, '%')
</if>
</where>
</select>
五、关联查询与结果映射
当需要查询关联表时,可以通过 <resultMap>
定义复杂的映射关系。例如,一个用户可能有多个订单:
5.1 一对一映射
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id"/>
<result property="name" column="user_name"/>
<association property="address" javaType="Address">
<id property="id" column="address_id"/>
<result property="street" column="street_name"/>
</association>
</resultMap>
5.2 一对多映射
<resultMap id="userOrderResultMap" type="User">
<id property="id" column="user_id"/>
<collection property="orders" ofType="Order">
<id property="id" column="order_id"/>
<result property="amount" column="order_amount"/>
</collection>
</resultMap>
六、高级特性与最佳实践
6.1 缓存机制
MyBatis 提供一级缓存(SqlSession 级)和二级缓存(Mapper 级)。通过开启二级缓存可提升查询性能:
<cache/> <!-- 默认使用 PerpetualCache 实现 -->
6.2 分页查询
通过 RowBounds
或 LIMIT
子句实现分页:
List<User> users = session.selectList("selectUsers", null, new RowBounds(0, 10));
6.3 代码注解替代 XML
MyBatis 也支持使用注解定义 SQL 语句:
@Select("SELECT * FROM users WHERE id = #{id}")
User selectUserById(@Param("id") int userId);
七、常见问题与解决方案
7.1 SQL 注入风险
使用 #{}
占位符而非 ${}
可避免 SQL 注入,因为前者会对参数进行预编译处理。
7.2 性能优化
- 避免在循环中执行单条 SQL,改用批量操作。
- 对频繁查询的表启用二级缓存。
7.3 映射不匹配问题
确保实体类字段名与数据库列名一致,或通过 <result>
标签显式指定列名映射。
结论
Java MyBatis 凭借其灵活性与易用性,成为 Java 开发者处理数据库操作的首选工具之一。从基础的 CRUD 操作到复杂的动态 SQL 和关联映射,MyBatis 的设计始终围绕“开发者可控”这一核心理念展开。通过本文的示例与解析,读者应能快速掌握 MyBatis 的核心功能,并在实际项目中应用其解决业务需求。未来的学习方向可进一步探索 MyBatis 的插件机制、与 Spring 框架的集成,以及更高级的性能优化策略。
本文通过循序渐进的方式,结合代码示例与场景化解释,帮助开发者快速上手 MyBatis。如需深入学习,建议参考官方文档并参与实际项目实践。