一、核心概念
Service接口
- 业务层抽象,定义CRUD操作方法
- 继承MyBatis-Plus的
IService<T>
接口获得基础方法
ServiceImpl实现类
- 服务接口的具体实现
- 继承
ServiceImpl<Mapper<T>, T>
获得默认实现 - 需添加
@Service
注解
二、详细操作步骤
步骤1:配置代码生成器(续接实体类生成)
public class CodeGenerator {
public static void main(String[] args) {
// ... [全局配置、数据源配置省略] ...
// 包配置
PackageConfig packageConfig = new PackageConfig();
packageConfig.setParent("com.example.project");
packageConfig.setEntity("entity");
packageConfig.setMapper("mapper");
packageConfig.setService("service"); // Service接口包名
packageConfig.setServiceImpl("service.impl"); // 实现类包名
generator.setPackageInfo(packageConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
// 重点配置:Service生成选项
strategy.setServiceGenerateEnable(true); // 启用Service生成
strategy.setSuperServiceClass("com.example.project.base.BaseService"); // 自定义父接口
strategy.setSuperServiceImplClass("com.example.project.base.BaseServiceImpl"); // 自定义父实现
strategy.setInclude("user", "product"); // 生成对应表的Service
generator.setStrategy(strategy);
// ... [模板引擎配置省略] ...
generator.execute();
}
}
步骤2:自定义Service模板(可选)
复制默认模板到
resources/templates
:service.java.ftl
(接口模板)serviceImpl.java.ftl
(实现类模板)
修改模板内容(示例简化接口):
// serviceImpl.java.ftl
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}>
implements ${table.serviceName} {
// 简化默认方法
public boolean save(${entity} entity) {
return retBool(baseMapper.insert(entity));
}
}
步骤3:生成文件结构
src/main/java
└── com
└── example
└── project
├── entity
├── mapper
└── service
├── UserService.java # Service接口
└── impl
├── UserServiceImpl.java # 实现类
三、常见错误及解决
Service方法调用报空指针
- 原因:未在Controller中注入Service
- 解决:添加
@Autowired
注解
@RestController public class UserController { @Autowired // 关键注入 private UserService userService; }
事务失效问题
- 现象:
@Transactional
注解不生效 - 解决:
避免在同类非事务方法中调用事务方法@Service public class UserServiceImpl extends ... { // 正确:在public方法上添加注解 @Transactional(rollbackFor = Exception.class) public void batchCreate(List<User> users) { // ... } }
- 现象:
多数据源Service报错
- 错误:
No qualifying bean of type 'UserService'
- 解决:在启动类排除自动配置
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
- 错误:
四、注意事项
服务层职责边界
- Service应包含业务逻辑,避免直接操作Mapper
- 事务管理应在Service层完成
方法覆盖原则
- 需要修改默认CRUD实现时:
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> { // 覆盖默认查询方法 @Override public User getById(Serializable id) { // 自定义逻辑 return super.getById(id); } }
泛型传递规范
- 正确声明泛型类型:
// ✅ 正确 public interface UserService extends IService<User> // ❌ 错误(缺少泛型参数) public class UserServiceImpl extends ServiceImpl<UserMapper>
五、高级使用技巧
链式查询封装
// 在Service接口中添加 default QueryChainWrapper<User> queryChain() { return new QueryChainWrapper<>(getBaseMapper()); } // 使用示例 User user = userService.queryChain() .eq("status", 1) .like("name", "John") .one();
多表关联查询
@Service public class OrderServiceImpl ... { public OrderDetailVO getDetail(Long orderId) { // 在Service层做数据组装 Order order = getById(orderId); User user = userService.getById(order.getUserId()); return new OrderDetailVO(order, user); } }
服务熔断降级
@Service public class PaymentService { @HystrixCommand(fallbackMethod = "defaultPayment") public boolean pay(Order order) { ... } private boolean defaultPayment(Order order) { // 降级逻辑 } }
六、性能优化方案
批量操作优化
@Service public class UserServiceImpl ... { // 使用批处理模式 @Transactional public void batchInsert(List<User> users) { saveBatch(users, 1000); // 每1000条提交一次 } }
读写分离配置
@Master // 自定义注解 @Override public boolean save(User entity) { // 写操作路由到主库 return super.save(entity); } @Slave // 从库查询 @Override public User getById(Serializable id) { return super.getById(id); }
二级缓存启用
# application.yml mybatis-plus: configuration: cache-enabled: true
在Service方法添加缓存注解:
@Cacheable(value = "users", key = "#id") @Override public User getById(Long id) { ... }
七、最佳实践
服务分层架构
service/ ├── UserService.java # 接口定义 ├── impl/ │ └── UserServiceImpl.java # 基础实现 └── ext/ # 扩展服务 └── UserServiceExt.java # 业务增强接口
DTO分离原则
@Service public class UserServiceImpl ... { // 使用DTO接收参数 public UserDTO createUser(UserCreateDTO dto) { User user = convert(dto, User.class); save(user); return convert(user, UserDTO.class); } }
服务监控集成
@Timed(value = "user_service_time", description = "用户服务耗时") @Counted(value = "user_service_count", description = "用户服务调用次数") @Override public User getById(Long id) { ... }
生成结果示例
Service接口:
public interface UserService extends IService<User> {
// 自定义业务方法
List<User> findInactiveUsers(LocalDateTime lastLoginBefore);
}
ServiceImpl实现类:
@Service
public class UserServiceImpl
extends ServiceImpl<UserMapper, User>
implements UserService {
@Override
public List<User> findInactiveUsers(LocalDateTime lastLoginBefore) {
return lambdaQuery()
.lt(User::getLastLoginTime, lastLoginBefore)
.eq(User::getActive, false)
.list();
}
// 覆盖默认删除方法
@Override
@Transactional
public boolean removeById(Serializable id) {
// 添加审计日志
log.info("Deleting user: {}", id);
return super.removeById(id);
}
}
执行效果验证:
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
void testBatchCreate() {
List<User> users = generateTestUsers(10000);
userService.batchInsert(users); // 批量插入1w条数据
}
}
关键要点:
- Service层应聚焦业务逻辑,基础CRUD交给MyBatis-Plus默认实现
- 事务控制在Service层实现
- 复杂查询使用
LambdaQueryWrapper
保持代码可读性- 批量操作注意设置合理的批处理大小(500-2000条/批)
- 高并发场景考虑添加
@Cacheable
缓存注解
通过合理使用MyBatis-Plus的Service生成功能,可减少70%以上的重复CRUD代码,同时保持架构的扩展性和可维护性。