学 Java 持久层的时候我先写了一个纯 JDBC 的小项目。写完之后只有一个感受太累了。后来换了 MyBatis 重写一遍同样的功能代码量直接砍了一半多。这篇就记一下 MyBatis 到底比 JDBC 好在哪都是我自己踩过的坑。一、JDBC 那些重复代码真的写到烦先说说 JDBC 写起来有多啰嗦。一个简单的查询用户功能你得干这些事加载数据库驱动获取连接创建 PreparedStatement手动给占位符设参数执行查询遍历 ResultSet一行一行取数据把数据塞到 Java 对象里关闭 ResultSet、Statement、Connection中间任何一步出错了还得处理异常这里面有一半以上的代码跟业务逻辑没有任何关系。你只是想查一个用户的信息结果写了几十行样板代码。而且每次查询都要写一遍复制粘贴改改就完事。我第一个 JDBC 项目光是关闭资源的try-catch-finally就写了不知道多少遍。后来才知道这种重复代码有个说法叫模板代码。MyBatis 把这些事全包了你只管写 SQL连接怎么开、怎么关、结果集怎么遍历它来处理。二、SQL 写在 Java 代码里看着就头疼JDBC 还有一个让我难受的地方SQL 是字符串硬编码在 Java 代码里。比如一个带条件的查询StringsqlSELECT id, username, email FROM user WHERE username ? AND status ?;简单查询还行一旦 SQL 复杂起来十几个条件、好几个 JOIN字符串拼起来又长又难看。而且你想改一下 SQL得改 Java 代码改完还得重新编译打包。MyBatis 把 SQL 抽出来放到 XML 文件里也可以用注解但复杂 SQL 还是 XML 看着清楚。Java 代码里只写一个接口方法SQL 写在对应的 XML 文件里。两边各管各的互不干扰。这样做的好处是改 SQL 不用动 Java 代码DBA 想审查你的 SQL 也方便直接看 XML 文件就行。我后来在团队项目里见过有人直接在 Java 里写几百行的 SQL 字符串说实话看的时候真的很崩溃。三、动态 SQL这个我最开始搞不明白实际开发里查询条件经常是不固定的。比如一个搜索页面用户可以填用户名也可以不填可以选状态也可以不选。SQL 里的 WHERE 条件要根据传进来的参数动态生成。用 JDBC 的话你得在 Java 代码里拼字符串。大概就是这样的逻辑StringsqlSELECT * FROM user WHERE 11;if(username!null){sql AND username ?;}if(status!null){sql AND status ?;}WHERE 11这种写法我以前以为是什么黑魔法后来才明白就是为了拼字符串方便。但这种方式很容易出错少一个空格、多一个 ANDSQL 就挂了而且报的错还不好排查。MyBatis 提供了一套 XML 标签来处理动态 SQLif条件满足就拼上这段choose/when/otherwise相当于 if-elsewhere自动处理 WHERE 后面多余的 AND 或 ORforeach批量处理比如 IN 查询写出来大概是这样selectidfindUsersresultTypeUserSELECT * FROM userwhereiftestusername ! nullAND username #{username}/ififteststatus ! nullAND status #{status}/if/where/select第一次看这段 XML 的时候觉得有点怪用了两天就习惯了。比起在 Java 里拼字符串这个写起来清楚太多了而且不用担心WHERE 11那种问题where标签会自动处理。还有一个sql标签可以定义 SQL 片段其他地方直接include引用省得同一段 SQL 到处复制。四、结果集映射终于不用一行一行 set 了JDBC 查完数据之后你要自己遍历 ResultSet一行一行取字段然后手动 set 到 Java 对象里while(rs.next()){UserusernewUser();user.setId(rs.getInt(id));user.setUsername(rs.getString(username));user.setEmail(rs.getString(email));// ... 还有很多字段}字段少的时候还好字段多了就是一场噩梦。而且一旦数据库表加了字段Java 这边也得跟着改很容易漏掉。MyBatis 可以自动把查询结果映射到 Java 对象上。简单的情况字段名和属性名一样它直接就映射了什么都不用配。复杂一点的情况用resultMap标签定义一下映射关系就行。resultMapiduserResultMaptypeUseridpropertyidcolumnid/resultpropertyusernamecolumnuser_name/resultpropertyemailcolumnemail//resultMap数据库字段叫user_nameJava 属性叫username在 resultMap 里对应一下就行了。如果是一对多关系比如一个用户有多条订单MyBatis 也有对应的标签可以处理不用自己写循环去组装。我第一次用的时候觉得这也太方便了JDBC 里这种事要写一堆代码。五、换数据库基本不用改代码MyBatis 底层还是用 JDBC 连数据库的所以 JDBC 支持的数据库它都支持。MySQL、Oracle、PostgreSQL换个数据库驱动、改一下连接配置基本就能跑。这一点在我刚学的时候感受不深因为一直用 MySQL。后来有个项目要从 MySQL 迁移到 PostgreSQL除了个别 SQL 语法不一样比如分页的写法MyBatis 的配置和 Java 代码完全不用动。如果用的是 JDBC改动量会大很多。另外 MyBatis 跟 Spring 的集成也很顺滑。Spring 帮你管数据源、管事务MyBatis 帮你管 SQL 和映射各干各的活。实际项目里基本都是这么搭配的配一次之后就不用再操心了。最后说了这么多其实 MyBatis 解决的核心问题就一个让你不用把时间浪费在 JDBC 那些重复的样板代码上。连接管理它帮你做了结果集映射它帮你做了动态 SQL 它给你一套标签SQL 和代码分离它给你 XML 文件。你剩下的事情就是两样写 SQL写业务逻辑。如果你是新手建议先老老实实用 JDBC 写一个小项目把那些痛苦都体验一遍。然后再切到 MyBatis你会知道它到底帮你省了多少事。没经历过 JDBC 的苦就很难理解 MyBatis 的好。
为什么大家都用 MyBatis,我写完第一个 JDBC 项目之后懂了
发布时间:2026/6/22 23:50:47
学 Java 持久层的时候我先写了一个纯 JDBC 的小项目。写完之后只有一个感受太累了。后来换了 MyBatis 重写一遍同样的功能代码量直接砍了一半多。这篇就记一下 MyBatis 到底比 JDBC 好在哪都是我自己踩过的坑。一、JDBC 那些重复代码真的写到烦先说说 JDBC 写起来有多啰嗦。一个简单的查询用户功能你得干这些事加载数据库驱动获取连接创建 PreparedStatement手动给占位符设参数执行查询遍历 ResultSet一行一行取数据把数据塞到 Java 对象里关闭 ResultSet、Statement、Connection中间任何一步出错了还得处理异常这里面有一半以上的代码跟业务逻辑没有任何关系。你只是想查一个用户的信息结果写了几十行样板代码。而且每次查询都要写一遍复制粘贴改改就完事。我第一个 JDBC 项目光是关闭资源的try-catch-finally就写了不知道多少遍。后来才知道这种重复代码有个说法叫模板代码。MyBatis 把这些事全包了你只管写 SQL连接怎么开、怎么关、结果集怎么遍历它来处理。二、SQL 写在 Java 代码里看着就头疼JDBC 还有一个让我难受的地方SQL 是字符串硬编码在 Java 代码里。比如一个带条件的查询StringsqlSELECT id, username, email FROM user WHERE username ? AND status ?;简单查询还行一旦 SQL 复杂起来十几个条件、好几个 JOIN字符串拼起来又长又难看。而且你想改一下 SQL得改 Java 代码改完还得重新编译打包。MyBatis 把 SQL 抽出来放到 XML 文件里也可以用注解但复杂 SQL 还是 XML 看着清楚。Java 代码里只写一个接口方法SQL 写在对应的 XML 文件里。两边各管各的互不干扰。这样做的好处是改 SQL 不用动 Java 代码DBA 想审查你的 SQL 也方便直接看 XML 文件就行。我后来在团队项目里见过有人直接在 Java 里写几百行的 SQL 字符串说实话看的时候真的很崩溃。三、动态 SQL这个我最开始搞不明白实际开发里查询条件经常是不固定的。比如一个搜索页面用户可以填用户名也可以不填可以选状态也可以不选。SQL 里的 WHERE 条件要根据传进来的参数动态生成。用 JDBC 的话你得在 Java 代码里拼字符串。大概就是这样的逻辑StringsqlSELECT * FROM user WHERE 11;if(username!null){sql AND username ?;}if(status!null){sql AND status ?;}WHERE 11这种写法我以前以为是什么黑魔法后来才明白就是为了拼字符串方便。但这种方式很容易出错少一个空格、多一个 ANDSQL 就挂了而且报的错还不好排查。MyBatis 提供了一套 XML 标签来处理动态 SQLif条件满足就拼上这段choose/when/otherwise相当于 if-elsewhere自动处理 WHERE 后面多余的 AND 或 ORforeach批量处理比如 IN 查询写出来大概是这样selectidfindUsersresultTypeUserSELECT * FROM userwhereiftestusername ! nullAND username #{username}/ififteststatus ! nullAND status #{status}/if/where/select第一次看这段 XML 的时候觉得有点怪用了两天就习惯了。比起在 Java 里拼字符串这个写起来清楚太多了而且不用担心WHERE 11那种问题where标签会自动处理。还有一个sql标签可以定义 SQL 片段其他地方直接include引用省得同一段 SQL 到处复制。四、结果集映射终于不用一行一行 set 了JDBC 查完数据之后你要自己遍历 ResultSet一行一行取字段然后手动 set 到 Java 对象里while(rs.next()){UserusernewUser();user.setId(rs.getInt(id));user.setUsername(rs.getString(username));user.setEmail(rs.getString(email));// ... 还有很多字段}字段少的时候还好字段多了就是一场噩梦。而且一旦数据库表加了字段Java 这边也得跟着改很容易漏掉。MyBatis 可以自动把查询结果映射到 Java 对象上。简单的情况字段名和属性名一样它直接就映射了什么都不用配。复杂一点的情况用resultMap标签定义一下映射关系就行。resultMapiduserResultMaptypeUseridpropertyidcolumnid/resultpropertyusernamecolumnuser_name/resultpropertyemailcolumnemail//resultMap数据库字段叫user_nameJava 属性叫username在 resultMap 里对应一下就行了。如果是一对多关系比如一个用户有多条订单MyBatis 也有对应的标签可以处理不用自己写循环去组装。我第一次用的时候觉得这也太方便了JDBC 里这种事要写一堆代码。五、换数据库基本不用改代码MyBatis 底层还是用 JDBC 连数据库的所以 JDBC 支持的数据库它都支持。MySQL、Oracle、PostgreSQL换个数据库驱动、改一下连接配置基本就能跑。这一点在我刚学的时候感受不深因为一直用 MySQL。后来有个项目要从 MySQL 迁移到 PostgreSQL除了个别 SQL 语法不一样比如分页的写法MyBatis 的配置和 Java 代码完全不用动。如果用的是 JDBC改动量会大很多。另外 MyBatis 跟 Spring 的集成也很顺滑。Spring 帮你管数据源、管事务MyBatis 帮你管 SQL 和映射各干各的活。实际项目里基本都是这么搭配的配一次之后就不用再操心了。最后说了这么多其实 MyBatis 解决的核心问题就一个让你不用把时间浪费在 JDBC 那些重复的样板代码上。连接管理它帮你做了结果集映射它帮你做了动态 SQL 它给你一套标签SQL 和代码分离它给你 XML 文件。你剩下的事情就是两样写 SQL写业务逻辑。如果你是新手建议先老老实实用 JDBC 写一个小项目把那些痛苦都体验一遍。然后再切到 MyBatis你会知道它到底帮你省了多少事。没经历过 JDBC 的苦就很难理解 MyBatis 的好。