Background
We may often transform data between DO, Model, VO layer data:
- Entity corresponds to the data structure of persistence layer (generally the mapping model of database table);
- The Model corresponds to the data structure of the business layer;
- VO is the data structure that the Controller interacts with the client.
For example: the user information (table mapping model) queried from the database is UserDO, but we need to pass it to the client is UserVO. In this case, we need to assign the attributes of the UserDO instance to the UserVO instance one by one.
A large number of attributes may be the same or different between these data structures.
2, Data copy
2.1 data model
- UserDO.jav
@Data
public class UserDO {private Long userId;
private String userName;
private Integer age;
private Integer sex;
public UserDO() {}
public UserDO(Long userId, String userName, Integer age, Integer sex) {
this.userId = userId;
this.userName = userName;
this.age = age;
this.sex = sex;
}
}
public class UserVO {
private Long userId;
private String userName;
private Integer age;
private String sex;
}
Note: the sex type of the last field of UserDO.java and UserVO.java is different, which are Integer/String
2.2. Regular use - bean utils
Spring provides the org.springframework.beans.BeanUtils class for quick assignment.
For example, we copy the UserDO.java found in the database to UserVO.java
@Test
public void commonCopy() {
UserDO userDO = new UserDO(1L, "Van", 18, 1);
UserVO userVO = new UserVO();
BeanUtils.copyProperties(userDO, userVO);
log.info("userVO:{}",userVO);
}
Log printing:
.... userVO:UserVO(userId=1, userName=Van, age=18, sex=null)
By printing the results, we can find that: except for the different types of sex, other values are copied successfully.
2.3. Set copy
What we just copied is an object, but sometimes we want to copy a group of UerDO.java. When it is a collection, we can't assign values directly. If this logic is also followed, it is as follows:
The log is printed as follows:
.... userVOList:[]
Through the log, we can find that the direct copy collection is invalid, so how to solve it?
3, Set copy
3.1 violent copy (not recommended)
Will need to copy the collection traversal, violent copy.
Test method
@Test
public void listCopyCommon() {
List<UserDO> userDOList = new ArrayList();
userDOList.add(new UserDO(1L, "Van", 18, 1));
userDOList.add(new UserDO(2L, "VanVan", 20, 2));
List<UserVO> userVOList = new ArrayList();
userDOList.forEach(userDO ->{
UserVO userVO = new UserVO();
BeanUtils.copyProperties(userDO, userVO);
userVOList.add(userVO);
});
log.info("userVOList:{}",userVOList);
}
- Copy result
.... userVOList:[UserVO(userId=1, userName=Van, age=18, sex=null), UserVO(userId=2, userName=VanVan, age=20, sex=null)]
Although this method can be solved, it is not elegant at all, especially the trouble of writing.
3.2 elegant copy (recommended in this article)
Encapsulate org.springframework.beans.BeanUtils through the functional interface of JDK 8
- Define a functional interface
The default method can be included in the functional interface. Here we define the default callback method.
@FunctionalInterface
public interface BeanCopyUtilCallBack <S, T> {/**
* Define default callback method
* @param t
* @param s
*/
void callBack(S t, T s);
}
- Encapsulate a data copying tool class BeanCopyUtil.java
public class BeanCopyUtil extends BeanUtils {
/**
* Copy of collection data
* @param sources: Data source class
* @param target: Target class:: new(eg: UserVO::new)
* @return
*/
public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target) {
return copyListProperties(sources, target, null);
}
/**
* Copy of collection data with callback function (customizable field copy rule)
* @param sources: Data source class
* @param target: Target class:: new(eg: UserVO::new)
* @param callBack: Callback function
* @return
*/
public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target, BeanCopyUtilCallBack<S, T> callBack) {
List<T> list = new ArrayList<>(sources.size());
for (S source : sources) {
T t = target.get();
copyProperties(source, t);
list.add(t);
if (callBack != null) {
// Callback
callBack.callBack(source, t);
}
}
return list;
}
}
- Simple copy test
@Test
public void listCopyUp() {
List<UserDO> userDOList = new ArrayList();
userDOList.add(new UserDO(1L, "Van", 18, 1));
userDOList.add(new UserDO(2L, "VanVan", 20, 2));
List<UserVO> userVOList = BeanCopyUtil.copyListProperties(userDOList, UserVO::new);
log.info("userVOList:{}",userVOList);
}
Print results:
.... userVOList:[UserVO(userId=1, userName=Van, age=18, sex=null), UserVO(userId=2, userName=VanVan, age=20, sex=null)]
Through the above methods, we basically implement the copy of the collection, but from the returned results we can find that: fields with different properties cannot be copied. Therefore, we need to use the callback method just defined to implement the custom transformation.
- Gender enumeration class
public enum SexEnum {
UNKNOW("Not set up",0),
MEN("Schoolboy", 1),
WOMAN("Girl student",2),;
private String desc;
private int code;SexEnum(String desc, int code) {
this.desc = desc;
this.code = code;
}public static SexEnum getDescByCode(int code) {
SexEnum[] typeEnums = values();
for (SexEnum value : typeEnums) {
if (code == value.getCode()) {
return value;
}
}
return null;
}public String getDesc() {
return desc;
}public void setDesc(String desc) {
this.desc = desc;
}public int getCode() {
return code;
}public void setCode(int code) {
this.code = code;
}
}
- Copy with callback function
@Test
public void listCopyUpWithCallback() {
List<UserDO> userDOList = new ArrayList();
userDOList.add(new UserDO(1L, "Van", 18, 1));
userDOList.add(new UserDO(2L, "VanVan", 20, 2));
List<UserVO> userVOList = BeanCopyUtil.copyListProperties(userDOList, UserVO::new, (userDO, userVO) ->{
// Here you can define specific transformation rules
userVO.setSex(SexEnum.getDescByCode(userDO.getSex()).getDesc());
});
log.info("userVOList:{}",userVOList);
}
Print results:
... userVOList:[UserVO(userId=1, userName=Van, age=18, sex=Schoolboy), UserVO(userId=2, userName=VanVan, age=20, sex=Girl student)]
It can be found from the printing results that the sex of Integer type in UserDO.java is copied to UserVO.java and becomes a boy / girl of String type.
If you want to get learning materials, please comment on [learning] below the comment
By Van Ou fa
Link: https://juejin.im/post/5e1b18b1f265da3e140fa377