MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,旨在简化开发、提高效率。它在 MyBatis 的基础上只做增强不做改变,为简化 CRUD 操作提供了强大支持,尤其在生成 Mapper
接口方面表现突出。
一、核心概念
1.1 Mapper 接口
- 定义:Mapper 接口是 MyBatis/MyBatis-Plus 中用于定义数据库操作方法的 Java 接口。
- 作用:通过接口方法与 SQL 映射,实现对数据库的增删改查(CRUD)。
- MyBatis-Plus 特性:无需编写 SQL,继承
BaseMapper<T>
即可获得通用 CRUD 方法。
1.2 BaseMapper
- 是 MyBatis-Plus 提供的通用 Mapper 接口,封装了常见的 CRUD 操作。
- 示例:
public interface UserMapper extends BaseMapper<User> { // 继承后自动拥有 insert, selectById, updateById, deleteById 等方法 }
1.3 实体类(Entity)
- 与数据库表对应的 Java 类,通常使用 Lombok 简化 Getter/Setter。
- 需要使用
@TableName
、@TableId
、@TableField
等注解进行映射。
1.4 代码生成器(AutoGenerator)
- MyBatis-Plus 提供的
AutoGenerator
工具可自动生成 Entity、Mapper、Service、Controller 等代码。 - 支持自定义模板、包路径、数据库配置等。
二、操作步骤(详细)
以下步骤基于 Spring Boot + MyBatis-Plus 实现 Mapper 接口生成。
步骤 1:添加依赖(Maven)
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis-Plus Starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok(可选) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 代码生成器依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
</dependencies>
⚠️ 注意:版本需兼容,建议使用最新稳定版。
步骤 2:配置数据库连接(application.yml)
spring:
datasource:
url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台输出 SQL
mapper-locations: classpath*:mapper/*.xml
步骤 3:创建实体类(Entity)
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
@Data
@TableName("user") // 指定表名
public class User {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField("name")
private String name;
@TableField("email")
private String email;
@TableField("status")
private Integer status;
}
@TableId
:主键注解,type = IdType.AUTO
表示数据库自增。
步骤 4:生成 Mapper 接口
方式一:手动创建
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 可以添加自定义方法,如复杂查询
}
@Mapper
注解使 Spring 能扫描到该接口。也可在启动类加@MapperScan("com.example.mapper")
。
方式二:使用代码生成器(推荐)
创建代码生成器类:
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.sql.Types;
import java.util.Collections;
public class CodeGenerator {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/test_db", "root", "your_password")
.globalConfig(builder -> {
builder.author("your_name") // 设置作者
.outputDir(System.getProperty("user.dir") + "/src/main/java"); // 输出路径
})
.dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
int typeCode = metaInfo.getJdbcType().TYPE_CODE;
if (typeCode == Types.SMALLINT) {
return DbColumnType.INTEGER;
}
return typeRegistry.getColumnType(metaInfo);
}))
.packageConfig(builder -> {
builder.parent("com.example") // 设置父包名
.moduleName("demo") // 模块名
.pathInfo(Collections.singletonMap(OutputFile.mapper, System.getProperty("user.dir") + "/src/main/java/com/example/mapper"));
})
.strategyConfig(builder -> {
builder.entityBuilder()
.naming(NamingStrategy.underline_to_camel) // 下划线转驼峰
.columnNaming(NamingStrategy.underline_to_camel)
.enableLombok() // 启用 Lombok
.logicDeleteColumnName("deleted"); // 逻辑删除字段
builder.mapperBuilder()
.enableFileOverride() // 覆盖已有文件(谨慎使用)
.enableBaseResultMap() // 生成 ResultMap
.enableBaseColumnList(); // 生成 BaseColumnList
builder.serviceBuilder()
.enableFileOverride();
builder.controllerBuilder()
.enableFileOverride();
builder.addInclude("user"); // 指定要生成的表
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用 Freemarker 模板引擎
.execute();
}
}
运行该类,自动生成:
User.java
(Entity)UserMapper.java
(Mapper 接口)UserService.java
,UserController.java
等(可选)
步骤 5:注册 Mapper 扫描
在 Spring Boot 启动类上添加:
@SpringBootApplication
@MapperScan("com.example.mapper") // 扫描 Mapper 接口
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
步骤 6:使用 Mapper 接口
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public void test() {
User user = new User();
user.setName("张三");
user.setEmail("zhangsan@example.com");
// 插入
userMapper.insert(user);
// 查询
User dbUser = userMapper.selectById(1L);
// 更新
user.setEmail("new@example.com");
userMapper.updateById(user);
// 删除
userMapper.deleteById(1L);
}
}
三、常见错误与解决方案
错误 | 原因 | 解决方案 |
---|---|---|
Invalid bound statement (not found) |
Mapper 接口未被扫描 | 检查 @MapperScan 路径或 @Mapper 注解 |
Unknown column 'xxx' in 'field list' |
实体字段与数据库列名不匹配 | 使用 @TableField("column_name") 映射 |
主键未自增 | @TableId 类型设置错误 |
设置 type = IdType.AUTO |
生成器无法连接数据库 | 驱动或 URL 错误 | 检查 JDBC URL、用户名、密码 |
生成代码乱码 | 文件编码问题 | 设置 IDE 和项目编码为 UTF-8 |
四、注意事项
- 包扫描路径必须正确:确保
@MapperScan
包含所有 Mapper 接口。 - 数据库字段命名规范:建议使用下划线命名(如
user_name
),Java 使用驼峰(userName
),MP 会自动转换。 - 避免循环依赖:Service 中注入 Mapper,不要在 Mapper 中注入 Service。
- 逻辑删除字段需配置:在
application.yml
中配置:mybatis-plus: global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0
- 生成器慎用
enableFileOverride()
:会覆盖已有文件,建议开发初期使用。
五、使用技巧
批量操作:
userMapper.insertBatchSomeColumn(list); // 批量插入 userMapper.deleteBatchIds(Arrays.asList(1L, 2L)); // 批量删除
条件构造器(Wrapper):
QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("status", 1).like("name", "王"); List<User> users = userMapper.selectList(wrapper);
自定义 SQL: 在 Mapper 接口中添加方法并配合 XML 使用:
@Select("SELECT * FROM user WHERE name LIKE #{name}") List<User> findByName(@Param("name") String name);
六、最佳实践与性能优化
6.1 最佳实践
统一异常处理:结合
@RestControllerAdvice
处理数据库异常。使用分页插件:
@Configuration public class MyBatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }
使用:
Page<User> page = new Page<>(1, 10); userMapper.selectPage(page, null);
逻辑删除代替物理删除:避免数据丢失。
6.2 性能优化
- 避免 N+1 查询:使用
@Select
+JOIN
查询关联数据。 - 合理使用缓存:结合 Redis 缓存热点数据。
- SQL 审计:开启
mybatis-plus.configuration.log-impl
查看执行 SQL。 - 索引优化:在频繁查询的字段上建立索引。
七、总结
MyBatis-Plus 极大简化了 Mapper 接口的开发:
- 继承
BaseMapper
→ 获得通用 CRUD - 使用代码生成器 → 快速生成全套代码
- 结合 Wrapper → 实现复杂查询
- 配合分页、逻辑删除 → 提升开发效率