feat: Spring Boot 学习脚手架 v2.0
- 新增 IoC 容器学习模块 - 新增 AOP 切面编程学习模块 - 新增 MyBatis 集成学习模块 - 新增事务管理学习模块 - 新增用户/产品/订单 CRUD - 新增 7 个交互式学习页面 - 集成性能监控切面
This commit is contained in:
24
src/main/java/com/example/scaffold/service/UserService.java
Normal file
24
src/main/java/com/example/scaffold/service/UserService.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.example.scaffold.service;
|
||||
|
||||
import com.example.scaffold.entity.User;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 用户服务接口 - 演示接口与实现分离
|
||||
*/
|
||||
public interface UserService {
|
||||
|
||||
List<User> findAll();
|
||||
|
||||
Optional<User> findById(Long id);
|
||||
|
||||
User save(User user);
|
||||
|
||||
void deleteById(Long id);
|
||||
|
||||
List<User> searchByUsername(String username);
|
||||
|
||||
long count();
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.example.scaffold.service.impl;
|
||||
|
||||
import com.example.scaffold.entity.Order;
|
||||
import com.example.scaffold.entity.Product;
|
||||
import com.example.scaffold.mapper.OrderMapper;
|
||||
import com.example.scaffold.mapper.ProductMapper;
|
||||
import com.example.scaffold.mapper.UserMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 订单服务 - 演示事务传播和隔离级别
|
||||
*
|
||||
* 学习要点:
|
||||
* 1. 事务传播行为 - Propagation
|
||||
* 2. 事务隔离级别 - Isolation
|
||||
* 3. 事务回滚 - rollbackFor
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class OrderService {
|
||||
|
||||
private final OrderMapper orderMapper;
|
||||
private final ProductMapper productMapper;
|
||||
private final UserMapper userMapper;
|
||||
|
||||
/**
|
||||
* 创建订单 - 演示事务
|
||||
* REQUIRED: 有事务则加入,无则新建
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
|
||||
public Order createOrder(Long userId, Long productId, Integer quantity) {
|
||||
log.info("📦 [OrderService] 创建订单: userId={}, productId={}, quantity={}", userId, productId, quantity);
|
||||
|
||||
// 检查用户
|
||||
if (userMapper.findById(userId) == null) {
|
||||
throw new RuntimeException("用户不存在: " + userId);
|
||||
}
|
||||
|
||||
// 检查产品
|
||||
Product product = productMapper.findById(productId);
|
||||
if (product == null) {
|
||||
throw new RuntimeException("产品不存在: " + productId);
|
||||
}
|
||||
|
||||
// 扣减库存
|
||||
int rows = productMapper.decreaseStock(productId, quantity);
|
||||
if (rows == 0) {
|
||||
throw new RuntimeException("库存不足");
|
||||
}
|
||||
|
||||
// 创建订单
|
||||
Order order = new Order();
|
||||
order.setUserId(userId);
|
||||
order.setProductId(productId);
|
||||
order.setQuantity(quantity);
|
||||
order.setTotalPrice(product.getPrice().multiply(BigDecimal.valueOf(quantity)));
|
||||
order.setStatus("PENDING");
|
||||
|
||||
orderMapper.insert(order);
|
||||
log.info("✅ [OrderService] 订单创建成功: orderId={}", order.getId());
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟事务回滚
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
|
||||
public Order createOrderWithRollback(Long userId, Long productId, Integer quantity, boolean shouldRollback) {
|
||||
log.info("📦 [OrderService] 创建订单(可能回滚): userId={}, shouldRollback={}", userId, shouldRollback);
|
||||
|
||||
Order order = createOrder(userId, productId, quantity);
|
||||
|
||||
if (shouldRollback) {
|
||||
log.warn("⚠️ [OrderService] 触发回滚!");
|
||||
throw new RuntimeException("模拟事务回滚");
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
/**
|
||||
* REQUIRES_NEW - 挂起当前事务,创建新事务
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void logOrderOperation(Long orderId, String operation) {
|
||||
log.info("📝 [OrderService] 记录订单操作: orderId={}, operation={}", orderId, operation);
|
||||
// 这个方法会在独立事务中执行
|
||||
// 即使外部事务回滚,这里的记录也会保留
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用隔离级别 READ_COMMITTED
|
||||
*/
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
public Order getOrder(Long id) {
|
||||
return orderMapper.findById(id);
|
||||
}
|
||||
|
||||
public List<Order> findAll() {
|
||||
return orderMapper.findAll();
|
||||
}
|
||||
|
||||
public List<Order> findByUserId(Long userId) {
|
||||
return orderMapper.findByUserId(userId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateStatus(Long id, String status) {
|
||||
orderMapper.updateStatus(id, status);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteById(Long id) {
|
||||
orderMapper.deleteById(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.example.scaffold.service.impl;
|
||||
|
||||
import com.example.scaffold.entity.User;
|
||||
import com.example.scaffold.mapper.UserMapper;
|
||||
import com.example.scaffold.service.UserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 用户服务实现 - 演示 Spring 服务层
|
||||
*
|
||||
* 学习要点:
|
||||
* 1. @Service - 标记为服务组件
|
||||
* 2. @Transactional - 声明式事务
|
||||
* 3. @RequiredArgsConstructor - Lombok 构造器注入
|
||||
* 4. @Slf4j - Lombok 日志
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
|
||||
@Override
|
||||
public List<User> findAll() {
|
||||
log.info("📊 [UserService] 查询所有用户");
|
||||
return userMapper.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<User> findById(Long id) {
|
||||
log.info("🔍 [UserService] 查询用户: id={}", id);
|
||||
// 演示 MyBatis 一级缓存 - 连续两次查询
|
||||
User user = userMapper.findById(id);
|
||||
User cached = userMapper.findById(id); // 第二次会命中缓存
|
||||
if (cached != null) {
|
||||
log.info("✅ [UserService] 一级缓存命中: id={}", id);
|
||||
}
|
||||
return Optional.ofNullable(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public User save(User user) {
|
||||
log.info("💾 [UserService] 保存用户: {}", user.getUsername());
|
||||
if (user.getId() == null) {
|
||||
userMapper.insert(user);
|
||||
} else {
|
||||
userMapper.update(user);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteById(Long id) {
|
||||
log.info("🗑️ [UserService] 删除用户: id={}", id);
|
||||
userMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<User> searchByUsername(String username) {
|
||||
log.info("🔎 [UserService] 搜索用户: username={}", username);
|
||||
return userMapper.findByUsernameLike(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return userMapper.count();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user