被问“为什么你们项目不用 JPA 用 MyBatis?”我这样回答拿下了 offer!

哈喽各位码友,欢迎来到我的“小米说面试”系列!

今天我们来聊一个Java社招面试中出镜率极高的常客——MyBatis

说真的,前不久我跳槽去面字节的时候,面试官问我的第一个问题就是:

“你们项目里用的ORM框架是什么?为什么不用JPA,用MyBatis?”

我当时心里一咯噔,MyBatis这哥们我明明用得六熟,突然被问到这个“哲学层面”的问题,居然卡了一下……(尴尬脸.jpg)

后来我总结了一下,如果面试时你对 MyBatis 的理解还停留在“它是个持久层框架,可以写SQL映射Java对象”这种表面回答,很容易被一波追问带走。

所以今天就让我这个老码农小米,给你讲讲我和MyBatis的故事,从是什么为什么用,再到怎么用好,希望你下次面试不再“背刺”。

从前有个项目,叫“CRUD地狱”

时间拉回几年前,我还是某大厂外包团队的一名搬砖选手。

那时候我们在做一个政务系统,说白了就是典型的CRUD应用,模块多、字段多、表也多得离谱,一张表五十多个字段见怪不怪。

我们的项目最早用的是原生JDBC + DAO 手撸 SQL 的方式,每次写个插入或者查询,像这样:

哇,当时真的是,写代码像在写诗,每句

<think>我们将在Spring Boot项目中集成MyBatis替代JPA,主要步骤包括:添加依赖、配置数据源、创建实体类、Mapper接口和XML映射文件、Service层、Controller层,以及配置MyBatis。 注意:由于之前使用了JPA,现在要替换为MyBatis,需要移除JPA相关依赖,并添加MyBatis依赖。 步骤详细说明如下: 1. 添加MyBatis和MySQL驱动依赖 在pom.xml中,移除Spring Data JPA依赖(如果存在),添加MyBatis Spring Boot Starter和MySQL驱动依赖。 2. 配置数据源和MyBatis 在application.properties(或application.yml)中配置数据源和MyBatis相关属性,如Mapper XML文件的位置、实体类包等。 3. 创建实体类 创建与数据库表对应的实体类(POJO),例如Teacher类。 4. 创建Mapper接口和XML映射文件 创建Mapper接口,定义数据库操作方法,并在XML文件中编写SQL语句。 5. 创建Service层 创建Service接口及其实现,调用Mapper接口中的方法。 6. 创建Controller层 创建RESTful API,调用Service层方法返回数据。 7. 在启动类上添加@MapperScan注解 指定Mapper接口所在的包,让Spring Boot能够扫描到Mapper接口。 下面我们详细展开每一步: ### 1. 添加依赖 在pom.xml中添加以下依赖: ```xml <!-- MyBatis Spring Boot Starter --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.0</version> <!-- 请使用最新版本 --> </dependency> <!-- MySQL 驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> ``` 同时,移除Spring Data JPA的依赖(如果之前有的话)。 ### 2. 配置数据源和MyBatis 在`application.properties`中配置: ```properties # 数据源配置 spring.datasource.url=jdbc:mysql://localhost:3306/school_db?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=your_password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # MyBatis 配置 # 指定实体类所在的包 mybatis.type-aliases-package=com.example.demo.entity # 指定Mapper XML文件的位置 mybatis.mapper-locations=classpath:mapper/*.xml # 开启驼峰命名转换(下划线转驼峰) mybatis.configuration.map-underscore-to-camel-case=true ``` ### 3. 创建实体类 在包`com.example.demo.entity`下创建`Teacher`类: ```java package com.example.demo.entity; public class Teacher { private int id; private String name; private String subject; // getter和setter public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } } ``` ### 4. 创建Mapper接口和XML映射文件 首先,在包`com.example.demo.mapper`下创建`TeacherMapper`接口: ```java package com.example.demo.mapper; import com.example.demo.entity.Teacher; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper public interface TeacherMapper { List<Teacher> findAllTeachers(); } ``` 然后,在`resources/mapper`目录下创建`TeacherMapper.xml`文件: ```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.demo.mapper.TeacherMapper"> <select id="findAllTeachers" resultType="Teacher"> SELECT id, name, subject FROM table2 </select> </mapper> ``` 注意:`namespace`属性必须对应Mapper接口的全限定名,`id`对应接口中的方法名。 ### 5. 创建Service层 在包`com.example.demo.service`下创建`TeacherService`接口: ```java package com.example.demo.service; import com.example.demo.entity.Teacher; import java.util.List; public interface TeacherService { List<Teacher> getAllTeachers(); } ``` 在包`com.example.demo.service.impl`下创建`TeacherServiceImpl`实现类: ```java package com.example.demo.service.impl; import com.example.demo.entity.Teacher; import com.example.demo.mapper.TeacherMapper; import com.example.demo.service.TeacherService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class TeacherServiceImpl implements TeacherService { @Autowired private TeacherMapper teacherMapper; @Override public List<Teacher> getAllTeachers() { return teacherMapper.findAllTeachers(); } } ``` ### 6. 创建Controller层 在包`com.example.demo.controller`下创建`TeacherController`: ```java package com.example.demo.controller; import com.example.demo.entity.Teacher; import com.example.demo.service.TeacherService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController @RequestMapping("/api/teachers") public class TeacherController { @Autowired private TeacherService teacherService; @GetMapping public List<Teacher> getAllTeachers() { return teacherService.getAllTeachers(); } } ``` ### 7. 在启动类上添加@MapperScan 在Spring Boot的主启动类上添加`@MapperScan`注解,指定Mapper接口所在的包: ```java package com.example.demo; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan("com.example.demo.mapper") // 添加这行 public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` 这样,MyBatis的集成就完成了。启动应用,访`http://localhost:8080/api/teachers`即可获取教师列表。 注意:如果之前配置了JPA,需要确保JPA的自动配置被禁用(通常移除JPA依赖后就不会自动配置了)。 ### 相关题 1. 如何在MyBatis中实现动态SQL查询? 2. MyBatis如何实现分页查询? 3. 如何在Spring Boot中配置MyBatis的多数据源? 4. MyBatis的Mapper接口如何与XML映射文件进行绑定? 5. MyBatis如何实现一对多、多对一的关系映射? 以上步骤详细说明了如何在Spring Boot项目中用MyBatis替代JPA进行数据库操作。如有题,可参考MyBatis官方文档或Spring Boot集成MyBatis的相关资料[^1][^2][^3]。</think>### 在 Spring Boot 项目中集成 MyBatis 替代 JPA 的完整指南 #### 1. **移除 JPA 依赖并添加 MyBatis 依赖** 在 `pom.xml` 中替换依赖: ```xml <!-- 移除 JPA 依赖 --> <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> --> <!-- 添加 MyBatis 依赖 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> <!-- 使用最新版本 --> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> ``` #### 2. **配置数据源和 MyBatis** 在 `application.properties` 中配置: ```properties # 数据源配置 spring.datasource.url=jdbc:mysql://localhost:3306/school_db?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=your_password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # MyBatis 配置 mybatis.mapper-locations=classpath:mapper/*.xml mybatis.type-aliases-package=com.example.demo.entity ``` #### 3. **创建实体类** ```java // src/main/java/com/example/demo/entity/Teacher.java public class Teacher { private Long id; private String name; private String subject; // Getters and Setters } ``` #### 4. **创建 Mapper 接口** ```java // src/main/java/com/example/demo/mapper/TeacherMapper.java @Mapper public interface TeacherMapper { List<Teacher> findAllTeachers(); Teacher findTeacherById(@Param("id") Long id); } ``` #### 5. **创建 XML 映射文件** ```xml <!-- src/main/resources/mapper/TeacherMapper.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.demo.mapper.TeacherMapper"> <resultMap id="teacherResultMap" type="Teacher"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="subject" column="subject"/> </resultMap> <select id="findAllTeachers" resultMap="teacherResultMap"> SELECT id, name, subject FROM table2 </select> </mapper> ``` #### 6. **创建 Service 层** ```java // src/main/java/com/example/demo/service/TeacherService.java @Service public class TeacherService { private final TeacherMapper teacherMapper; @Autowired public TeacherService(TeacherMapper teacherMapper) { this.teacherMapper = teacherMapper; } public List<Teacher> getAllTeachers() { return teacherMapper.findAllTeachers(); } } ``` #### 7. **创建 Controller** ```java // src/main/java/com/example/demo/controller/TeacherController.java @RestController @RequestMapping("/api/teachers") @CrossOrigin(origins = "http://localhost:8080") public class TeacherController { private final TeacherService teacherService; @Autowired public TeacherController(TeacherService teacherService) { this.teacherService = teacherService; } @GetMapping public ResponseEntity<List<Teacher>> getAllTeachers() { return ResponseEntity.ok(teacherService.getAllTeachers()); } } ``` #### 8. **添加 MyBatis 扫描配置** 在启动类添加注解: ```java @SpringBootApplication @MapperScan("com.example.demo.mapper") // 添加此注解 public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } ``` ### 关键配置说明: 1. **XML 映射文件位置**: `mybatis.mapper-locations=classpath:mapper/*.xml` 确保 MyBatis 能扫描到 XML 文件 2. **实体类别名**: `mybatis.type-aliases-package` 允许在 XML 中直接使用类名代替全限定名 3. **Mapper 接口扫描**: `@MapperScan` 注解替代了 JPA 的 Repository 自动扫描机制 4. **动态 SQL 支持**: MyBatis 支持在 XML 中使用动态 SQL 标签: ```xml <select id="findByCondition" resultMap="teacherResultMap"> SELECT * FROM table2 <where> <if test="name != null"> AND name LIKE CONCAT('%', #{name}, '%') </if> <if test="subject != null"> AND subject = #{subject} </if> </where> </select> ``` ### 与 JPA 的主要区别: | **特性** | **MyBatis** | **JPA** | |------------------|------------------------------------------|--------------------------------------| | **SQL 控制** | 完全手动编写,灵活性高 | 自动生成,灵活性低 | | **开发效率** | 需写 SQL 和映射文件,效率较低 | 自动生成代码,开发效率高 | | **复杂查询支持** | 强大(支持动态 SQL) | 较弱(需结合 `@Query` 或 QueryDSL) | | **数据库兼容性** | 依赖 SQL 方言 | 通过 Hibernate 适配多种数据库 | | **学习曲线** | 需熟悉 SQL 和 XML 配置 | 需理解 JPA 规范和衍生查询语法 | ### 前端调用示例(Vue) ```vue <template> <div> <table> <tr v-for="teacher in teachers" :key="teacher.id"> <td>{{ teacher.name }}</td> <td>{{ teacher.subject }}</td> </tr> </table> </div> </template> <script> import axios from 'axios'; export default { data() { return { teachers: [] }; }, mounted() { axios.get('http://localhost:8080/api/teachers') .then(response => { this.teachers = response.data; }) .catch(error => { console.error('获取教师数据失败:', error); }); } }; </script> ``` ### 常见题解决: 1. **Mapper 接口未注入**: 检查 `@MapperScan` 包路径是否正确,或直接在 Mapper 接口添加 `@Mapper` 注解 2. **XML 文件未加载**: 确认 `application.properties` 中 `mybatis.mapper-locations` 路径匹配 3. **驼峰命名转换**: 在配置中添加: ```properties mybatis.configuration.map-underscore-to-camel-case=true ``` 4. **事务管理**: 在 Service 方法添加 `@Transactional` 注解支持事务 MyBatis 提供了比 JPA 更精细的 SQL 控制能力,特别适合需要复杂查询优化或遗留数据库集成的场景[^1][^2]。其核心优势在于将 SQL 与 Java 代码解耦,通过 XML 配置实现灵活的数据库操作[^3]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软件求生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值