Skip to content

后端开发规范

1. 项目结构

1.1 整体架构

梵医云后端项目采用微服务架构,基于 Spring Boot 3.3.1 + Java 17 开发。

fanyi-cloud/
├── fanyi-dependencies/           # 依赖管理
├── fanyi-framework/             # 框架层
│   ├── fanyi-common/           # 公共模块
│   ├── fanyi-spring-boot-starter-web/       # Web启动器
│   ├── fanyi-spring-boot-starter-mybatis/    # MyBatis启动器
│   ├── fanyi-spring-boot-starter-security/   # 安全启动器
│   ├── fanyi-spring-boot-starter-redis/     # Redis启动器
│   └── ...
├── fanyi-gateway/              # 网关服务
├── fanyi-module-system/         # 系统模块
│   ├── fanyi-module-system-api/    # API接口定义
│   └── fanyi-module-system-biz/   # 业务实现
├── fanyi-module-infra/         # 基础设施模块
├── fanyi-module-mall/          # 商城模块
├── fanyi-module-crm/          # CRM模块
├── fanyi-module-erp/          # ERP模块
├── fanyi-module-bpm/          # 工作流模块
└── ...

1.2 模块结构规范

每个业务模块采用统一的目录结构:

fanyi-module-{module}/
├── fanyi-module-{module}-api/          # API接口定义
│   └── src/main/java/com/fanyi/cloud/module/{module}/api/
│       ├── {domain}/dto/               # 数据传输对象
│       └── {domain}/                  # API接口
└── fanyi-module-{module}-biz/          # 业务实现
    └── src/main/java/com/fanyi/cloud/module/{module}/
        ├── controller/                 # 控制器层
        │   ├── admin/                  # 管理后台接口
        │   │   └── {domain}/
        │   │       ├── vo/             # 视图对象
        │   │       └── {Domain}Controller.java
        │   └── app/                    # 移动端接口
        ├── service/                    # 服务层
        │   └── {domain}/
        │       ├── {Domain}Service.java
        │       └── {Domain}ServiceImpl.java
        ├── dal/                       # 数据访问层
        │   ├── dataobject/             # 数据对象
        │   │   └── {domain}/
        │   │       └── {Domain}DO.java
        │   └── mysql/                  # Mapper接口
        │       └── {domain}/
        │           └── {Domain}Mapper.java
        ├── convert/                   # 对象转换器
        │   └── {domain}/
        │       └── {Domain}Convert.java
        ├── framework/                 # 框架配置
        │   ├── config/                # 配置类
        │   ├── security/              # 安全配置
        │   └── mq/                   # 消息队列
        ├── mq/                        # 消息队列
        │   └── producer/              # 消息生产者
        ├── job/                       # 定时任务
        │   └── demo/
        └── {Module}ServerApplication.java  # 启动类

2. 命名规范

2.1 包命名规范

  • 基础包名com.fanyi.cloud.module.{module}
  • controller包com.fanyi.cloud.module.{module}.controller
  • service包com.fanyi.cloud.module.{module}.service
  • dal包com.fanyi.cloud.module.{module}.dal
  • convert包com.fanyi.cloud.module.{module}.convert
  • framework包com.fanyi.cloud.module.{module}.framework

2.2 类命名规范

类型命名规则示例
Controller{Domain}ControllerUserController
Service{Domain}ServiceUserService
ServiceImpl{Domain}ServiceImplUserServiceImpl
Mapper{Domain}MapperUserMapper
DataObject{Domain}DOUserDO
VO (Request){Operation}{Domain}ReqVOUserSaveReqVO
VO (Response){Domain}RespVOUserRespVO
VO (Page){Domain}PageReqVOUserPageReqVO
VO (Simple){Domain}SimpleRespVOUserSimpleRespVO
Convert{Domain}ConvertUserConvert
Enum{Domain}EnumSexEnum
Constants{Domain}ConstantsUserConstants

2.3 变量命名规范

  • 使用驼峰命名法
  • 布尔类型变量以 is 开头
  • 集合类型变量使用复数形式
java
private String username;
private Boolean isAdmin;
private List<UserDO> users;
private Map<Long, String> userMap;

2.4 方法命名规范

操作命名规则示例
新增createcreateUser
修改updateupdateUser
删除deletedeleteUser
查询单个getgetUser
查询列表list{Domain}slistUsers
查询分页get{Domain}PagegetUserPage
统计count{Domain}scountUsers
校验validatevalidateUser

3. 代码分层规范

3.1 Controller层

Controller层负责接收HTTP请求,参数校验,调用Service层处理业务逻辑,返回响应结果。

java
@Tag(name = "管理后台 - 用户")
@RestController
@RequestMapping("/system/user")
@Validated
public class UserController {

    @Resource
    private AdminUserService userService;

    @PostMapping("/create")
    @Operation(summary = "新增用户")
    @PreAuthorize("@ss.hasPermission('system:user:create')")
    public CommonResult<Long> createUser(@Valid @RequestBody UserSaveReqVO reqVO) {
        Long id = userService.createUser(reqVO);
        return success(id);
    }

    @GetMapping("/page")
    @Operation(summary = "获得用户分页列表")
    @PreAuthorize("@ss.hasPermission('system:user:list')")
    public CommonResult<PageResult<UserRespVO>> getUserPage(@Valid UserPageReqVO pageReqVO) {
        PageResult<AdminUserDO> pageResult = userService.getUserPage(pageReqVO);
        return success(pageResult);
    }
}

Controller层规范

  • 使用 @RestController 注解
  • 使用 @RequestMapping 定义基础路径
  • 使用 @Tag 注解添加API文档说明
  • 使用 @Operation 注解添加接口说明
  • 使用 @PreAuthorize 注解进行权限控制
  • 使用 @Valid@Validated 进行参数校验
  • 返回统一响应类型 CommonResult
  • 不包含业务逻辑,只负责参数接收和响应返回

3.2 Service层

Service层负责业务逻辑处理,事务控制,调用Mapper层进行数据操作。

java
@Service("adminUserService")
@Slf4j
public class AdminUserServiceImpl implements AdminUserService {

    @Resource
    private AdminUserMapper userMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}",
            success = CREATE_SUCCESS)
    public Long createUser(UserSaveReqVO createReqVO) {
        validateUserExists(null, createReqVO.getUsername(), 
                       createReqVO.getMobile(), createReqVO.getEmail());
        
        AdminUserDO user = UserConvert.INSTANCE.convert(createReqVO);
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userMapper.insert(user);
        return user.getId();
    }

    private void validateUserExists(Long id, String username, String mobile, String email) {
        if (StrUtil.isNotEmpty(username)) {
            AdminUserDO user = userMapper.selectByUsername(username);
            if (user != null && !user.getId().equals(id)) {
                throw exception(USER_USERNAME_EXISTS);
            }
        }
    }
}

Service层规范

  • 使用 @Service 注解
  • 实现对应的Service接口
  • 使用 @Transactional 注解控制事务
  • 使用 @LogRecord 注解记录操作日志
  • 包含完整的业务逻辑
  • 进行参数校验和业务规则校验
  • 抛出业务异常使用 ServiceException
  • 使用 @Resource 注入依赖

3.3 Mapper层

Mapper层负责数据库操作,继承 BaseMapperX 获得基础CRUD方法。

java
@Mapper
public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {

    default AdminUserDO selectByUsername(String username) {
        return selectOne(AdminUserDO::getUsername, username);
    }

    default AdminUserDO selectByEmail(String email) {
        return selectOne(AdminUserDO::getEmail, email);
    }

    default PageResult<AdminUserDO> selectPage(UserPageReqVO reqVO, Collection<Long> deptIds) {
        return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
                .likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
                .likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
                .eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())
                .inIfPresent(AdminUserDO::getDeptId, deptIds)
                .orderByDesc(AdminUserDO::getId));
    }
}

Mapper层规范

  • 使用 @Mapper 注解
  • 继承 BaseMapperX<DO> 获得基础方法
  • 使用 LambdaQueryWrapperX 构建查询条件
  • 使用 selectOneselectListselectPage 等方法
  • 复杂查询使用自定义SQL方法
  • 不包含业务逻辑,只负责数据访问

3.4 DataObject层

DataObject层对应数据库表,使用MyBatis-Plus注解映射。

java
@TableName(value = "system_users", autoResultMap = true)
@KeySequence("system_users_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AdminUserDO extends TenantBaseDO {

    @TableId
    private Long id;

    private String username;

    private String password;

    private String nickname;

    private String email;

    private String mobile;

    private Integer sex;

    private String avatar;

    private Integer status;

    private String loginIp;

    private LocalDateTime loginDate;
}

DataObject层规范

  • 使用 @TableName 注解指定表名
  • 使用 @TableId 注解标记主键
  • 使用 @KeySequence 注解指定序列(Oracle等)
  • 继承 TenantBaseDO 获得租户字段
  • 使用 @Data 注解自动生成getter/setter
  • 使用 @Builder 注解支持构建器模式
  • 字段类型与数据库类型对应
  • 不包含业务逻辑

3.5 Convert层

Convert层负责对象之间的转换,使用MapStruct自动生成转换代码。

java
@Mapper
public interface UserConvert {

    UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);

    default List<UserRespVO> convertList(List<AdminUserDO> list, Map<Long, DeptDO> deptMap) {
        return CollectionUtils.convertList(list, user -> convert(user, deptMap.get(user.getDeptId())));
    }

    default UserRespVO convert(AdminUserDO user, DeptDO dept) {
        UserRespVO userVO = BeanUtils.toBean(user, UserRespVO.class);
        if (dept != null) {
            userVO.setDeptName(dept.getName());
        }
        return userVO;
    }

    default AdminUserDO convert(UserSaveReqVO reqVO) {
        return BeanUtils.toBean(reqVO, AdminUserDO.class);
    }
}

Convert层规范

  • 使用 @Mapper 注解(MapStruct)
  • 定义 INSTANCE 常量
  • 使用 BeanUtils.toBean 进行对象转换
  • 处理复杂转换逻辑
  • 不包含业务逻辑

4. 数据库操作规范

4.1 基础CRUD操作

使用 BaseMapperX 提供的基础方法:

java
// 插入
userMapper.insert(userDO);

// 根据ID查询
AdminUserDO user = userMapper.selectById(id);

// 根据条件查询单个
AdminUserDO user = userMapper.selectOne(AdminUserDO::getUsername, username);

// 根据条件查询列表
List<AdminUserDO> users = userMapper.selectList(AdminUserDO::getDeptId, deptId);

// 分页查询
PageResult<AdminUserDO> pageResult = userMapper.selectPage(reqVO, wrapper);

// 更新
userMapper.updateById(userDO);

// 删除
userMapper.deleteById(id);

4.2 条件查询构建

使用 LambdaQueryWrapperX 构建查询条件:

java
new LambdaQueryWrapperX<AdminUserDO>()
    .eq(AdminUserDO::getStatus, 1)                    // 等于
    .ne(AdminUserDO::getDeleted, true)                  // 不等于
    .like(AdminUserDO::getUsername, "admin")             // 模糊查询
    .likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())  // 条件模糊查询
    .in(AdminUserDO::getDeptId, deptIds)               // IN查询
    .between(AdminUserDO::getCreateTime, startTime, endTime)  // BETWEEN查询
    .gt(AdminUserDO::getAge, 18)                       // 大于
    .ge(AdminUserDO::getAge, 18)                       // 大于等于
    .lt(AdminUserDO::getAge, 60)                       // 小于
    .le(AdminUserDO::getAge, 60)                       // 小于等于
    .isNull(AdminUserDO::getDeletedTime)                  // IS NULL
    .isNotNull(AdminUserDO::getUpdateTime)                // IS NOT NULL
    .orderByDesc(AdminUserDO::getId)                     // 降序排序
    .orderByAsc(AdminUserDO::getCreateTime)               // 升序排序

4.3 分页查询

使用统一的分页查询方法:

java
default PageResult<AdminUserDO> selectPage(UserPageReqVO reqVO, Collection<Long> deptIds) {
    return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
            .likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
            .likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
            .eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())
            .inIfPresent(AdminUserDO::getDeptId, deptIds)
            .orderByDesc(AdminUserDO::getId));
}

4.4 批量操作

java
// 批量插入
userMapper.insertBatch(userList);

// 批量更新
userMapper.updateBatch(userList);

// 批量删除
userMapper.deleteBatchIds(ids);

5. 接口开发规范

5.1 RESTful API规范

操作HTTP方法路径示例
新增POST/{module}/{domain}/createPOST /system/user/create
修改PUT/{module}/{domain}/updatePUT /system/user/update
删除DELETE/{module}/{domain}/deleteDELETE /system/user/delete?id=1
查询详情GET/{module}/{domain}/getGET /system/user/get?id=1
查询列表GET/{module}/{domain}/listGET /system/user/list
查询分页GET/{module}/{domain}/pageGET /system/user/page

5.2 请求参数规范

5.2.1 路径参数

java
@GetMapping("/get")
@Operation(summary = "获得用户")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<UserRespVO> getUser(@RequestParam("id") Long id) {
    return success(userService.getUser(id));
}

5.2.2 请求体参数

java
@PostMapping("/create")
@Operation(summary = "新增用户")
public CommonResult<Long> createUser(@Valid @RequestBody UserSaveReqVO reqVO) {
    Long id = userService.createUser(reqVO);
    return success(id);
}

5.2.3 查询参数

java
@GetMapping("/page")
@Operation(summary = "获得用户分页列表")
public CommonResult<PageResult<UserRespVO>> getUserPage(@Valid UserPageReqVO pageReqVO) {
    PageResult<AdminUserDO> pageResult = userService.getUserPage(pageReqVO);
    return success(pageResult);
}

5.3 响应结果规范

使用统一的响应结果 CommonResult

java
// 成功响应
return success(data);

// 成功响应(无数据)
return success(true);

// 失败响应
throw exception(USER_NOT_EXISTS);

5.4 分页响应规范

使用统一的分页结果 PageResult

java
PageResult<AdminUserDO> pageResult = userService.getUserPage(pageReqVO);
return success(pageResult);

6. 注解使用规范

6.1 Spring注解

注解用途示例
@RestController标记REST控制器@RestController
@RequestMapping定义请求路径@RequestMapping("/system/user")
@GetMappingGET请求@GetMapping("/get")
@PostMappingPOST请求@PostMapping("/create")
@PutMappingPUT请求@PutMapping("/update")
@DeleteMappingDELETE请求@DeleteMapping("/delete")
@RequestParam请求参数@RequestParam("id") Long id
@RequestBody请求体@RequestBody UserSaveReqVO reqVO
@Autowired依赖注入@Autowired
@Resource依赖注入@Resource
@Service标记服务类@Service("adminUserService")
@Transactional事务控制@Transactional(rollbackFor = Exception.class)
@Valid参数校验@Valid @RequestBody UserSaveReqVO reqVO
@Validated参数校验@Validated

6.2 MyBatis-Plus注解

注解用途示例
@TableName指定表名@TableName("system_users")
@TableId标记主键@TableId
@TableField标记字段@TableField("user_name")
@KeySequence指定序列@KeySequence("system_users_seq")
@TableLogic逻辑删除@TableLogic

6.3 Swagger注解

注解用途示例
@TagAPI分组@Tag(name = "管理后台 - 用户")
@Operation接口说明@Operation(summary = "新增用户")
@Parameter参数说明@Parameter(name = "id", description = "编号")

6.4 自定义注解

注解用途示例
@PreAuthorize权限控制@PreAuthorize("@ss.hasPermission('system:user:create')")
@LogRecord操作日志@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE)
@ApiAccessLog访问日志@ApiAccessLog(operateType = CREATE)

7. 异常处理规范

7.1 业务异常

使用 ServiceException 抛出业务异常:

java
import static com.fanyi.cloud.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.fanyi.cloud.module.system.enums.ErrorCodeConstants.USER_USERNAME_EXISTS;

private void validateUserExists(String username) {
    AdminUserDO user = userMapper.selectByUsername(username);
    if (user != null) {
        throw exception(USER_USERNAME_EXISTS);
    }
}

7.2 错误码定义

ErrorCodeConstants 中定义错误码:

java
public interface ErrorCodeConstants {
    ErrorCode USER_USERNAME_EXISTS = new ErrorCode(1_001_000_000, "用户名已存在");
    ErrorCode USER_NOT_EXISTS = new ErrorCode(1_001_000_001, "用户不存在");
    ErrorCode USER_PASSWORD_ERROR = new ErrorCode(1_001_000_002, "密码错误");
}

7.3 全局异常处理

使用框架提供的全局异常处理器,统一处理异常并返回错误信息。

8. 日志规范

8.1 日志级别

级别用途示例
ERROR错误日志log.error("用户创建失败", e);
WARN警告日志log.warn("用户名已存在");
INFO信息日志log.info("用户创建成功,userId={}", userId);
DEBUG调试日志log.debug("查询条件:{}", wrapper);

8.2 日志使用

java
@Slf4j
public class UserServiceImpl implements UserService {

    public Long createUser(UserSaveReqVO reqVO) {
        log.info("[createUser][开始创建用户,username={}]", reqVO.getUsername());
        try {
            Long id = doCreateUser(reqVO);
            log.info("[createUser][用户创建成功,userId={}]", id);
            return id;
        } catch (Exception e) {
            log.error("[createUser][用户创建失败,username={}]", reqVO.getUsername(), e);
            throw e;
        }
    }
}

8.3 操作日志

使用 @LogRecord 注解记录操作日志:

java
@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}",
        success = CREATE_SUCCESS)
public Long createUser(UserSaveReqVO createReqVO) {
    // 业务逻辑
}

9. 参数校验规范

9.1 基础校验注解

注解用途示例
@NotNull不能为null@NotNull private Long id;
@NotEmpty不能为空@NotEmpty private String name;
@NotBlank不能为空白@NotBlank private String username;
@Size长度校验@Size(min = 1, max = 20) private String username;
@Min最小值@Min(0) private Integer age;
@Max最大值@Max(150) private Integer age;
@Email邮箱格式@Email private String email;
@Pattern正则校验@Pattern(regexp = "^1[3-9]\d{9}$") private String mobile;

9.2 自定义校验

java
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MobileValidator.class)
public @interface Mobile {
    String message() default "手机号格式不正确";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

9.3 分组校验

java
public interface CreateGroup {}
public interface UpdateGroup {}

public class UserSaveReqVO {
    @Null(groups = CreateGroup.class)
    @NotNull(groups = UpdateGroup.class)
    private Long id;

    @NotBlank(groups = {CreateGroup.class, UpdateGroup.class})
    private String username;
}

10. 事务管理规范

10.1 事务注解

java
@Transactional(rollbackFor = Exception.class)
public void createUser(UserSaveReqVO reqVO) {
    // 业务逻辑
}

10.2 事务传播行为

java
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
    // 默认传播行为
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
    // 创建新事务
}

10.3 事务隔离级别

java
@Transactional(isolation = Isolation.READ_COMMITTED)
public void method() {
    // 读已提交
}

11. 权限控制规范

11.1 接口权限

使用 @PreAuthorize 注解控制接口权限:

java
@PreAuthorize("@ss.hasPermission('system:user:create')")
public CommonResult<Long> createUser(@Valid @RequestBody UserSaveReqVO reqVO) {
    // 业务逻辑
}

11.2 数据权限

使用数据权限注解控制数据访问范围:

java
@DataPermission(enable = true)
public PageResult<AdminUserDO> getUserPage(UserPageReqVO pageReqVO) {
    // 业务逻辑
}

12. 代码注释规范

12.1 类注释

java
/**
 * 管理后台的用户 Service 实现类
 *
 * @author 芋道源码
 */
@Service("adminUserService")
@Slf4j
public class AdminUserServiceImpl implements AdminUserService {
    // ...
}

12.2 方法注释

java
/**
 * 创建用户
 *
 * @param createReqVO 创建信息
 * @return 用户编号
 */
public Long createUser(UserSaveReqVO createReqVO) {
    // ...
}

12.3 字段注释

java
/**
 * 用户ID
 */
@TableId
private Long id;

/**
 * 用户账号
 */
private String username;

/**
 * 加密后的密码
 */
private String password;

13. 性能优化规范

13.1 批量操作

java
// 批量插入
userMapper.insertBatch(userList);

// 批量更新
userMapper.updateBatch(userList);

13.2 缓存使用

java
@Cacheable(cacheNames = "user", key = "#id")
public UserRespVO getUser(Long id) {
    // 业务逻辑
}

@CacheEvict(cacheNames = "user", key = "#id")
public void updateUser(UserSaveReqVO reqVO) {
    // 业务逻辑
}

13.3 懒加载

java
@Lazy
private TenantService tenantService;

13.4 分页查询

java
// 使用分页查询,避免全表扫描
PageResult<AdminUserDO> pageResult = userMapper.selectPage(reqVO, wrapper);

14. 安全规范

14.1 密码加密

java
@Resource
private PasswordEncoder passwordEncoder;

public void createUser(UserSaveReqVO reqVO) {
    String encodedPassword = passwordEncoder.encode(reqVO.getPassword());
    user.setPassword(encodedPassword);
}

14.2 SQL注入防护

使用 MyBatis-Plus 的 Lambda 查询,避免 SQL 注入:

java
new LambdaQueryWrapperX<AdminUserDO>()
    .eq(AdminUserDO::getUsername, username)

14.3 XSS防护

使用框架提供的 XSS 过滤器,防止 XSS 攻击。

15. 测试规范

15.1 单元测试

java
@SpringBootTest
class UserServiceTest {

    @Resource
    private AdminUserService userService;

    @Test
    void testCreateUser() {
        UserSaveReqVO reqVO = new UserSaveReqVO();
        reqVO.setUsername("test");
        Long id = userService.createUser(reqVO);
        assertNotNull(id);
    }
}

15.2 集成测试

java
@SpringBootTest
@AutoConfigureMockMvc
class UserControllerTest {

    @Resource
    private MockMvc mockMvc;

    @Test
    void testCreateUser() throws Exception {
        UserSaveReqVO reqVO = new UserSaveReqVO();
        reqVO.setUsername("test");
        
        mockMvc.perform(post("/system/user/create")
                .contentType(MediaType.APPLICATION_JSON)
                .content(JSON.toJSONString(reqVO)))
                .andExpect(status().isOk());
    }
}

16. 版本控制规范

16.1 Git提交规范

提交信息格式:<type>(<scope>): <subject>

类型说明示例
feat新功能feat(user): 添加用户创建接口
fix修复bugfix(user): 修复用户查询bug
docs文档docs(readme): 更新README文档
style代码格式style(user): 代码格式调整
refactor重构refactor(user): 重构用户服务
test测试test(user): 添加用户测试
chore构建/工具chore(deps): 更新依赖版本

16.2 分支规范

分支类型命名规则示例
主分支mainmain
开发分支developdevelop
功能分支feature/feature/user-login
修复分支fix/fix/user-login-error
发布分支release/release/v1.0.0

17. 常见问题

17.1 如何处理循环依赖?

使用 @Lazy 注解延迟加载:

java
@Resource
@Lazy
private TenantService tenantService;

17.2 如何处理大事务?

将大事务拆分为多个小事务:

java
@Transactional(rollbackFor = Exception.class)
public void bigTransaction() {
    methodA();
    methodB();
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodA() {
    // 小事务
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
    // 小事务
}

17.3 如何处理并发问题?

使用乐观锁:

java
@Version
private Integer version;

使用悲观锁:

java
@Transactional
public void updateWithLock(Long id) {
    AdminUserDO user = userMapper.selectByIdForUpdate(id);
    // 业务逻辑
    userMapper.updateById(user);
}

注意:本文档持续更新中,如有问题请及时反馈。