The concept and difference between PO VO BO DTO DAO and POJO in Java (illustration)

object relationship diagram

I drew one according to myself on the Internet:

I also uploaded the file I drew so that you can change it easily. I drew it with drawio: https://download.csdn.net/download/weixin_45525272/84730067

each object concept

DAO

DAO (Data Access Object) data access object,it isAn object-oriented database interface, is responsible for the operation of the persistence layer, provides an interface for the business layer, and is mainly used to encapsulate the access to the database. The common operation is nothing more than CURD.

We can also think that a DAO corresponds to a POJO object, which is located in the middle of business logic and database resources, and can be combined with PO to perform related operations on the database.

PO

PO (Persistent Object) persistence layer object,it isConsists of a set of properties and property get and set methods, the simplest PO corresponds to a record in a table in the database (that is to say, we can understand a record in the database table as a persistent layer object), multiple records can use the collection of PO, and the PO should be Does not contain any operations on the database. The properties of PO are in one-to-one correspondence with the fields of the database table, and the PO object needs to implement the serialization interface.

BO

BO (Business Object) business layer object, are simple real-world software abstractions, usually in the middle layer.

The main function of BO is to encapsulate business logic as an object, which can include one or more other objects. To give an example of job-hunting resumes, each resume includes educational experience, project experience, etc. We can make education experience and project experience correspond to a PO, so that when we create a BO object corresponding to job-hunting resumes to process resumes, let each BO can contain these POs.

VO

VO (Value Object) value object, usually used for data transfer between business layers,Like PO, it only contains data, but VO should be an abstract business object, which can correspond to a table or not, according to the needs of the business.

If the pots and pans are the corresponding business objects, then the entire cupboard is a value object. also,VO can also be called a page object, if it is called a page object, then it will represent the object of the entire page display layer, and it can also be assembled from the required business objects.

DTO

DTO (Data Transfer Object) data transfer object, mainly used for remote calls and other places that require a large number of transfer objects. For example, if we have a transaction order table with 25 fields, then the corresponding PO has 25 attributes, but we only need to display 5 fields on our page. Therefore, there is no need to pass the entire PO object to the client. At this time, we only need to pass the DTO with only 5 properties to the client. If this object is used to correspond to the display object of the interface, then it The identity will be changed to VO.

There are two advantages of using DTO, one is to avoid passing too much useless data and improve the data transmission speed; the other is to hide the back-end table structure. The common usage is: assemble the requested data or attributes into a RequestDTO, and then assemble the response data or attributes into a ResponseDTO.

POJO

POJO (Plain Ordinary Java Object) simple Java object, is actually ordinary JavaBeans, which is an abbreviation created to avoid confusion with EJB (Enterprise JavaBean).

POJO can essentially be understood as a simple entity class, whereA class with some properties and their getter and setter methods, no business logic, no business methods, and no methods such as connection

POJO is the most flexible object in the JavaEE world. In a simple system, if it is POJO from database to page display, it can be DTO; if it is POJO from database to business processing, it can be BO; if From the database to the display of the entire page, it can also be VO.

Further reading:

In actual projects, we will also encounter a common object, which is the Entity object, which corresponds to a table in the database. We can simply understand that a table corresponds to an Entity. Also take the transaction order table Order as an example. If the table has 25 fields, then the OrderEntity object also contains 25 corresponding properties.

Extension: Differences and connections between objects

The following is from: https://www.jianshu.com/p/ccdbef3ec75f

The difference between VO and DTO

Since DTO is the object that transfers data between the presentation layer and the service layer, why do you need a VO? right! For most application scenarios, the attribute values ​​of DTO and VO are basically the same, and they are usually POJOs, 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, the concept There should still be VO and DTO, because there are essential differences between the two. DTO represents the data that the service layer needs to receive and returns, and VO represents the data that the display layer needs to display.

It might be easier to understand with an example:

For example, the Service layer has a getUser method that returns a system user, one of which is gender (gender). For the Service layer, it is only defined semantically: 1-male, 2-female, 0-unspecified, and For the presentation layer, it might need to use "handsome" for male, "beautiful" for female, and "secret" for unspecified. Having said that, you may also refute, wouldn't it be enough to just return "handsome guys and beauties" at the service level? For most applications, this is not a problem, but imagine if the requirements allow customers to customize styles, and different styles represent "gender" differently, or if the service is used by multiple clients at the same time (different portals) ), and different clients have different requirements for the presentation layer, then the problem comes. Furthermore, returning to the analysis at the design level, from the point of view 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 returned by it should not be coupled with the form of expression.
Theory belongs to theory. In the end, this is still thinking at the level of analysis and design. Is it necessary to do so at the level of implementation? A one-size-fits-all approach is often not worth the loss. I will analyze the application immediately below.

Application of VO and DTO

When the demand is very clear and stable, and the client clearly has only one, there is no need to distinguish VO from DTO. At this time, VO can be retired, and only one DTO can be used. Why is VO retired instead of DTO? Back to the design level, the responsibilities of the Service layer should still not be coupled with the View layer. Therefore, for the previous example, you can easily understand that DTO still cannot use "Beauty" for "gender". This conversion should depend on Scripting (such as JavaScript) or other mechanisms (JSTL, EL, CSS) of the page
even if the client can be customized, or there are multiple different clients, if the client can use some technology (scripting or other mechanism) to achieve the transformation, It can also make VO retreat

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

For some technical reasons, for example, when a framework (such as Flex) provides automatic conversion of POJOs to some Fields in the UI, you can consider defining VO at the implementation level. This trade-off depends entirely on the automatic conversion capabilities of the framework. The comparison between the improvement of development and maintenance efficiency and the reduction of development and maintenance efficiency caused by the extra work done by designing one more VO.

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 the service layer providing a DTO that returns a large view at one time, 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

The first is the conceptual difference. DTO is the data transfer object between the View layer and the Service layer (which can be considered as the agreement between the two), while DO is the abstraction of various business roles in the real world, which leads to two The difference in data between users, such as UserInfo and User (for the naming rules of DTO and DO, see the author's previous blog post), for a getUser method, it should never return the user's password in essence, so UserInfo At least one password less data than User. And in Domain Driven Design, as the first article in the series said, DO is not a simple POJO, it has domain business logic.

Application of DTO and DO

From the example in the previous section, careful readers may find the problem: since the UserInfo returned by the getUser method should not contain password, there should be no password attribute definition, but if there is a createUser method at the same time, the incoming UserInfo Need to include the user's password, what should I do? At the design level, the DTO passed by the View layer to the Service layer is conceptually different from the DTO returned by the Service layer to the View layer, but at the implementation level, we usually rarely do this (define two UserInfos, or even more) , because it is not very wise to do so, we can design a fully compatible DTO. When the service layer receives data, the properties that should not be set by the View layer (such as the total price of the order should be determined by its unit price, quantity, discount) etc.), regardless of whether the View layer is set, the Service layer will ignore it, and when the Service layer returns data, the corresponding properties will not be set for the data that should not be returned (such as user passwords).

For DO, one more point needs to be explained: why not return DO directly in the Service layer? This saves the work of encoding and converting DTOs for the following reasons:

The essential difference between the two may lead to a one-to-one correspondence with each other. One DTO may correspond to multiple DOs, and vice versa, and even there is a many-to-many relationship between the two.
DO has some data that the View layer should not know. DO has business methods. If the DO is directly passed to the View layer, the code of the View layer can bypass the Service layer and directly call operations that it should not access. For intercepting the Service layer based on AOP For the mechanism of access control, this problem is particularly prominent, and the business method of calling DO in the View layer will also make the transaction difficult to control because of the transaction problem.
For some ORM frameworks (such as hibernate), the "lazy loading" technology is usually used. If the DO is directly exposed to the View layer, for most cases, the View layer is not within the scope of the transaction (Open session in view is in most cases. case is not a worthy design), if it tries to get an unloaded associated object while the Session is closed, a runtime exception (for Hibernate, LazyInitiliaztionException) will occur.
From a design perspective, the View layer depends on the Service layer, and the Service layer depends on the domain layer. If the DO is exposed, the View layer will directly depend on the dao layer. Although this is still a one-way dependency, this cross-layer Dependencies can lead to unnecessary coupling.
For DTO, it is also necessary to explain that DTO should be a "flat two-dimensional object"
For example, if User is associated with several other entities (such as Address, Account, Region, etc.), does the UserInfo returned by getUser() need to return all the DTOs of the 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 due to the transmission, serialization and deserialization of data on the network. If getUser needs to return an AccountId, AccountName, RegionId, RegionName in addition to the basic information of the User, then please define these attributes in UserInfo, and "squeeze" a "stereo" object tree into a "flat" The two-dimensional object", the project the author is currently involved in is a distributed system, which converts all the associated objects of an object into a DTO object tree of the same structure and returns them, regardless of the three-seven-two-one, resulting in very slow performance. .

The difference between DO and PO

DO and PO are in one-to-one correspondence in most cases. PO is a POJO with only get/set methods, but some scenarios can still reflect the essential difference between the two concepts:

DO does not require explicit persistence in some scenarios. For example, the commodity discount strategy designed by using the strategy pattern will derive the interface of the discount strategy and different discount strategy implementation classes. These discount strategy implementation classes can be regarded as DO, but they It only resides in static memory and does not need to be persisted to the persistence layer. Therefore, there is no corresponding PO for this type of DO.

In the same way, 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 TeacherAndStudentPO The PO, but this PO has no practical significance in the business field, and it cannot correspond to any DO at all.

It should be specially stated here that not all many-to-many relationships have business meanings, which are related to specific business scenarios. For example, the relationship between two POs will affect specific businesses, and there are multiple types of this relationship. A many-to-many relationship should also be expressed as a DO. Another example: there is a many-to-many relationship between "role" and "resource", and this relationship will obviously be expressed as a DO - "authority".

In some cases, for a certain persistence strategy or performance considerations, a PO may correspond to multiple DOs, and vice versa. For example, the customer Customer has its contact information Contacts, here are two DOs of one-to-one relationship, but it may be out of performance considerations (extreme cases, right as an example), in order to reduce the connection query operation of the database, the Customer and Contacts two DO data is combined into one data table. Conversely, if a book Book has an attribute of cover, but this attribute is the binary data of a picture, and some query operations do not want to load the cover together, thus reducing the disk IO overhead, and assuming the ORM framework If attribute-level lazy loading is not supported, then you need to consider separate covers into a data table, so that a DO corresponds to a PO.

Some attribute values ​​of PO have no meaning to DO. These attribute values ​​may be data that exists to solve some persistence strategies. For example, in order to implement "optimistic locking", PO has a version attribute, which is for DO. It doesn't make any business sense and it shouldn't exist in DO. Similarly, there may also be properties in DO that do not need to be persisted.

Application of DO and PO

Because 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 completely hidden in DO through JPA, Hibernate Annotations/hbm. Nonetheless, there are some issues we must 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, you can use @Transient declaration.

For the attribute in PO that exists for a certain persistence strategy, such as version, because DO and PO are merged, it must be declared in DO, but because this attribute has no business meaning to DO, it needs to be hidden from the outside world. , the most common practice is to privatize the get/set method of the property, and even not provide the get/set method, but for Hibernate, this needs special attention, because Hibernate reads data from the database and converts it to DO. The reflection mechanism first calls the empty parameter constructor of DO to construct a DO instance, and then uses the JavaBean specification to reflect the set method to set the value for each property. If the set method is not explicitly declared, or the set method is set to private, it will cause Hibernate cannot initialize DO, resulting in a runtime exception. The feasible approach is to set the property's set method to protected.

Hibernate provides good support for scenarios where one DO corresponds to multiple POs, or one PO corresponds to multiple DOs, as well as property-level lazy loading. Please refer to Hibernate's related materials.

Guess you like

Origin blog.csdn.net/weixin_45525272/article/details/123438712