MyBatis基础教程:Java持久层框架入门

数据库守门员
2025-12-17 23:02
阅读 785

上周五晚上十点半,我正躺在沙发上用MacBook Pro敲代码,窗外下着小雨,咖啡已经凉了。这时候产品经理突然在群里@我:“双11运营活动明天要上线,用户积分查询接口得加个条件过滤,能搞定吗?”

我嘴角一抽——这需求上周才改过三轮,现在又要动数据库逻辑。但没办法,谁叫我们是远程办公的“福报打工人”呢?不过好在我早就把项目从JDBC手写SQL迁到了MyBatis,不然今晚又得通宵。

其实说起来有点惭愧:作为一个Cursor重度用户,我已经离不开AI写代码了。每天打开IDE,第一件事就是Cmd+K唤出Cursor,让它帮我生成Mapper XML或者调试SQL。以前自己手写DAO层的时候,光是ResultSet取字段就能写到怀疑人生。现在?一句提示词的事儿。

为什么选MyBatis而不是JPA?

很多团队喜欢用Spring Data JPA,尤其是那些从Python转过来的同事(别问,问就是综合技术栈)。JPA确实香,注解一打,CRUD自动生成,看起来非常“现代化”。但问题来了:

  • 复杂查询写起来像在拼乐高,性能调优全靠玄学
  • SQL对DBA不透明,线上慢查询根本没法快速定位
  • 动态条件拼接?那叫HQL地狱

而MyBatis不一样。它不替你写SQL,而是让你掌控SQL。作为喜欢研究底层原理的老码农,我宁愿多写几行XML,也不想被ORM框架“过度封装”。

有一次线上OOM,查了半天发现是JPA的N+1查询惹的祸。换成MyBatis后,SQL一目了然,连运维大哥都说:“你们这SQL格式化得比我的shell脚本还整齐。”

五分钟上手MyBatis核心三件套

MyBatis的核心就三样东西:SqlSessionFactoryMapper接口XML映射文件。听起来很抽象?我给你拆解成人类语言:

  1. SqlSessionFactory:数据库连接池的“包工头”,负责开工(创建SqlSession)
  2. Mapper接口:你写的Java接口,比如UserMapper
  3. XML文件:SQL语句的“老家”,所有增删改查都藏在这里

先看配置(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/ops_db"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
      </dataSource>
    </environment>
  </environments>
  
  <!-- 告诉MyBatis去哪里找你的Mapper XML -->
  <mappers>
    <mapper resource="mappers/UserMapper.xml"/>
  </mappers>
</configuration>

接着写Mapper接口:

public interface UserMapper {
    List<User> selectUsersByStatus(@Param("status") String status);
}

最后是XML(mappers/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="com.example.mapper.UserMapper">
  <select id="selectUsersByStatus" resultType="com.example.model.User">
    SELECT user_id, username, points 
    FROM users 
    WHERE status = #{status}
  </select>
</mapper>

看到没?SQL明明白白写在XML里,运维查日志、DBA优化索引都方便。这才是可维护性

动态SQL:让运营需求不再可怕

回到开头那个双11需求。产品经理要加“按积分范围+状态+注册时间”筛选,典型的动态查询。MyBatis的<where><if>标签简直就是救星:

<select id="searchUsers" resultType="User">
  SELECT user_id, username, points, create_time
  FROM users
  <where>
    <if test="minPoints != null">
      AND points >= #{minPoints}
    </if>
    <if test="maxPoints != null">
      AND points &lt;= #{maxPoints}
    </if>
    <if test="status != null and status != ''">
      AND status = #{status}
    </if>
    <if test="startTime != null">
      AND create_time >= #{startTime}
    </if>
  </where>
  ORDER BY create_time DESC
</select>

注意:<where>会自动处理AND/OR的前缀,避免SQL语法错误。以前用JDBC手拼字符串,漏个空格就得debug半小时。现在?Cursor直接帮我生成模板,我只管填业务逻辑。

性能陷阱:别让MyBatis变成“慢Batis”

虽然MyBatis灵活,但用不好照样翻车。去年双11我们就踩过坑:

事故现场:运营后台导出百万级用户数据,直接把DB连接池打满。
根因:Mapper里写了SELECT *,而且没分页!
解决方案

  1. 永远不要SELECT *:明确指定字段,减少网络IO
  2. 大查询必须分页:用RowBounds或物理分页插件
  3. 开启二级缓存要谨慎:我们关掉了,因为数据实时性要求高

附上我们生产环境的调优参数对比:

配置项 开发环境 生产环境 说明
defaultFetchSize 100 1000 控制ResultSet一次拉取的行数
mapUnderscoreToCamelCase true true 数据库下划线字段自动转驼峰
cacheEnabled true false 生产关闭二级缓存
logImpl STDOUT_LOGGING SLF4J 日志对接公司ELK

Python党别走!MyBatis和你的世界也能联动

我知道读者里有不少Python选手(毕竟现在全栈工程师都得会点Python做数据分析)。虽然MyBatis是Java的,但思想可以复用:

  • SQL与逻辑分离:Python里可以用SQLAlchemy Core,把SQL写在单独文件
  • 动态查询构建:用sqlglot或原生f-string(小心SQL注入!)
  • 运维脚本集成:我们用Python脚本定期分析MyBatis日志,找出慢SQL

举个例子,我写了个Python小工具,扫描所有Mapper XML,统计高频表和字段,反哺给DBA做索引优化。这叫综合效能提升

最后一点碎碎念

说实话,学MyBatis真不是为了炫技。是因为被现实毒打过——手写JDBC的时代,一个字段类型改错,测试能提20个bug。现在用MyBatis + Cursor,开发效率飞起,连产品经理都说:“你这需求响应速度,比我点外卖还快。”

当然,MyBatis只是工具。真正重要的是理解数据流向:从HTTP请求 → Service → Mapper → DB → 返回结果。每一层都要有监控、有兜底、有日志。毕竟线上事故不分语言,Java崩了和Python崩了,老板骂人是一样的凶。

如果你也在被运营需求折磨,不妨试试MyBatis。至少下次凌晨三点改SQL的时候,你能优雅地喝口咖啡,而不是砸键盘。

(完)


作者:某大厂远程办公Java工程师,Cursor骨灰级用户,坚信“能用AI解决的问题都不是问题”。最近在研究MyBatis源码中的Executor设计,欢迎交流~

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝