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 {
    
    @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. 依赖注入

@Service
public 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 DESC

List<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. 命名规范

  • 实体类: UserUserInfo
  • Mapper接口: UserMapper
  • Service接口: UserService
  • Service实现: UserServiceImpl
  • 数据库表: useruser_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 通过以下机制实现了简洁高效的数据访问:

  1. 泛型机制: 确保类型安全和代码提示
  2. 继承体系: 提供丰富的基础功能
  3. 注解映射: 简化配置,提高开发效率
  4. Spring集成: 无缝融入Spring生态

掌握这些核心概念,就能快速理解和使用MyBatis-Plus进行数据访问层开发。

你可能感兴趣的:(mybatis,spring,java)