MyBatis基础教程:一个老广程序员的持久层上岸路

程序员阿远
2025-12-14 14:44
阅读 696

去年十月的一个深夜,我坐在越秀区老东山那间月租3500的小单间里,窗外是熟悉的骑楼和昏黄的路灯。桌上泡着一壶凉了的普洱,键盘旁边堆着几本翻烂了的《Java编程思想》和《Spring Boot实战》。屏幕上的IDEA还在报错,红得刺眼——“Invalid bound statement (not found): com.example.mapper.UserMapper.selectById”。

那一刻,我差点把键盘砸了。

不是因为技术多难,而是因为明天就要交项目初稿,而我这个“资深”程序员居然连MyBatis的基本配置都没搞明白。更扎心的是,再过三个月,我就要参加广州市考了。白天在公司写业务代码,晚上啃行测申论,周末还得抽空学框架——我感觉自己快被撕成两半了。

从“增删改查”到“增删改查+考公”

我是土生土长的老广,大学读的是华工计算机,毕业后进了天河一家中型互联网公司做后端开发,月薪15k,不算高,但在广州老城区生活,勉强够用。去年年初,老婆(对,我已经结婚了)看着我天天加班到十点,黑眼圈比荔枝湾的水还深,突然说:“不如试试考公吧?稳定点。”

我一开始嗤之以鼻:“程序员不就是吃青春饭?考公?我都30了!”

但她一句话戳中我:“你每天写的那些CRUD,十年后还是CRUD。但公务员,十年后可能还在喝茶看报,至少不会被优化。”

那天晚上我没睡着。打开招聘网站,看到某市直单位招信息化岗,要求“熟悉Java、Spring Boot、MyBatis”,薪资虽然只有现在的一半(税后大概8k),但公积金双边4000,还有食堂、宿舍、年假……最关键的是——不用半夜被报警电话吵醒

我动心了。

于是,一边准备笔试,一边开始恶补岗位要求的技术栈。而MyBatis,就是横在我面前的第一座山。

初识MyBatis:原来ORM没那么可怕

说实话,以前在公司用的都是JPA或者公司自研ORM,MyBatis只是听说过。我以为它很复杂,结果上手才发现:这不就是SQL的“美化器”吗?

上周五晚上,我决定从零搭个Demo。打开IDEA,新建一个Spring Boot项目(2.7.5版本),引入依赖:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

然后在application.yml里配数据源:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.entity

接着建个User实体类:

public class User {
    private Long id;
    private String name;
    private Integer age;
    // getter/setter省略
}

再写个Mapper接口:

@Mapper
public interface UserMapper {
    User selectById(Long id);
    List<User> selectAll();
    int insert(User user);
    int update(User user);
    int delete(Long id);
}

到这里,一切都很顺利。问题出在XML映射文件。

我把UserMapper.xml放在resources/mapper/下,内容如下:

<?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="selectById" resultType="User">
        SELECT * FROM user WHERE id = #{id}
    </select>
</mapper>

结果一跑,就报那个经典的错误:“Invalid bound statement”。

我当时真的懵了。反复检查namespace、方法名、XML路径……都对啊!直到凌晨两点,我才想起来——Spring Boot默认不会扫描resources下的XML文件

解决办法?在启动类加个注解:

@MapperScan("com.example.mapper")
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

或者在pom.xml里加resource过滤:

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
</build>

搞定那一刻,我长舒一口气,赶紧截图发给老婆:“搞定了!MyBatis其实不难!”

她回我:“你上次说‘LeetCode简单题’也不难,结果刷了三天。”

我……无言以对。

案例驱动:用MyBatis写一个“考公报名系统”原型

为了加深理解,我决定用MyBatis做个微型“考公报名系统”。功能很简单:用户注册、查看岗位、提交报名。

第一步:建表

CREATE TABLE candidate (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    id_card VARCHAR(18) UNIQUE,
    phone VARCHAR(11),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE post (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(100),
    department VARCHAR(100),
    quota INT,
    min_score DECIMAL(5,2)
);

第二步:写Mapper

比如CandidateMapper:

@Mapper
public interface CandidateMapper {
    @Select("SELECT * FROM candidate WHERE id_card = #{idCard}")
    Candidate findByCard(String idCard);

    @Insert("INSERT INTO candidate(name, id_card, phone) VALUES(#{name}, #{idCard}, #{phone})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insert(Candidate candidate);
}

看到了吗?MyBatis支持两种方式:XML映射 or 注解。对于简单SQL,用注解更清爽;复杂查询(比如多表联查、动态条件),还是XML更灵活。

比如岗位查询,可能要根据部门、最低分筛选,这时候就得用<if>标签:

<select id="searchPosts" resultType="Post">
    SELECT * FROM post
    <where>
        <if test="department != null and department != ''">
            AND department LIKE CONCAT('%', #{department}, '%')
        </if>
        <if test="minScore != null">
            AND min_score &lt;= #{minScore}
        </if>
    </where>
</select>

注意那个&lt;——这是XML转义,写的时候容易漏,调试时又找不到原因,气死个人。

第三步:Service层调用

@Service
public class CandidateService {
    
    @Autowired
    private CandidateMapper candidateMapper;
    
    public boolean register(String name, String idCard, String phone) {
        // 先查是否已存在
        if (candidateMapper.findByCard(idCard) != null) {
            return false; // 身份证已注册
        }
        Candidate c = new Candidate();
        c.setName(name);
        c.setIdCard(idCard);
        c.setPhone(phone);
        return candidateMapper.insert(c) > 0;
    }
}

整个流程跑通后,我在Postman里测试,成功插入了一条“张三,4401041990xxxxxx,138****1234”的数据。那一刻,我居然有点小激动——这不就是未来我要维护的政务系统吗?

那些踩过的坑,都是上岸的垫脚石

学MyBatis的过程中,我踩了不少坑,也总结了些经验:

  1. 命名空间必须全限定类名namespace="com.example.mapper.UserMapper",少一个字母都不行。
  2. 驼峰转换要开启:数据库字段是user_name,Java属性是userName,记得在配置里加:
    mybatis:
      configuration:
        map-underscore-to-camel-case: true
    
  3. 事务别忘了:涉及多个操作(比如报名+扣费),记得在Service方法上加@Transactional
  4. 日志很重要:开发时打开SQL日志,一眼看出执行了什么:
    logging:
      level:
        com.example.mapper: debug
    

最让我感慨的是:MyBatis的本质,其实是“让Java程序员安心写SQL”。它不像Hibernate那样试图完全屏蔽SQL,而是承认SQL的价值,只是帮你把参数绑定、结果映射这些脏活自动化了。

这特别适合政务系统——很多老系统迁移,SQL逻辑复杂,直接重写成本太高,用MyBatis就能平滑过渡。

考公or码农?我的选择

昨天,我收到了广州市某局信息化岗的面试通知。笔试成绩第3,岗位招2人。老婆比我激动,说:“终于不用天天debug到凌晨了!”

但我心里清楚,考公不是逃避,而是另一种责任。政务系统关乎民生,一个bug可能导致几百人无法办理业务。这比电商少卖几单严重得多。

而MyBatis,作为国内政务、金融系统最常用的ORM框架,掌握它,不仅是应付考试,更是为未来的工作打基础。

我现在每天依然写代码,但心态变了。以前是为了KPI,现在是为了“能用技术让老百姓办事更方便一点”。哪怕只是优化一个查询速度,减少用户等待时间,也觉得有意义。

写给同样在路上的你

如果你也在准备考公,又担心技术荒废,我的建议是:

  • 聚焦岗位要求:别盲目学微服务、分布式,先把Java、Spring Boot、MyBatis这“铁三角”吃透。
  • 用项目驱动学习:像我这样,做个“考公报名系统”、“社保查询Demo”,比刷100道题更有效。
  • 接受自己的焦虑:我经常怀疑自己是不是太晚了,但转念一想——30岁考公的人多了去了,有人上岸,有人二战,重要的是别停下。

最后分享个小故事:上周我去陈家祠附近喝早茶,邻桌两个阿伯聊天。一个说:“现在年轻人真辛苦,又要写代码,又要考试。”另一个笑:“但人家有技术傍身,考不上还能回去打工,我们当年可没这退路。”

我低头喝了口虾饺皇,心里暖暖的。

技术人的路,从来不止一条。MyBatis可以连接数据库,也可以连接理想与现实。只要手不抖,心不慌,总能找到属于自己的那条SQL语句——精准、高效、不报错。

共勉。


后记:本文所有代码均在我本地环境验证通过(MySQL 8.0 + Spring Boot 2.7.5 + MyBatis 2.3.0)。如果你也在广州备考,欢迎留言交流。对了,我老婆说,要是上岸了,请大家饮茶——就在北京路那家老字号,人均50,管饱。

评论 0

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