The introduction
Hello, this is Anyin.
I was going to write down some simple uses of MQTT this week because I’ve been working with hardware for a while, and it’s kind of a summary. But today when I was writing a user add, delete, change and check of Anyin Cloud project, I suddenly felt that there are some small ways in writing a CRUD.
Today we are going to talk about some simple CRUD tricks that are part of daily development work.
Data entity Conversion
In our normal three-tier architecture, we have Controller, Service, and Dao layers, whose dependencies are top-down. As follows:
When we subcontract code, we generally stipulate that the upper layer cannot depend on the lower layer; Data interaction is required between layers, so three types of basic data entities are generated: VO, DTO and DO. They subcontract corresponding Controller layer, Service layer and Dao layer, and the conversion sequence is as follows:
You will find that this process requires four transformations. For example, if a query returns a result, the sequence of its conversions is as follows:
ReqVO => ReqDTO => ReqDO
|
RespVO <= RespDTO <= RespDO
Copy the code
This would be particularly annoying in a real development project, where a single query would operate on six entity classes and four transformation methods. So, I made a subtraction:
- To get rid of
RespVO
.RespDTO
andRespDO
Can be returned directly to the front end,But do not expose the table structure. - merge
ReqDO
andRespDO
That is they areDO
. - Merge in some scenarios
ReqDTO
andRespDTO
.
In this case, I am left with VO, DTO, and DO, which are usually converted 2 times. For example, in user list query, VO is transferred to DTO, DTO is transferred to DO, and the query result DO is directly returned to the front end. As follows:
Ext can be a single table query result or a join table query result. Note that Ext cannot inherit data mapping DO directly, otherwise it risks exposing the table structure
This way, the entire data entity transformation is at least a lot easier to write, albeit a mindless CURD
Method naming and method signing
Method commands and method signatures refer to CRUD method names and signatures, and the Controller layer and Service layer remain corresponding. I usually use the following five forms:
new
// --------- added ---------
/ / Controlelr layer
public ApiResponse create(@Valid @RequestBody SysUserSaveForm form)
/ / Service layer
public void create(SysUserSaveDTO info);
// --------- edit ---------
public ApiResponse modify(@PathVariable("id") Long id, @Valid @RequestBody SysUserSaveForm form)
public void modify(Long id, SysUserSaveDTO info);
// --------- query ---------
public ApiResponse<SysUserInfoDTO> info(@PathVariable("id") Long id)
public SysUserInfoDTO info(Long id);
// --------- delete ---------
public ApiResponse delete(@PathVariable("id") Long id)
public void delete(Long id);
// --------- page ---------
public ApiResponse<Page<SysUserExt>> page(@RequestBody SysUserPageForm form)
public Page<SysUserExt> page(SysUserPageDTO query);
Copy the code
These five basic methods are available for controllers and services of business object or entity type, but not for associated objects or non-business objects or entities. For example, users and roles belong to business objects and will have these five basic methods, while the association table between users and roles will not have these five basic methods and will not have corresponding Controller and Service classes.
The create and modify methods generally have the same data entities, but one has an ID and the other has no ID, so either the Controller or the Service layer will display the ID and pass it, This ensures that the fields of the SysUserSaveForm and SysUserSaveDTO data entities are one-to-one.
There are only two things you can do in the Controller layer:
- Data validation, this all goes through the data entity
Form
On the annotation match@Valid
Annotation for processing. - Data transformation is recommended here
mapsturct
Component data conversion, which saves a lot of effort.
The aggregation ofService
layer
In my understanding of the Service layer it should handle a small amount of simple business logic; If a complex Service is involved, add a separate ServiceA class for the complex Service. The current Service holds a reference to ServiceA and provides the corresponding GET method. Other business services that reference ServiceA cannot be injected directly through @AutoWired, but must get it from getXXXService of their main business Service.
To summarize, in the current business, only one Service class provides services, and its subclass is obtained through getXXXService. Is there that DDD thing about polymeric roots?
The Service layer also holds a reference to multiple Repositories. At the Service layer, complex business logic is stripped away to other sub-services, while database-related operations are stripped away to Repository. Here’s an example:
SysUserService holds a reference to SysUserRepository and provides the getRepository method to get an instance of SysUserRepository. In addition to the five basic methods in the previous section, all simple and complex database operations involving getByUsername should be stored in SysUserRepository. In addition, SysUserService may hold a Repository of its associated tables, such as SysUserRoleRepository, the associated table of users and roles.
A Service is an aggregation of its subservice and associated Repository. It provides the corresponding getXXX method. Services of other services cannot directly reference their subservice and associated Repository.
With some of the specifications described above, our Service is no longer bloated, but simply a scheduler or choreographer.
The last
Those are some simple thoughts for today’s simple CRUD. If you have any suggestions, please correct them.
Anyin Cloud