当前位置: 首页 > news >正文

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工作原理

  1. 加载驱动程序:Class.forName("com.mysql.jdbc.Driver")

  2. 建立连接:DriverManager.getConnection(url, username, password)

  3. 创建语句对象:connection.createStatement()

  4. 执行SQL:statement.executeQuery()或executeUpdate()

  5. 处理结果集:遍历ResultSet获取数据

  6. 释放资源:关闭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工作原理

  1. 加载配置:读取mybatis-config.xml和Mapper XML

  2. 创建SqlSessionFactory

  3. 创建SqlSession

  4. 获取Mapper接口代理对象

  5. 执行数据库操作

  6. 提交事务/关闭会话

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. 架构设计对比

特性JDBCMyBatis
架构层次基础API持久层框架
设计理念直接数据库操作SQL与代码分离
抽象程度低级别,需要处理所有细节高级别,封装常见操作
学习曲线相对简单较复杂,需学习配置和映射

2. 开发效率对比

方面JDBCMyBatis
代码量需要大量样板代码代码简洁,自动生成常用操作
SQL编写硬编码在Java代码中可写在XML或注解中,与Java代码分离
参数处理需要手动设置参数自动参数映射
结果集处理需要手动遍历ResultSet并转换自动结果集映射到对象
修改维护修改SQL需要重新编译Java代码修改XML无需重新编译

3. 性能对比

性能因素JDBCMyBatis
执行效率理论上最高,直接操作略低,有框架开销
缓存支持无内置缓存提供一级和二级缓存
连接管理需手动或使用第三方连接池内置连接池支持
批处理原生支持支持但配置稍复杂
SQL预编译需要手动使用PreparedStatement自动使用预编译语句

4. 功能特性对比

功能JDBC支持情况MyBatis支持情况
动态SQL需手动拼接字符串提供强大动态SQL支持
关联查询需手动处理结果集支持复杂对象关联映射
事务管理基本事务控制更灵活的事务管理
插件扩展支持插件扩展
多数据库支持依赖不同驱动通过方言支持
存储过程支持支持

5. 适用场景对比

JDBC更适合:

  1. 需要极致性能的简单应用

  2. 学习数据库操作原理

  3. 需要完全控制SQL执行的场景

  4. 小型项目或原型开发

  5. 需要与特定数据库特性深度集成

MyBatis更适合:

  1. 中大型企业级应用

  2. 需要快速开发的团队

  3. SQL需要频繁调整的项目

  4. 复杂对象关系映射场景

  5. 需要良好维护性的长期项目

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. 技术选型考虑因素

  1. 项目规模:小型项目可用JDBC,中大型建议MyBatis

  2. 团队技能:熟悉SQL的团队适合MyBatis,新手可从JDBC学起

  3. 性能需求:极高性能要求考虑JDBC,一般场景MyBatis足够

  4. 维护需求:长期维护项目MyBatis更合适

  5. 灵活性:需要复杂SQL和动态查询优先MyBatis

2. 现代Java持久层发展

虽然MyBatis比JDBC先进,但现在还有更多选择:

  • JPA/Hibernate:全自动ORM框架

  • Spring Data JPA:基于JPA的更高抽象

  • JOOQ:类型安全的SQL构建

  • QueryDSL:流畅API查询

3. 学习路径建议

  1. 先掌握JDBC理解底层原理

  2. 学习MyBatis掌握半自动化ORM

  3. 根据需要学习JPA/Hibernate等全自动ORM

  4. 了解Spring Data等更高抽象

4. 最佳实践

JDBC最佳实践:

  • 始终使用PreparedStatement防止SQL注入

  • 使用try-with-resources确保资源释放

  • 实现连接池提高性能

  • 将数据库操作封装到DAO层

MyBatis最佳实践:

  • 合理设计resultMap处理复杂映射

  • 使用动态SQL提高灵活性

  • 合理配置缓存提升性能

  • 将SQL集中管理便于维护

  • 使用Mapper接口而非直接SqlSession操作

无论选择JDBC还是MyBatis,良好的数据库设计和规范的编码实践都是保证系统性能和维护性的关键。

相关文章:

  • 如何优雅的关闭线程池
  • 深度学习常见模块实现001
  • 为什么 Transformer 要使用多头注意力机制?
  • Log4j2远程命令执行(CVE-2021-44228)复现
  • 智能 GitHub Copilot 副驾驶® 更新升级!
  • Spring JDBC 与数据访问:从性能优化到事务协同
  • 如何实现一个构造函数继承另一个构造函数的属性和方法?给出ES5和ES6两种方式
  • 软件研发过程中的技术债
  • (Matlab)自动驾驶仿真 设计驾驶场景、配置传感器并生成合成 数据
  • #Liunx内存管理# 页面分配器是按照什么方向来扫描zone的?
  • 第一期第10讲
  • ShellScript脚本编程
  • C语言 - 深拷贝与浅拷贝详解
  • 【扩散模型连载 · 第 2 期】逆向扩散建模与神经网络的角色
  • Object.create(null)`和`{}`创建的对象有什么区别?
  • git提交规范
  • Linux的应用领域,测试与Linux,Linux的介绍,VirtualBox和Ubuntu的安装,VMware的安装和打开虚拟机CentOS
  • 密码学(二)流密码
  • Delphi HMAC算法
  • Spring常用注解
  • 加建网网站/关键词优化推广公司排名
  • 如何做网站产品图片/西安专业网络推广平台
  • html5 可以做网站吗/分销系统
  • 官网网站建设公司/谷歌seo网站优化
  • wordpress插件分类/谷歌seo搜索引擎下载
  • 学做烤制食品的网站/网络营销方案案例