Service层调用Mapper与Service原则

在Spring Boot项目中,Service层通常会同时使用Mapper其他Service,但两者的用途和设计原则有明显区别:


1. 直接调用Mapper —— 处理当前模块的持久化操作

  • 对于当前Service所管理的实体(如CapitalAllocate),直接注入对应的Mapper,进行CRUD或复杂查询。

  • 这是最直接的职责划分:Service负责业务逻辑,Mapper负责数据库交互。

示例

java

@Autowired
private CapitalAllocateMapper allocateMapper;

public void allocate(CapitalAllocateDTO dto) {
    // 业务校验
    CapitalAllocate entity = convert(dto);
    allocateMapper.insert(entity);   // ✅ 直接调用自己模块的Mapper
}

2. 调用其他Service —— 获取跨模块的业务能力

  • 当需要其他业务模块的数据或操作时,应通过该模块的Service接口进行调用,不要直接注入其他模块的Mapper

  • 这样做可以:

    • 保持业务逻辑的封装性(其他模块的校验、状态流转等在Service层已处理);

    • 降低模块间的直接耦合;

    • 便于事务传播和AOP增强。

示例

java

@Autowired
private UserService userService;   // ✅ 调用其他模块的Service

public void allocate(CapitalAllocateDTO dto) {
    User user = userService.findById(dto.getUserId()); // 不直接注入UserMapper
    // ... 业务处理
}

3. 核心原则与注意事项

✅ 推荐做法

  • 自己的数据 → 自己的Mapper

  • 别人的数据 → 别人的Service

❌ 常见反模式

  • 在ServiceA中直接注入OtherMapper:导致业务逻辑分散,后续维护时可能遗漏Other模块内的约束。

  • Service之间循环依赖:应通过设计分层或引入中间层解决。


4. 总结

在您给出的CapitalAllocateService中:

  • allocateDetailMapperallocateMappercapitalInfoMapper 是当前模块/密切相关的Mapper,直接调用是合理的;

  • userService 是其他模块的服务,通过Service调用符合最佳实践。

因此,Service层既可以调用Mapper(自己模块的),也可以调用其他Service(其他模块的),关键是职责清晰、依赖合理


在 Spring Boot 的标准分层架构中,Service 层既可以调用 Mapper,也可以调用其他的 Service,二者并不互斥,而是根据职责分工合理使用。


1. 职责划分

  • Mapper:负责数据持久化操作(单表 CRUD、复杂 SQL 等),是 DAO 层。

  • Service:负责业务逻辑,可以组合多个 Mapper 或调用其他 Service 来完成一个完整的业务功能。


2. 何时调用 Mapper,何时调用 Service?

场景推荐做法原因
直接对单表进行简单增删改查直接注入并调用 Mapper轻量、直接、无需经过额外的业务层
需要复用某个复杂的业务逻辑(例如:用户权限校验、积分计算、订单状态流转)注入并调用 Service避免重复代码,保持业务逻辑的封装性和一致性
一个业务需要操作多张表,且这些操作属于同一个事务在当前 Service 中注入多个 Mapper,或调用其他 Service(注意事务传播)根据代码组织习惯,二者皆可。推荐将核心业务逻辑收口在 Service 中,通过 Service 调用 Service 更符合“领域驱动”风格

3. 你的 CapitalAllocateService 示例

java

public class CapitalAllocateService {
    private final CapitalAllocateDetailMapper allocateDetailMapper;
    private final CapitalAllocateMapper allocateMapper;
    private final CapitalInfoMapper capitalInfoMapper;
    private final UserService userService;
  • 前三个是 Mapper:用于操作数据库表(资金分配明细、资金分配主表、资金信息表)。

  • 最后一个是 UserService:很可能用于获取当前登录用户、权限校验等,这些是业务逻辑,不应由 Mapper 直接提供,因此注入 Service 是合理且常见的。

这个组合完全没有问题,是实际项目中的标准写法。


4. 需要注意的点

  • 避免循环依赖:Service A 调用 Service B,Service B 又调用 Service A,会导致启动失败。可通过 @Lazy 或重新设计职责解决。

  • 事务边界:如果调用其他 Service 的方法,注意该方法是否包含事务(@Transactional),以及事务传播行为是否符合预期。

  • 保持层间清晰:Controller 不能直接调用 Mapper,必须经过 Service;Service 之间可以互相调用,但尽量不要跨层调用(例如 Service 调用 Repository 再调用别的 Service 的反模式)。


总结

Service 层既可以调用 Mapper,也可以调用其他 Service,关键是根据职责选择:

  • 需要数据访问 → 注入 Mapper

  • 需要业务逻辑复用 → 注入 Service

你的 CapitalAllocateService 同时使用了 Mapper 和 Service,是合理且常见的设计。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值