3.6Service层实现

分类: 搭建单体商城服务

Service 层实现

Service 层是业务逻辑层,负责处理业务逻辑,协调 Repository 层和 Controller 层。MyBatis-Plus 提供了 IService 接口,简化了 Service 层的实现。本节将学习如何实现 Service 层。

本节将学习:Service 接口设计、ServiceImpl 实现、业务逻辑编写,以及事务管理。

Service 接口设计

IService 接口

IService 是 MyBatis-Plus 提供的通用 Service 接口,包含了基础的 CRUD 方法。

Service 接口定义

package com.example.ecommerce.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.ecommerce.entity.User; public interface UserService extends IService<User> { /** * 用户注册 */ User register(User user); /** * 用户登录 */ User login(String username, String password); /** * 根据用户名查询用户 */ User getByUsername(String username); }

IService 提供的方法

IService 常用方法:

  • boolean save(T entity):保存一条记录
  • boolean saveBatch(Collection<T> entityList):批量保存
  • boolean removeById(Serializable id):根据 ID 删除
  • boolean updateById(T entity):根据 ID 更新
  • T getById(Serializable id):根据 ID 查询
  • List<T> list():查询所有
  • Page<T> page(Page<T> page):分页查询

ServiceImpl 实现

ServiceImpl 类

ServiceImpl 是 MyBatis-Plus 提供的通用 Service 实现类,实现了 IService 接口的所有方法。

Service 实现类

package com.example.ecommerce.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.ecommerce.entity.User; import com.example.ecommerce.mapper.UserMapper; import com.example.ecommerce.service.UserService; import org.springframework.stereotype.Service; @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Override public User register(User user) { // 业务逻辑实现 return null; } @Override public User login(String username, String password) { // 业务逻辑实现 return null; } @Override public User getByUsername(String username) { // 业务逻辑实现 return null; } }

业务逻辑编写

用户注册业务逻辑

@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Autowired private PasswordEncoder passwordEncoder; @Override @Transactional(rollbackFor = Exception.class) public User register(User user) { // 1. 检查用户名是否已存在 User existUser = baseMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getUsername, user.getUsername()) ); if (existUser != null) { throw new BusinessException("Username already exists"); } // 2. 检查邮箱是否已存在 existUser = baseMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getEmail, user.getEmail()) ); if (existUser != null) { throw new BusinessException("Email already exists"); } // 3. 加密密码 user.setPassword(passwordEncoder.encode(user.getPassword())); // 4. 设置默认状态 user.setStatus(1); // 5. 保存用户 save(user); return user; } }

用户登录业务逻辑

@Override public User login(String username, String password) { // 1. 根据用户名查询用户 User user = baseMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getUsername, username) ); if (user == null) { throw new BusinessException("User not found"); } // 2. 检查用户状态 if (user.getStatus() == 0) { throw new BusinessException("User is disabled"); } // 3. 验证密码 if (!passwordEncoder.matches(password, user.getPassword())) { throw new BusinessException("Invalid password"); } return user; }

业务逻辑流程

事务管理

@Transactional 注解

@Transactional 用于声明事务,确保方法内的多个数据库操作要么全部成功,要么全部回滚。

事务使用示例

@Service public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService { @Autowired private OrderItemService orderItemService; @Autowired private ProductService productService; @Override @Transactional(rollbackFor = Exception.class) public Order createOrder(Order order, List<OrderItem> orderItems) { // 1. 计算订单总金额 BigDecimal totalAmount = orderItems.stream() .map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()))) .reduce(BigDecimal.ZERO, BigDecimal::add); order.setTotalAmount(totalAmount); // 2. 保存订单 save(order); // 3. 保存订单项 orderItems.forEach(item -> { item.setOrderId(order.getId()); orderItemService.save(item); }); // 4. 扣减库存 orderItems.forEach(item -> { productService.deductStock(item.getProductId(), item.getQuantity()); }); return order; } }

事务传播行为

事务传播行为说明:

  • REQUIRED:如果当前存在事务,则加入该事务;如果当前不存在事务,则创建一个新的事务(默认)
  • REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起
  • SUPPORTS:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行
  • NOT_SUPPORTED:以非事务的方式运行,如果当前存在事务,则把当前事务挂起
  • MANDATORY:如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常
  • NEVER:以非事务的方式运行,如果当前存在事务,则抛出异常
  • NESTED:如果当前存在事务,则创建一个嵌套事务;如果当前不存在事务,则创建一个新的事务

完整 Service 示例

UserService 完整示例

package com.example.ecommerce.service; import com.baomidou.mybatisplus.extension.service.IService; import com.example.ecommerce.entity.User; public interface UserService extends IService<User> { User register(User user); User login(String username, String password); User getByUsername(String username); User getByEmail(String email); boolean updatePassword(Long userId, String oldPassword, String newPassword); }
package com.example.ecommerce.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.ecommerce.entity.User; import com.example.ecommerce.mapper.UserMapper; import com.example.ecommerce.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @Autowired private PasswordEncoder passwordEncoder; @Override @Transactional(rollbackFor = Exception.class) public User register(User user) { // 检查用户名和邮箱是否已存在 if (getByUsername(user.getUsername()) != null) { throw new BusinessException("Username already exists"); } if (getByEmail(user.getEmail()) != null) { throw new BusinessException("Email already exists"); } // 加密密码 user.setPassword(passwordEncoder.encode(user.getPassword())); user.setStatus(1); // 保存用户 save(user); return user; } @Override public User login(String username, String password) { User user = getByUsername(username); if (user == null || user.getStatus() == 0) { throw new BusinessException("Invalid username or password"); } if (!passwordEncoder.matches(password, user.getPassword())) { throw new BusinessException("Invalid username or password"); } return user; } @Override public User getByUsername(String username) { return baseMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getUsername, username) ); } @Override public User getByEmail(String email) { return baseMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getEmail, email) ); } @Override @Transactional(rollbackFor = Exception.class) public boolean updatePassword(Long userId, String oldPassword, String newPassword) { User user = getById(userId); if (user == null) { throw new BusinessException("User not found"); } if (!passwordEncoder.matches(oldPassword, user.getPassword())) { throw new BusinessException("Invalid old password"); } user.setPassword(passwordEncoder.encode(newPassword)); return updateById(user); } }

官方资源

本节小结

在本节中,我们学习了:

第一个是 Service 接口设计。 继承 IService 接口,定义业务方法。

第二个是 ServiceImpl 实现。 继承 ServiceImpl 类,实现业务逻辑。

第三个是业务逻辑编写。 实现用户注册、登录等业务逻辑。

第四个是事务管理。 使用 @Transactional 注解管理事务。

这就是 Service 层实现。Service 层封装业务逻辑,是系统的核心层。

在下一节,我们将学习如何实现 Controller 层,提供 RESTful API。