PO, BO, VO, DTO and POJO

1. POJO (Plain Ordinary Java Object, simple Java object without rules)

POJO is a concept that refers to simple Java objects without rules.

Two, VO (View Object, view object)

Used in the presentation layer, its function is to encapsulate all the data of a specified page (or component).
VO is usually the object transmitted by the Web to the template rendering engine layer. According to the needs of the business, the data object corresponding to the page display (web page/swt, swing interface).

3. DTO/TO (Data Transfer Object, data transfer object)

It is used for data transfer object between presentation layer and service layer, it should not contain business logic.
DTO can be the object transmitted by Service and Manager.
Most of the time the data inside DTO comes from multiple tables.
For example, if a table has 100 fields, then the corresponding PO has 100 attributes. But the view layer only needs to display 10 fields, and there is no need to pass the entire PO object to the client. At this time, we can use DTO with only these 10 attributes to transfer data to the client. After reaching the client, if this object is used to display the corresponding interface, then its identity will be changed to VO at this time.

At the conceptual design level, the DTO passed from the presentation layer to the service layer is conceptually different from the DTO returned from the service layer to the presentation layer. But at the implementation level, we usually rarely do this (define two UserInfo, or even more), because doing so usually affects development efficiency. Generally, we design a fully compatible DTO. When the service layer receives data, attributes that should not be set by the presentation layer (such as the total price of an order should be determined by its unit price, quantity, discount, etc.), regardless of whether the presentation layer is set, the service layer ignores them; That is, a step of attribute filtering is added to the service layer, and the attribute values ​​​​that do not need to participate in the transmission are ignored, so that they do not participate in business logic or transmission.

The table name of DTO is recommended to use "*Info", such as: CustomerInfo

Four, DO (Domain Object, domain object)

A tangible or intangible business entity abstracted from the real world.
In domain-driven design, DO is not a simple POJO, it has domain business logic.

DO itself is the core of the business, it is recommended to appear with a real name, such as: Account, Customer

5. BO (business object, business object)

An object after encapsulating business logic. When dealing with business logic, we can deal with BO. BO can be an object that encapsulates business logic output by the Service layer. The main function of business objects is to encapsulate business logic into an object. This object can contain one or more other objects.

6. PO (Persistent Object, persistent layer data object)

A persistent object, which forms a one-to-one mapping relationship with the data structure of the persistence layer (usually a relational database).
PO is a POJO with only get/set methods
. If the persistence layer is a relational database, then, corresponding to the entities in the database table, you can simply think that a PO corresponds to a record in the database, and each field (or several) in the data table corresponds to one (or several) attributes of the PO.
PO is also sometimes referred to as a Data object, and PO should not contain any operations on the database.

For example, a resume, with education experience, work experience, training experience and so on. We can map education experience to a PO, work experience to a PO, and training experience to a PO. Create a BO object corresponding to the resume to process the resume, and each BO contains these POs.

A BO ​​can include multiple POs, and it is usually necessary to convert BOs into POs for data persistence; conversely, POs obtained from the DB need to be converted into BOs to be used in the business layer).

QUERY

Data query object, each layer receives the query request from the upper layer.
Note: For query packages with more than 2 parameters, it is forbidden to use the Map class to transmit.
Distinguish icons:

Create a simple model with a sequence diagram to describe the position of the above objects in the three-tier architecture application:

    The user makes a request (maybe filling out a form), and the data of the form is matched as VO at the presentation layer.
    The presentation layer converts the VO into the DTO required by the corresponding method of the service layer and sends it to the service layer.
    The service layer first constructs (or rebuilds) a DO based on the data of the DTO, and calls the business method of the DO to complete the specific business.
    The service layer converts the DO into the PO corresponding to the persistence layer (the ORM tool can be used or not), calls the persistence method of the persistence layer, passes the PO to it, and completes the persistence operation.
    For a reverse operation, such as reading data, it is also converted and passed in a similar way, omitted.


The difference between VO and DTO

Since DTO is the object that transfers data between the presentation layer and the service layer, why do we need a VO?

For most application scenarios, the attribute values ​​of DTO and VO are basically the same, and they are usually POJO, so there is no need to do more. But don’t forget that this is the thinking at the implementation level. For the design level, there should still be VO and DTO conceptually, because there is an essential difference between the two. DTO represents the data that the service layer needs to receive or return, and VO represents the data that the presentation layer needs to display.

For example: the service layer has a getUser() method to return a system user, and one of the attributes is gender (gender). For the service layer, it is only semantically defined: 1-male, 2-female, 0-unspecified, but for the presentation layer, it may need to use "handsome guy" to represent male, "beauty" to represent female, and "secret" to represent unspecified. Although the service layer directly returns the displayed "handsome guys and beautiful women" required by the presentation layer, it is no problem for most applications, but imagine that if the requirements allow customers to customize the style, different styles have different representations of "gender", or this service can be used by multiple clients (different portals) at the same time, and different clients have different requirements for the presentation layer. Going back to the analysis at the design level, from the perspective of the principle of single responsibility, the service layer is only responsible for the business and has nothing to do with the specific form of expression. Therefore, the DTO it returns should not be coupled with the form of expression.
application

In the following scenarios, we can consider combining VO and DTO into one (note: it is the implementation level):

    When the requirements are very clear and stable, and there is only one client, there is no need to distinguish VO from DTO, and only one DTO is sufficient. The reason for using only one DTO instead of VO is that the responsibilities of the service layer at the design level should still not be coupled with the presentation layer. Therefore, DTO still cannot use "handsome men and beautiful women" for "gender". This conversion should rely on page scripts (such as JavaScript) or other mechanisms (JSTL, EL, CSS).
    Even if the client can be customized, or there are multiple different clients, if the client can use some technology (script or other mechanism) to realize the conversion, the VO can also be retired.

The following scenarios need to give priority to the coexistence of VO and DTO:

  1. For some technical reasons, such as a framework (such as Flex) that automatically converts POJOs to certain fields in the UI, you can consider defining VO at the implementation level. This trade-off depends entirely on the comparison between the improvement of development and maintenance efficiency brought about by using the automatic conversion capability of the framework and the reduction of development and maintenance efficiency brought about by the extra work of designing one more VO.
  2. If there is a "big view" on the page, and all the data that make up this big view needs to call multiple services and return multiple DTOs to assemble (of course, this can also be replaced by providing a DTO that returns a big view at one time at the service layer, but whether it is appropriate to provide such a method at the service layer needs to be weighed at the design level).

The difference between DTO and DO

Conceptual difference: DTO is the data transmission object between the presentation layer and the service layer (it can be considered as an agreement between the two), while DO is an abstraction of various business roles in the real world. There is no one-to-one correspondence between the two, one DTO may correspond to multiple DOs, and vice versa, that is, there is a many-to-many relationship between the two.

The difference in data: For example, UserInfo and User, for a getUser() method, UserInfo should not return the user's password, then there should be no attribute definition of password, so UserInfo has at least one password attribute less than User. But if there is a createUser() method at the same time, the incoming UserInfo needs to contain the user's password.

Reasons for not returning DO directly in the service layer:

    From the design level, the presentation layer depends on the service layer, and the service layer depends on the domain layer. If DO is exposed, the presentation layer will directly depend on the domain layer. Although this is still a one-way dependency, this cross-layer dependency will lead to unnecessary coupling. At this time, the code in the presentation layer can bypass the service layer and directly call DO business operations in the domain layer that it should not access or some data that should not be obtained by the presentation layer. For the access control mechanism based on AOP intercepting the service layer, this problem is particularly prominent, and the business method of calling DO at the presentation layer will also make the transaction difficult to control due to transaction problems.

For some ORM frameworks (such as Hibernate), the "lazy loading" technology is usually used. If DO is directly exposed to the presentation layer, in most cases, the presentation layer is not within the scope of the transaction (Open session in view is not a design worth admiring in most cases).

DTO should be a "flat two-dimensional object". For example: if User is associated with several other entities (such as Address, Account, Region, etc.), then does the UserInfo returned by getUser() need to return all the DTOs of its associated objects? If this is the case, it will inevitably lead to a large increase in the amount of data transmission. For distributed applications, this design is even more unacceptable because it involves data transmission, serialization and deserialization on the network. If getUser needs to return an AccountId, AccountName, RegionId, and RegionName in addition to the basic information of the User, then please define these attributes in UserInfo to "flatten" a "three-dimensional" object tree into a "flat two-dimensional object".

The difference between DO and PO

DO and PO are in one-to-one correspondence in most cases, but some scenarios can still reflect the essential difference between the two concepts:

DO does not need to be explicitly persisted in some scenarios. For example, the product discount strategy designed using the strategy pattern will derive discount strategy interfaces and different discount strategy implementation classes. These discount strategy implementation classes can be regarded as DOs, but they only reside in static memory and do not need to be persisted to the persistence layer. Therefore, there is no corresponding PO for this type of DO.
    In some scenarios, PO does not have a corresponding DO. For example, there is a many-to-many relationship between Teacher and Student. In a relational database, this relationship needs to be represented as an intermediate table, which corresponds to a PO of TeacherAndStudentPO. However, this PO has no practical significance in the business field, and it cannot correspond to any DO at all. It is specially stated here that not all many-to-many relationships have no business meaning, which is related to specific business scenarios. For example, the relationship between two POs will affect specific businesses, and there are many types of such relationships, so this many-to-many relationship should also be expressed as a DO. Another example: there is a many-to-many relationship between "roles" and "resources", and this relationship will obviously be expressed as a DO-"permission".
    In some cases, for a certain persistence strategy or performance considerations, one PO may correspond to multiple DOs, and vice versa. For example, the customer Customer has its contact information Contacts, here are two DOs with a one-to-one relationship, but for performance considerations (extreme cases), in order to reduce the connection query operation of the database, the two DO data of Customer and Contacts are merged into one data table. Conversely, if a Book has an attribute of the cover cover, but this attribute is the binary data of a pair of pictures, and some query operations do not want to load the cover together, so as to reduce the disk IO overhead, and assuming that the ORM framework does not support attribute-level lazy loading, then it is necessary to consider separating the cover into a data table, thus forming a situation where one DO corresponds to multiple POs.
    Some attribute values ​​of PO have no meaning for DO. These attribute values ​​may be data that exist to solve certain persistence strategies. For example, in order to implement "optimistic locking", PO has a version attribute. This version has no business significance for DO, and it should not exist in DO. Similarly, there may also be attributes in DO that do not need to be persisted.

application

Since the ORM framework is very powerful and popular, and JavaEE has also introduced the JPA specification, the current business application development basically does not need to distinguish between DO and PO. PO can be hidden in DO through JPA and Hibernate Annotations/hbm. Even so, there are some issues we must also pay attention to:

    For properties that do not need to be persisted in DO, they need to be explicitly declared through ORM. For example, in JPA, @Transient declaration can be used.
    For attributes that exist in PO for a certain persistence strategy, such as version, since DO and PO are merged, they must be declared in DO. However, since this attribute has no business significance for DO, it needs to be hidden from the outside. The most common way is to privatize the get/set method of this attribute, or even not provide get/set methods. But for Hibernate, this requires special attention. Because when Hibernate reads data from the database and converts it into DO, it first uses the reflection mechanism to call the empty parameter constructor of DO to construct the DO instance, and then uses the JavaBean specification to reflect the set method to set the value for each attribute. If the set method is not explicitly declared, or the set method is set to private, Hibernate will not be able to initialize DO, resulting in runtime exceptions. The feasible way is to set the set method of the attribute as protected.
    For scenarios where one DO corresponds to multiple POs, or one PO corresponds to multiple DOs, and attribute-level lazy loading, Hibernate provides good support. Please refer to the relevant information of Hibnate.


 

Guess you like

Origin blog.csdn.net/m0_51660523/article/details/123235948