MyBatis-Plus 与 Spring 新手指南
MyBatis-Plus 与 Spring 新手指南
概述
本文档介绍 MyBatis-Plus 框架与 Spring 的集成方式,帮助新手快速理解数据访问层的设计模式和实现原理。
核心架构
1. 分层架构概念
Controller 层 (接口层) ↓Service 层 (业务逻辑层) ↓Repository 层 (数据访问层) ↓Mapper 层 (数据映射层) ↓Entity 层 (实体层) ← → Database (数据库)
2. Repository 模式
Repository 模式是领域驱动设计(DDD)中的重要概念,用于封装数据访问逻辑。
接口定义
public interface UserRepository { void save(User user); User findById(Long id); List<User> findByName(String name); void deleteById(Long id);}
实现类
@Servicepublic class UserRepositoryImpl implements UserRepository { // 具体实现}
MyBatis-Plus 核心组件
1. 实体类 (Entity)
@Data@TableName(\"user_info\") // 指定数据库表名public class User { @TableId(type = IdType.AUTO) // 主键,自增 private Long id; @TableField(\"user_name\") // 字段映射 private String name; private String email; @TableLogic // 逻辑删除标记 private Boolean deleted; @TableField(fill = FieldFill.INSERT) // 插入时自动填充 private LocalDateTime createTime;}
常用注解说明
@TableName
@TableName(\"user_info\")
@TableId
@TableId(type = IdType.AUTO)
@TableField
@TableField(\"user_name\")
@TableLogic
@TableLogic
2. Mapper 接口
@Mapper // 标记为MyBatis的Mapper接口public interface UserMapper extends BaseMapper<User> { // BaseMapper提供基础CRUD方法 // 可以添加自定义查询方法 @Select(\"SELECT * FROM user_info WHERE age > #{age}\") List<User> findByAgeGreaterThan(@Param(\"age\") Integer age);}
BaseMapper 提供的方法
// 插入int insert(T entity);// 删除int deleteById(Serializable id);int delete(Wrapper<T> wrapper);// 更新int updateById(T entity);int update(T entity, Wrapper<T> wrapper);// 查询T selectById(Serializable id);List<T> selectList(Wrapper<T> wrapper);IPage<T> selectPage(IPage<T> page, Wrapper<T> wrapper);
3. Service 层
接口定义
public interface UserService { boolean saveUser(User user); User getUserById(Long id); List<User> getUsersByName(String name); boolean updateUser(User user); boolean deleteUser(Long id);}
实现类 (继承 ServiceImpl)
@Servicepublic class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Override public boolean saveUser(User user) { return this.save(user); // 继承自ServiceImpl的方法 } @Override public User getUserById(Long id) { return this.getById(id); } @Override public List<User> getUsersByName(String name) { LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(); wrapper.eq(User::getName, name); return this.list(wrapper); }}
泛型机制详解
1. ServiceImpl 的泛型参数
public class ServiceImpl<M extends BaseMapper<T>, T> { // M: Mapper类型 // T: 实体类型}
2. 实际使用示例
// 明确指定泛型参数public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { // UserMapper: 操作数据库的Mapper // User: 操作的实体类型}
这样设计的优势:
- 类型安全: 编译时检查类型匹配
- 代码提示: IDE能提供准确的代码补全
- 自动映射: 框架自动处理实体与数据库的映射
Spring 集成要点
1. 依赖注入
@Servicepublic class UserController { @Autowired private UserService userService; // Spring自动注入 public User getUser(Long id) { return userService.getUserById(id); }}
2. 配置类
@Configuration@MapperScan(\"com.example.mapper\") // 扫描Mapper接口public class MyBatisConfig { @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); }}
3. 配置文件 (application.yml)
mybatis-plus: configuration: map-underscore-to-camel-case: true # 下划线转驼峰 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # SQL日志 global-config: db-config: logic-delete-field: deleted # 逻辑删除字段 logic-delete-value: 1 logic-not-delete-value: 0
查询构造器 (Wrapper)
1. LambdaQueryWrapper (推荐)
LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();wrapper.eq(User::getName, \"张三\") // name = \'张三\' .gt(User::getAge, 18) // age > 18 .like(User::getEmail, \"@gmail.com\") // email LIKE \'%@gmail.com%\' .orderByDesc(User::getCreateTime); // ORDER BY create_time DESCList<User> users = userMapper.selectList(wrapper);
2. QueryWrapper
QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq(\"name\", \"张三\") .gt(\"age\", 18) .like(\"email\", \"@gmail.com\") .orderByDesc(\"create_time\");
3. 常用查询方法
eq
eq(\"name\", \"张三\")
ne
ne(\"status\", 0)
gt
gt(\"age\", 18)
ge
ge(\"score\", 60)
lt
lt(\"price\", 100)
le
le(\"count\", 10)
like
like(\"name\", \"张\")
in
in(\"id\", Arrays.asList(1,2,3))
between
between(\"age\", 18, 30)
分页查询
// 创建分页对象IPage<User> page = new Page<>(1, 10); // 第1页,每页10条// 构建查询条件LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();wrapper.gt(User::getAge, 18);// 执行分页查询IPage<User> result = userMapper.selectPage(page, wrapper);System.out.println(\"总记录数: \" + result.getTotal());System.out.println(\"总页数: \" + result.getPages());System.out.println(\"当前页数据: \" + result.getRecords());
最佳实践
1. 项目结构建议
src/main/java/├── entity/ # 实体类├── mapper/ # Mapper接口├── service/ # Service接口├── service/impl/ # Service实现类├── controller/ # Controller层└── config/ # 配置类
2. 命名规范
- 实体类:
User
、UserInfo
- Mapper接口:
UserMapper
- Service接口:
UserService
- Service实现:
UserServiceImpl
- 数据库表:
user
、user_info
3. 代码建议
// ✅ 推荐:使用Lambda表达式,类型安全LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();wrapper.eq(User::getName, name);// ❌ 不推荐:字符串方式,容易出错QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq(\"name\", name);
常见问题
1. 实体类与数据库表名不匹配
@TableName(\"t_user\") // 指定实际的表名public class User { // ...}
2. 字段名不匹配
public class User { @TableField(\"user_name\") // 数据库字段名 private String name; // Java属性名}
3. 主键策略选择
@TableId(type = IdType.AUTO) // 数据库自增@TableId(type = IdType.ASSIGN_ID) // 雪花算法@TableId(type = IdType.INPUT) // 手动输入
总结
MyBatis-Plus 通过以下机制实现了简洁高效的数据访问:
- 泛型机制: 确保类型安全和代码提示
- 继承体系: 提供丰富的基础功能
- 注解映射: 简化配置,提高开发效率
- Spring集成: 无缝融入Spring生态
掌握这些核心概念,就能快速理解和使用MyBatis-Plus进行数据访问层开发。