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
| Directory | Content |
|---|---|
| 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
| Category | Technology | Version |
|---|---|---|
| Framework | Spring Boot | 2.7.18 |
| ORM (Read) | MyBatis-Plus | 3.5.7 |
| ORM (Write) | Hibernate JPA | 5.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 MySQLVII. 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
