Skip to Content
Dev DocsTocoAI Generated Code Architecture Summary

TocoAI Generated Code Architecture Summary

I. Project Overview

Tech Stack: Java (JDK 11 or above) + Spring Boot + MyBatis-Plus + Hibernate

Top-level Directory Structure:

root/ ├── pom.xml # Root POM, declares global dependencies ├── common/ # Global common module (UserContext, JwtUtil, etc.) ├── public_service/ # Cross-module RPC public interface storage ├── entrance/ # Project startup entry (AppApplication, global Filter, etc.) └── modules/ # All business modules

💡 Note: All specific examples in this document are based on the Homestay System requirement — Member Management Module


II. Internal Layered Structure of a Single Business Module

Each business module is split into 5 Maven sub-modules, strictly following a four-layer architecture:

modules/member/ ├── pom.xml # Module aggregate POM ├── common/ # Module-level enums, constants, utilities ├── persist/ # Data persistence layer ├── manager/ # Data assembly layer (DTO factory) ├── service/ # Business service layer (core for write operations) └── entrance/ # HTTP access layer (Controller)

Unidirectional Layer Dependency (top to bottom)

entrance └── service └── manager └── persist └── common / public_service (both available)

III. Core Responsibilities and Code File Details of Each Layer

1. common Layer — Module-level Public Definitions

DirectoryContent
enums/Enum types, e.g. MemberStatusEnum, RegisterChannelEnum
utils/Module-level utility classes
constants/Constant definitions

2. persist Layer — Data Persistence Layer (MyBatis-Plus for Read + Hibernate for Write)

persist/ ├── dos/ │ └── Member.java # DO: @TableName + @TableField, maps to DB table, used by MyBatis-Plus ├── mapper/ │ ├── MemberDao.java # Dao interface: provides getByXxx query methods (for upper layers) │ ├── MemberDaoImpl.java # Dao implementation: calls MemberMapper to execute queries │ └── mybatis/ │ └── MemberMapper.java # extends BaseMapper<Member>, native MyBatis-Plus Mapper └── qto/ # Query parameter objects for read plans (auto-generated, do not modify)

Key Characteristics:

  • Read operations: Use MyBatis-Plus, Mapper → Dao → Manager
  • Write operations: Use Hibernate (BO.persist()), bypass Mapper and persist directly via JPA Session

3. manager Layer — Data Assembly Layer (Entity → DTO Factory)

manager/ ├── dto/ │ └── MemberBaseDto.java # DTO data structure definition (FULLY_LOCKED, do not modify) ├── bo/ │ ├── MemberBO.java # Aggregate object (rich model, extendable via validateAggregate) │ │ └── extends base/BaseMemberBO.java (FULLY_LOCKED) │ └── ...(PointRecordBO、RechargeRecordBO, etc.) ├── converter/ │ └── MemberBaseDtoConverter.java # DO → DTO converter (FULLY_LOCKED) └── impl/ ├── MemberBaseDtoManagerImpl.java # Manager implementation (extendable) └── base/ └── MemberBaseDtoManagerBaseImpl.java # Base class (FULLY_LOCKED, auto-invokes Converter)

Key Characteristics:

  • MemberBO extends BaseMemberBO, implements BoValidator, uses JPA annotations (@Entity, @Column, @OneToMany, etc.), and participates in write operations as a Hibernate entity
  • validateAggregate() is the business invariant validation extension point (auto-invoked by the framework, do not call manually)
  • Converter is responsible for DO → BaseDTO field mapping, only performs get/set operations

4. service Layer — Business Service Layer (Core for Write + DTO Query Services)

service/ ├── MemberBOService.java # Write operation entry, extends BaseMemberBOService (STRUCTURE_LOCKED, method body extendable) ├── base/ │ └── BaseMemberBOService.java # Write operation framework code (FULLY_LOCKED, core logic generated by framework) ├── bto/ │ └── RegisterMemberBto.java # Write plan parameter object (FULLY_LOCKED, auto-generated by write plan) ├── dto/ │ ├── MemberBaseDtoService.java # DTO preset query service (implements PubMemberBaseDtoService) │ ├── RechargeRecordBaseDtoService.java │ └── assembler/ │ ├── MemberBaseDtoDataAssembler.java # Post-processing extension point (implement postProcessData) │ └── base/ │ └── MemberBaseDtoBaseDataAssembler.java # Base class (FULLY_LOCKED) └── query/ # QueryHandler generated by read plans (DtoQueryHandler)

Key Characteristics:

  • BOService write flow: Controller → BOService.writeMethod() → super.xxxBase(bto) → BaseBOService operates BO → rootBo.persist() commits to Hibernate Session
  • DtoService query flow: Service.getByXxx() → Manager.getByXxx() → Dao.getByXxx() → Converter converts → DataAssembler.postProcessData() post-processing

5. entrance Layer — HTTP Access Layer (Controller)

entrance/ └── web/ ├── controller/ │ └── MemberController.java # @Controller + @Validated (STRUCTURE_LOCKED, method body modifiable) ├── vo/ # VO structure definitions (member module currently does not return VO directly) │ ├── converter/ # DTO → VO converter │ └── assembler/ # VO data assembly └── query/ # VoQueryHandler (generated when read plan returns VO)

Key Characteristics:

  • Controller uses @Controller (not @RestController); return values are automatically wrapped as {code, message, data} by the framework’s HandlerMethodReturnValueHandler — do not add @ResponseBody
  • Only BTO / QTO / primitive types / Enum / VO are allowed as parameters; exposing DTO directly is prohibited

IV. Cross-module Call Mechanism (RPC Subscription)

Other modules calling MemberBaseDtoService in the member module:

┌─────────────┐ │ Other Module│ │ Controller │ └──────┬──────┘ │ @Resource injection ┌────────────────────────────────┐ │ public_service module │ │ PubMemberBaseDtoService │ ← Public RPC interface (Stub) └────────────────┬───────────────┘ │ Implementation class lives in member module ┌────────────────────────────────┐ │ member module │ │ MemberBaseDtoService │ ← implements PubMemberBaseDtoService └────────────────────────────────┘

Same-module calls: Inject the corresponding Service directly via @Resource, without going through public_service.


V. Tech Stack Summary

CategoryTechnologyVersion
FrameworkSpring Boot2.7.18
ORM (Read)MyBatis-Plus3.5.7
ORM (Write)Hibernate JPA5.5.7.Final

VI. Typical Write Operation Call Chain (Example: “Register Member”)

HTTP POST /api/member/register AuthFilter (JWT validation → write memberId into UserContext) MemberController.register(RegisterMemberBto) ├── Parameter validation (validateRegisterParams) ├── Phone uniqueness check (MemberBaseDtoService.getByPhone) └── MemberBOService.registerMember(bto) BaseMemberBOService.registerMemberBase(bto) ├── Check phone unique key conflict ├── new MemberBO() + set fields └── boResult.getAddedList().add(memberBO) MemberBO.persist() ← Hibernate Session flush → write to MySQL

VII. Typical Read Operation Call Chain (Example: “Query Member by Phone”)

MemberBaseDtoService.getByPhone(phone) MemberBaseDtoManager.getByPhoneList([phone]) MemberBaseDtoManagerBaseImpl └── MemberDao.getByPhoneList([phone]) ← MyBatis-Plus queries MySQL MemberBaseDtoConverter.convertFromDo(memberList) ← DO → DTO MemberBaseDtoDataAssembler.postProcessData(dtoList) ← Custom post-processing extension point Returns List<MemberBaseDto>

💡Core Philosophy: Read/Write Separation (MyBatis-Plus for reads + Hibernate for writes) + Strict Four-layer Architecture + Design-element-driven Code Generation.

Last updated on