Spring Boot + MyBatis 是 Java 后端开发中最常见的技术组合之一。本文记录完整的整合过程和 CRUD 实现。
添加依赖
pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
数据源配置
application.yml:
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8
username: root
password: root123
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.demo.entity
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true 自动把数据库的 user_name 映射到 Java 的 userName。
建表
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`email` varchar(100) DEFAULT NULL,
`age` int DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
实体类
package com.example.demo.entity;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class User {
private Long id;
private String username;
private String email;
private Integer age;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
Mapper 接口
package com.example.demo.mapper;
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserMapper {
// 注解方式 —— 简单 SQL 直接写注解
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(Long id);
@Insert("INSERT INTO user(username, email, age) VALUES(#{username}, #{email}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
@Delete("DELETE FROM user WHERE id = #{id}")
int deleteById(Long id);
// XML 方式 —— 复杂 SQL 写在 XML 里
List<User> findByCondition(@Param("username") String username,
@Param("minAge") Integer minAge);
int updateSelective(User user);
}
Mapper XML
resources/mapper/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.demo.mapper.UserMapper">
<select id="findByCondition" resultType="User">
SELECT * FROM user
<where>
<if test="username != null and username != ''">
AND username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="minAge != null">
AND age >= #{minAge}
</if>
</where>
ORDER BY create_time DESC
</select>
<update id="updateSelective">
UPDATE user
<set>
<if test="username != null">username = #{username},</if>
<if test="email != null">email = #{email},</if>
<if test="age != null">age = #{age},</if>
</set>
WHERE id = #{id}
</update>
</mapper>
<where> 标签会自动处理多余的 AND/OR,<set> 标签会自动处理多余的逗号。
启动类配置
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);
}
}
@MapperScan 扫描指定包下的所有 Mapper 接口,自动生成代理实现并注册到 Spring 容器。也可以在每个 Mapper 接口上加 @Mapper 注解代替。
Service 层
package com.example.demo.service;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class UserService {
private final UserMapper userMapper;
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
public User getById(Long id) {
return userMapper.findById(id);
}
@Transactional
public User create(User user) {
userMapper.insert(user);
return user; // id 已通过 useGeneratedKeys 回填
}
@Transactional
public int update(User user) {
return userMapper.updateSelective(user);
}
public List<User> search(String username, Integer minAge) {
return userMapper.findByCondition(username, minAge);
}
@Transactional
public int delete(Long id) {
return userMapper.deleteById(id);
}
}
Controller 层
package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public User getById(@PathVariable Long id) {
return userService.getById(id);
}
@PostMapping
public User create(@RequestBody User user) {
return userService.create(user);
}
@PutMapping("/{id}")
public int update(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return userService.update(user);
}
@GetMapping
public List<User> search(@RequestParam(required = false) String username,
@RequestParam(required = false) Integer minAge) {
return userService.search(username, minAge);
}
@DeleteMapping("/{id}")
public int delete(@PathVariable Long id) {
return userService.delete(id);
}
}
小结
整合过程:加依赖 → 配数据源 → 写实体类 → 写 Mapper 接口(+XML) → @MapperScan → 正常写 Service/Controller。简单 SQL 用注解,复杂动态 SQL 用 XML,两种方式可以混用。生产项目建议配合 PageHelper 做分页,配合 MyBatis-Plus 减少模板代码。