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);
}
实现类
@Service
public 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)
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {@Overridepublic boolean saveUser(User user) {return this.save(user); // 继承自ServiceImpl的方法}@Overridepublic User getUserById(Long id) {return this.getById(id);}@Overridepublic 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. 依赖注入
@Service
public class UserController {@Autowiredprivate UserService userService; // Spring自动注入public User getUser(Long id) {return userService.getUserById(id);}
}
2. 配置类
@Configuration
@MapperScan("com.example.mapper") // 扫描Mapper接口
public class MyBatisConfig {@Beanpublic 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: 1logic-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查询 | 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进行数据访问层开发。