How does SpringBoot practice object replication _java_ Scripting Home

How does SpringBoot practice object replication

Updated: Sep 24, 2021 09:40:25 Author: Ethereal Jam
This article mainly introduces how to copy the SpringBoot object, the article introduces very detailed through the example code, has a certain reference value, interested partners can refer to it

First of all, why do we need object copying?

Why do I need object replication

image-20210906145134173

As above, it is the most common three-layer MVC architecture model in our usual development. During the editing operation, the Controller layer receives the DTO object from the front end, and the Service layer needs to convert the DTO to DO, and then save it in the database. During the query operation, after the Service layer queries the DO object, it needs to convert the DO object into a VO object, and then return the DO object to the front-end through the Controller layer for rendering.

There's a lot of object conversion involved, and obviously we can't just copy object properties using getters/setters, it's too low. Imagine your business logic is flooded with getters & setters. How will the old timers laugh at you during code review?

image-20210716084136689

So we had to find a third-party tool to help us with object conversion.

Seeing this, some students may ask, why can't we use DO objects uniformly on both the front and back ends? So there is no object conversion?

Imagine if instead of defining Dtos and VOs, we use DO directly on the data access layer, service layer, control layer, and external access interface. In this case, if a field is deleted or modified in the table, DO must be modified synchronously. This modification affects all layers, which does not comply with the principle of high cohesion and low coupling. By defining different Dtos, you can control the exposure of different attributes to different systems, and you can also hide specific field names through attribute mapping. Different services use different models. When a business changes and needs to modify fields, it is not necessary to consider the impact on other services. If the same object is used, many inelegant compatibility behaviors may occur because of "dare not change".

Recommended object copy tool class

There are many class library tools for object copying, in addition to the common Apache BeanUtils, Spring BeanUtils, Cglib BeanCopier, and heavyweight components MapStruct, Orika, Dozer, ModelMapper, etc.

All of these utility classes can be used without special requirements, except for Apache's BeanUtils. The reason is that in order to pursue perfection, the underlying source code of Apache BeanUtils adds too much packaging, uses a lot of reflection, and does a lot of verification, so the performance is poor, and it is mandatory to avoid using Apache BeanUtils in the Alibaba development manual.

强制规定避免使用 Apache BeanUtils

For the rest of the heavyweight components, I recommend Orika for performance and ease of use. Orika uses the javassist class library underneath to generate the bytecode of the Bean map, and then directly loads and executes the resulting bytecode file, which is much faster than using reflection for assignment.

Great god baeldung abroad has carried out detailed tests the performance of common components, you can be at https://www.baeldung.com/java-performance-mapping-frameworks.

Orika basic use

To use Orika is as simple as four simple steps:

Introduce dependency

<dependency>
  <groupId>ma.glasnost.orika</groupId>
  <artifactId>orika-core</artifactId>
  <version>1.5.4</version>
</dependency>

Construct a MapperFactory

MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();  

Registration field mapping

mapperFactory.classMap(SourceClass.class, TargetClass.class)  
   .field("firstName", "givenName")
   .field("lastName", "sirName")
   .byDefault()
   .register();

When the field name is inconsistent between two entities, it can be mapped by the.field() method. If the field name is the same, it can be omitted. The byDefault() method is used to register attributes with the same name.

mapping

MapperFacade mapper = mapperFactory.getMapperFacade();

SourceClass source = new SourceClass();  
// set some field values
...
// map the fields of 'source' onto a new instance of PersonDest
TargetClass target = mapper.map(source, TargetClass.class);  

With the above four steps we have completed the conversion of SourceClass to TargetClass. Other ways to use Orika can be found at http://orika-mapper.github.io/orika-docs/index.html

Seeing here, there must be fans who will say: What do you recommend, this Orika is not simple to use, every time you have to create a MapperFactory, establish a field mapping relationship, in order to map the transformation.

Don't worry, I have prepared a tool class OrikaUtils for you, you can get through the github repository at the end of the article.

It provides five public methods:

image-20210903151829872

Corresponding to:

  • Field consistent entity transformation
  • Field inconsistency Entity transformation (requires field mapping)
  • Field consistent set conversion
  • Field inconsistent collection transformation (requires field mapping)
  • Field property conversion registration

Let's focus on the use of this utility class with unit test cases.

Orika tool class usage documentation

First prepare two basic entity classes, Student and Teacher.

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private String id;
    private String name;
    private String email;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
    private String id;
    private String name;
    private String emailAddress;
}

TC1, the underlying entity mapping

/** * Copies only the same property */ @Test public void convertObject(){Student student = new Student("1","javadaily","jianzh5@163.com"); Teacher teacher = OrikaUtils.convert(student, Teacher.class); System.out.println(teacher); }

The output:

Teacher(id=1, name=javadaily, emailAddress=null)

In this case, the field email cannot be mapped because the attribute names are inconsistent.

TC2, Entity mapping - Field transformation

/** * Copy different properties */ @Test public void convertRefObject(){Student student = new Student("1","javadaily","jianzh5@163.com"); Map<String,String> refMap = new HashMap<>(1); refMap.put("email","emailAddress"); //map key places source attributes, value places target attributes; refmap. put("email"," emailaddress "); Teacher teacher = OrikaUtils.convert(student, Teacher.class, refMap); System.out.println(teacher); }

The output:

Teacher(id=1, name=javadaily, emailAddress=jianzh5@163.com)

In this case, because the field is mapped, you can map the email to the emailAddress. Note that in refMap, key places the attribute of the source entity and value places the attribute of the target entity.

TC3, basic set mapping

/** * Copies only the same set of attributes */ @Test public void convertList(){Student student1 = new Student("1","javadaily","jianzh5@163.com"); Student student2 = new Student("2","JAVA Journal ","jianzh5@xxx.com"); List<Student> studentList = Lists.newArrayList(student1,student2); List<Teacher> teacherList = OrikaUtils.convertList(studentList, Teacher.class); System.out.println(teacherList); }

The output:

[Teacher(id=1, name=javadaily, emailAddress=null), Teacher(id=2, name=JAVA Journal, emailAddress=null)]

The field email cannot be mapped in the collection because the attribute names are inconsistent.

TC4, Set mapping - Field mapping

/** * Maps a set of different attributes */ @Test public void convertRefList(){Student student1 = new Student("1","javadaily","jianzh5@163.com"); Student student2 = new Student("2","JAVA Journal ","jianzh5@xxx.com"); List<Student> studentList = Lists.newArrayList(student1,student2); Map<String,String> refMap = new HashMap<>(2); refMap.put("email","emailAddress"); //map key places source attributes, value places target attributes; refmap. put("email"," emailaddress "); List<Teacher> teacherList = OrikaUtils.convertList(studentList, Teacher.class,refMap); System.out.println(teacherList); }

The output:

[Teacher(id=1, name=javadaily, emailAddress=jianzh5@163.com), Teacher(id=2, name=JAVA Journal, emailAddress=jianzh5@xxx.com)]

It can also be mapped like this:

Map<String,String> refMap = new HashMap<>(2);
refMap.put("email","emailAddress");
List<Teacher> teacherList = OrikaUtils.classMap(Student.class,Teacher.class,refMap)
        .mapAsList(studentList,Teacher.class);

TC5, collection and entity mapping

Sometimes we need to map collection data to entities, such as the Person class

@Data
public class Person {
    private List<String> nameParts;
}

Now you need to map the values of the nameParts of the Person class to the Student, which you can do

/** * Mappings between arrays and lists */ @Test public void convertListObject(){Person person = new Person(); person.setNameParts(Lists.newArrayList("1","javadaily","jianzh5@163.com")); Map<String,String> refMap = new HashMap<>(2); refMap.put("nameParts[0]","id"); //map key places source attributes and value places target attributes; refmap. put(" nameparts [0]","id"); refMap.put("nameParts[1]","name"); refMap.put("nameParts[2]","email"); Student student = OrikaUtils.convert(person, Student.class,refMap); System.out.println(student); }

The output:

Student(id=1, name=javadaily, email=jianzh5@163.com)

TC6, class type mapping

Sometimes we need a class type object map, such as the BasicPerson class

@Data
public class BasicPerson {
    private Student student;
}

Now you need to map the BasicPerson to the Teacher

/** * Class type mapping */ @Test public void convertClassObject(){BasicPerson basicPerson = new BasicPerson(); Student student = new Student("1","javadaily","jianzh5@163.com"); basicPerson.setStudent(student); Map<String,String> refMap = new HashMap<>(2); //map key places the source attribute and value places the target attribute refMap.put("student.id","id"); refMap.put("student.name","name"); refMap.put("student.email","emailAddress"); Teacher teacher = OrikaUtils.convert(basicPerson, Teacher.class,refMap); System.out.println(teacher); }

The output:

Teacher(id=1, name=javadaily, emailAddress=jianzh5@163.com)

TC7, multiple mapping

Sometimes we encounter multiple mappings, such as StudentGrade to TeacherGrade

@Data
public class StudentGrade {
    private String studentGradeName;
    private List<Student> studentList;
}

@Data
public class TeacherGrade {
    private String teacherGradeName;
    private List<Teacher> teacherList;
}

This scenario is slightly complicated. The attributes of Student and Teacher have different email fields, so transformation mapping is required. Attributes in StudentGrade and TeacherGrade also need to be mapped.

/** * one-to-many mapping */ @Test public void convertComplexObject(){Student student1 = new Student("1","javadaily","jianzh5@163.com"); Student student2 = new Student("2","JAVA Journal ","jianzh5@xxx.com"); List<Student> studentList = Lists.newArrayList(student1,student2); StudentGrade studentGrade = new StudentGrade(); StudentGrade. SetStudentGradeName (" master "); studentGrade.setStudentList(studentList); Map<String,String> refMap1 = new HashMap<>(1); //map key places source attributes and value places target attributes refMap1.put("email","emailAddress"); OrikaUtils.register(Student.class,Teacher.class,refMap1); Map<String,String> refMap2 = new HashMap<>(2); //map key to place the source attribute and value to place the target attribute refMap2.put("studentGradeName", "teacherGradeName"); refMap2.put("studentList", "teacherList"); TeacherGrade teacherGrade = OrikaUtils.convert(studentGrade,TeacherGrade.class,refMap2); System.out.println(teacherGrade); }

In multiple mapping scenarios, you need to call OrikaUtils.register() to register field mappings.

The output:

TeacherGrade(teacherGradeName= Master, teacherList=[Teacher(id=1, name=javadaily, emailAddress=jianzh5@163.com), Teacher(id=2, name=JAVA Journal, emailAddress=jianzh5@xxx.com)])

TC8, MyBaits plus page mapping

If you are using the mybatis paging component, you can convert it like this

public IPage<UserDTO> selectPage(UserDTO userDTO, Integer pageNo, Integer pageSize) { Page page = new Page<>(pageNo, pageSize); LambdaQueryWrapper<User> query = new LambdaQueryWrapper(); if (StringUtils.isNotBlank(userDTO.getName())) { query.like(User::getKindName,userDTO.getName()); } IPage<User> pageList = page(page,query); Convert SysKind to SysKindDto Map<String,String> refMap = new HashMap<>(3); // Convert syskinddto map < string, string > refmap = new hashmap <>(3); refMap.put("kindName","name"); refMap.put("createBy","createUserName"); refMap.put("createTime","createDate"); return pageList.convert(item -> OrikaUtils.convert(item, UserDTO.class, refMap)); }

Brief summary

In MVC architecture, there must be the need to use object copy, property conversion functions, borrowing Orika components, you can easily achieve these functions. This article encapsulates the tool class on the basis of Orika and further simplifies the operation of Orika. I hope it will be helpful to you.

This article on how to practice SpringBoot object replication is introduced to this article, more related to SpringBoot object replication content please search the previous articles of Script Home or continue to browse the following related articles hope that you will support script home in the future!

Related article

  • SpringMVC自定义类型转换器实现解析

    SpringMVC custom type converter implements parsing

    This article mainly introduces the implementation of SpringMVC custom type converter analysis, the article through the example code is very detailed, for everyone's study or work has a certain reference learning value, need friends can refer to the next
    2019-12-12
  • 值得收藏的SpringBoot 实用的小技巧

    Useful tips for SpringBoot worth bookmarking

    Recently shared some source code, framework design things. I found that everyone's enthusiasm is not particularly high, think about the majority of people should still seriously write code; This time to share a little ground gas: SpringBoot in the use of some tips, the need for friends can refer to
    2018-10-10
  • 实例详解java Struts2的配置与简单案例

    Example details java Struts2 configuration and simple cases

    This article mainly introduces the java Struts2 configuration and simple cases, need friends can refer to the next
    2017-04-04
  • spring+netty服务器搭建的方法

    Method of setting up the spring+netty server

    This article mainly introduces the method of spring+netty server construction, Xiaobian feel very good, now share with you, also give you a reference. Let's take a look
    2018-01-01
  • 浅谈Springboot之于Spring的优势

    A brief discussion on the advantages of Springboot to Spring

    This article mainly introduces the advantages of Springboot in Spring, and briefly describes the problems encountered in Java EE development. It is concise and comprehensive, and the friends who need it can refer to it.
    2017-09-09
  • elasticsearch源码分析index action实现方式

    elasticsearch source code analysis index action implementation

    This article mainly introduces the elasticsearch source code analysis index action implementation, friends in need can draw on the reference, I hope to be helpful, I wish you a lot of progress, early promotion and pay rise
    2022-04-04
  • spring cloud中启动Eureka Server的方法

    How to start Eureka Server in spring cloud

    This article mainly introduces the method of starting Eureka Server in spring cloud, Xiaobian think it is very good, now share with you, but also give you a reference. Let's take a look
    2018-01-01
  • Springboot中项目的属性配置的详细介绍

    This section describes the configuration of project properties in Springboot

    Many times need to use some configuration information, this information may have different configurations in the test environment and production environment, this article mainly introduces the Springboot project property configuration in detail, interested in you can understand
    2022-01-01
  • Java网络编程UDP实现多线程在线聊天

    Java network programming UDP multi-threaded online chat

    This article mainly introduces the Java network programming UDP multi-threaded online chat in detail, the example code is introduced in very detail, has a certain reference value, interested partners can refer to it
    2021-07-07
  • springboot中jsp配置tiles全过程

    The whole process of configuring jsp tiles in springboot

    This article mainly introduces the whole process of jsp configuration tiles in springboot, which has a good reference value and hopes to be helpful to you. If there are mistakes or incomplete areas, please feel free to comment
    2022-10-10

Latest comments