JDBC与MyBatis全面解析:从基础到比较
目录
第一部分:JDBC基础知识
1. JDBC概述
JDBC核心组件:
2. JDBC工作原理
3. JDBC核心API详解
Connection接口
Statement接口
PreparedStatement接口
ResultSet接口
4. JDBC事务管理
5. JDBC批处理
6. JDBC连接池
第二部分:MyBatis基础知识
1. MyBatis概述
MyBatis核心组件:
2. MyBatis工作原理
3. MyBatis核心配置
mybatis-config.xml
Mapper XML示例
4. MyBatis API详解
SqlSessionFactoryBuilder
SqlSession
Mapper接口
5. MyBatis动态SQL
6. MyBatis高级特性
一对一、一对多关联
缓存机制
插件开发
第三部分:JDBC与MyBatis全面比较
1. 架构设计对比
2. 开发效率对比
3. 性能对比
4. 功能特性对比
5. 适用场景对比
6. 代码示例对比
查询操作对比
插入操作对比
第四部分:总结与选择建议
1. 技术选型考虑因素
2. 现代Java持久层发展
3. 学习路径建议
4. 最佳实践
第一部分:JDBC基础知识
1. JDBC概述
JDBC(Java Database Connectivity)是Java语言中用来规范客户端程序如何访问数据库的应用程序接口(API),它提供了一种与各种关系型数据库进行统一交互的方式。
JDBC核心组件:
-
DriverManager:管理数据库驱动程序
-
Connection:与数据库的连接
-
Statement/PreparedStatement/CallableStatement:执行SQL语句
-
ResultSet:保存查询结果集
2. JDBC工作原理
-
加载驱动程序:Class.forName("com.mysql.jdbc.Driver")
-
建立连接:DriverManager.getConnection(url, username, password)
-
创建语句对象:connection.createStatement()
-
执行SQL:statement.executeQuery()或executeUpdate()
-
处理结果集:遍历ResultSet获取数据
-
释放资源:关闭ResultSet、Statement、Connection
3. JDBC核心API详解
Connection接口
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
主要方法:
-
createStatement():创建Statement对象
-
prepareStatement():创建预编译Statement
-
prepareCall():创建存储过程调用Statement
-
setAutoCommit()/getAutoCommit():事务自动提交设置
-
commit()/rollback():事务提交/回滚
Statement接口
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
主要方法:
-
executeQuery():执行查询,返回ResultSet
-
executeUpdate():执行更新,返回影响行数
-
execute():执行任意SQL
-
addBatch()/executeBatch():批处理操作
PreparedStatement接口
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO users VALUES(?, ?, ?)");
pstmt.setInt(1, 101);
pstmt.setString(2, "John");
pstmt.setString(3, "john@example.com");
pstmt.executeUpdate();
优势:
-
预编译SQL,性能更好
-
防止SQL注入
-
代码更清晰易读
ResultSet接口
while(rs.next()) {int id = rs.getInt("id");String name = rs.getString("name");String email = rs.getString("email");
}
主要方法:
-
next():移动到下一行
-
getXXX():获取各种类型数据
-
absolute()/relative():绝对/相对定位
-
updateXXX():更新结果集
-
deleteRow():删除当前行
4. JDBC事务管理
try {conn.setAutoCommit(false); // 开始事务// 执行多个SQL操作stmt.executeUpdate("UPDATE account SET balance = balance - 500 WHERE user = 'A'");stmt.executeUpdate("UPDATE account SET balance = balance + 500 WHERE user = 'B'");conn.commit(); // 提交事务
} catch (SQLException e) {conn.rollback(); // 回滚事务
} finally {conn.setAutoCommit(true);
}
5. JDBC批处理
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO employees VALUES (?, ?, ?)");for (Employee employee : employees) {pstmt.setInt(1, employee.getId());pstmt.setString(2, employee.getName());pstmt.setDouble(3, employee.getSalary());pstmt.addBatch(); // 添加到批处理
}int[] result = pstmt.executeBatch(); // 执行批处理
6. JDBC连接池
原生JDBC每次操作都创建新连接性能低下,常用连接池:
-
Apache DBCP
-
C3P0
-
HikariCP (性能最好)
示例(HikariCP):
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("user");
config.setPassword("password");HikariDataSource ds = new HikariDataSource(config);
Connection conn = ds.getConnection();
第二部分:MyBatis基础知识
1. MyBatis概述
MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。
MyBatis核心组件:
-
SqlSessionFactory:创建SqlSession的工厂
-
SqlSession:与数据库交互的会话
-
Mapper接口:数据操作接口
-
Mapper XML:SQL映射文件
2. MyBatis工作原理
-
加载配置:读取mybatis-config.xml和Mapper XML
-
创建SqlSessionFactory
-
创建SqlSession
-
获取Mapper接口代理对象
-
执行数据库操作
-
提交事务/关闭会话
3. 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.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mydb"/><property name="username" value="user"/><property name="password" value="password"/></dataSource></environment></environments><mappers><mapper resource="com/example/mapper/UserMapper.xml"/></mappers>
</configuration>
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.example.mapper.UserMapper"><select id="getUserById" resultType="com.example.model.User">SELECT * FROM users WHERE id = #{id}</select><insert id="insertUser" parameterType="com.example.model.User">INSERT INTO users(name, email) VALUES(#{name}, #{email})</insert><update id="updateUser" parameterType="com.example.model.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>
4. MyBatis API详解
SqlSessionFactoryBuilder
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession
try (SqlSession session = sqlSessionFactory.openSession()) {UserMapper mapper = session.getMapper(UserMapper.class);User user = mapper.getUserById(1);// 其他操作...session.commit(); // 提交事务
}
主要方法:
-
getMapper():获取Mapper接口实现
-
selectOne()/selectList():执行查询
-
insert()/update()/delete():执行增删改
-
commit()/rollback():事务控制
Mapper接口
public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{id}")User getUserById(int id);@Insert("INSERT INTO users(name, email) VALUES(#{name}, #{email})")@Options(useGeneratedKeys=true, keyProperty="id")int insertUser(User user);@Update("UPDATE users SET name=#{name}, email=#{email} WHERE id=#{id}")int updateUser(User user);@Delete("DELETE FROM users WHERE id=#{id}")int deleteUser(int id);
}
5. MyBatis动态SQL
<select id="findUsers" parameterType="map" resultType="User">SELECT * FROM users<where><if test="name != null">AND name LIKE #{name}</if><if test="email != null">AND email = #{email}</if><if test="ids != null and ids.size() > 0">AND id IN<foreach item="id" collection="ids" open="(" separator="," close=")">#{id}</foreach></if></where>ORDER BY ${orderBy}
</select>
常用动态SQL标签:
-
if
-
choose/when/otherwise
-
trim/where/set
-
foreach
-
bind
6. MyBatis高级特性
一对一、一对多关联
<resultMap id="userWithOrders" type="User"><id property="id" column="user_id"/><result property="name" column="user_name"/><collection property="orders" ofType="Order"><id property="id" column="order_id"/><result property="orderNo" column="order_no"/></collection>
</resultMap><select id="getUserWithOrders" resultMap="userWithOrders">SELECT u.id as user_id, u.name as user_name,o.id as order_id, o.order_no as order_noFROM users u LEFT JOIN orders o ON u.id = o.user_idWHERE u.id = #{id}
</select>
缓存机制
-
一级缓存:SqlSession级别,默认开启
-
二级缓存:Mapper级别,需要配置开启
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
插件开发
可以拦截的方法:
-
Executor (update, query, flushStatements, commit, rollback等)
-
ParameterHandler (getParameterObject, setParameters)
-
ResultSetHandler (handleResultSets, handleOutputParameters)
-
StatementHandler (prepare, parameterize, batch, update, query)
第三部分:JDBC与MyBatis全面比较
1. 架构设计对比
特性 | JDBC | MyBatis |
---|---|---|
架构层次 | 基础API | 持久层框架 |
设计理念 | 直接数据库操作 | SQL与代码分离 |
抽象程度 | 低级别,需要处理所有细节 | 高级别,封装常见操作 |
学习曲线 | 相对简单 | 较复杂,需学习配置和映射 |
2. 开发效率对比
方面 | JDBC | MyBatis |
---|---|---|
代码量 | 需要大量样板代码 | 代码简洁,自动生成常用操作 |
SQL编写 | 硬编码在Java代码中 | 可写在XML或注解中,与Java代码分离 |
参数处理 | 需要手动设置参数 | 自动参数映射 |
结果集处理 | 需要手动遍历ResultSet并转换 | 自动结果集映射到对象 |
修改维护 | 修改SQL需要重新编译Java代码 | 修改XML无需重新编译 |
3. 性能对比
性能因素 | JDBC | MyBatis |
---|---|---|
执行效率 | 理论上最高,直接操作 | 略低,有框架开销 |
缓存支持 | 无内置缓存 | 提供一级和二级缓存 |
连接管理 | 需手动或使用第三方连接池 | 内置连接池支持 |
批处理 | 原生支持 | 支持但配置稍复杂 |
SQL预编译 | 需要手动使用PreparedStatement | 自动使用预编译语句 |
4. 功能特性对比
功能 | JDBC支持情况 | MyBatis支持情况 |
---|---|---|
动态SQL | 需手动拼接字符串 | 提供强大动态SQL支持 |
关联查询 | 需手动处理结果集 | 支持复杂对象关联映射 |
事务管理 | 基本事务控制 | 更灵活的事务管理 |
插件扩展 | 无 | 支持插件扩展 |
多数据库支持 | 依赖不同驱动 | 通过方言支持 |
存储过程 | 支持 | 支持 |
5. 适用场景对比
JDBC更适合:
-
需要极致性能的简单应用
-
学习数据库操作原理
-
需要完全控制SQL执行的场景
-
小型项目或原型开发
-
需要与特定数据库特性深度集成
MyBatis更适合:
-
中大型企业级应用
-
需要快速开发的团队
-
SQL需要频繁调整的项目
-
复杂对象关系映射场景
-
需要良好维护性的长期项目
6. 代码示例对比
查询操作对比
JDBC实现查询:
public User getUserById(int id) throws SQLException {Connection conn = null;PreparedStatement pstmt = null;ResultSet rs = null;User user = null;try {conn = dataSource.getConnection();pstmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?");pstmt.setInt(1, id);rs = pstmt.executeQuery();if (rs.next()) {user = new User();user.setId(rs.getInt("id"));user.setName(rs.getString("name"));user.setEmail(rs.getString("email"));}} finally {if (rs != null) rs.close();if (pstmt != null) pstmt.close();if (conn != null) conn.close();}return user;
}
MyBatis实现相同查询:
Mapper接口:
public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{id}")User getUserById(int id);
}
或XML配置:
<select id="getUserById" resultType="com.example.User">SELECT * FROM users WHERE id = #{id}
</select>
运行 HTML
使用代码:
try (SqlSession session = sqlSessionFactory.openSession()) {UserMapper mapper = session.getMapper(UserMapper.class);User user = mapper.getUserById(1);
}
插入操作对比
JDBC实现插入:
public int insertUser(User user) throws SQLException {Connection conn = null;PreparedStatement pstmt = null;int affectedRows = 0;try {conn = dataSource.getConnection();pstmt = conn.prepareStatement("INSERT INTO users(name, email) VALUES(?, ?)");pstmt.setString(1, user.getName());pstmt.setString(2, user.getEmail());affectedRows = pstmt.executeUpdate();} finally {if (pstmt != null) pstmt.close();if (conn != null) conn.close();}return affectedRows;
}
MyBatis实现相同插入:
Mapper接口:
@Insert("INSERT INTO users(name, email) VALUES(#{name}, #{email})")
@Options(useGeneratedKeys=true, keyProperty="id")
int insertUser(User user);
或XML配置:
<insert id="insertUser" parameterType="com.example.User" useGeneratedKeys="true" keyProperty="id">INSERT INTO users(name, email) VALUES(#{name}, #{email})
</insert>
使用代码:
User user = new User();
user.setName("John");
user.setEmail("john@example.com");try (SqlSession session = sqlSessionFactory.openSession()) {UserMapper mapper = session.getMapper(UserMapper.class);int affectedRows = mapper.insertUser(user);session.commit();System.out.println("Generated ID: " + user.getId());
}
第四部分:总结与选择建议
1. 技术选型考虑因素
-
项目规模:小型项目可用JDBC,中大型建议MyBatis
-
团队技能:熟悉SQL的团队适合MyBatis,新手可从JDBC学起
-
性能需求:极高性能要求考虑JDBC,一般场景MyBatis足够
-
维护需求:长期维护项目MyBatis更合适
-
灵活性:需要复杂SQL和动态查询优先MyBatis
2. 现代Java持久层发展
虽然MyBatis比JDBC先进,但现在还有更多选择:
-
JPA/Hibernate:全自动ORM框架
-
Spring Data JPA:基于JPA的更高抽象
-
JOOQ:类型安全的SQL构建
-
QueryDSL:流畅API查询
3. 学习路径建议
-
先掌握JDBC理解底层原理
-
学习MyBatis掌握半自动化ORM
-
根据需要学习JPA/Hibernate等全自动ORM
-
了解Spring Data等更高抽象
4. 最佳实践
JDBC最佳实践:
-
始终使用PreparedStatement防止SQL注入
-
使用try-with-resources确保资源释放
-
实现连接池提高性能
-
将数据库操作封装到DAO层
MyBatis最佳实践:
-
合理设计resultMap处理复杂映射
-
使用动态SQL提高灵活性
-
合理配置缓存提升性能
-
将SQL集中管理便于维护
-
使用Mapper接口而非直接SqlSession操作
无论选择JDBC还是MyBatis,良好的数据库设计和规范的编码实践都是保证系统性能和维护性的关键。