java善假于物(五):ModelMapper实体间快速赋值

前言

ModelMapper是一个从对象到对象(object-to-object)的框架,能将Java Bean(Pojo)对象从一种表现形式转化为另一种表现形式。它采用“通过约定来配置”的方式,自动匹配不同的对象映射,同时具备满足某些特殊需求的高级功能。

参考地址:https://github.com/bigbeef/cppba-modelmapper
开源地址:https://github.com/bigbeef
个人博客:http://blog.cppba.com

在实际开发中,我们遇到过这样的问题:
我们数据库有这样两张表User和City,映射的实体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class User {
private Long id;
private String userName;
private String password;
private Integer gender;//0-未知,1-男,2-女
private Long cityId;
//省去getter setter tostring constructor
}
public class City {
private Long id;
private String name;
private Long parentId;
//省去getter setter tostring constructor
}

我们的restful API有这样一个接口(/user/getInfo),大家想一想我们的接口返回是什么?

1
2
3
4
5
6
public class UserVo {
private Long id;
private String UserName;
private String cityName;
private String gender;
}

假如我们返回这样一个实体,我们应该怎么去生成这个实体呢?
一般人是这么做的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Main {
public static String[] genders={"男","女","未知"};
public static void main(String[] args) {
//模拟数据库查询出来的数据
User user = new User(1L,"jack","123456",1,2L);
City city = new City(2L,"重庆",0L);
UserVo userVo = new UserVo();
userVo.setUserName(user.getUserName());
userVo.setId(user.getId());
userVo.setCityName(city.getName());
userVo.setGender(genders[user.getGender()]);
}
}

这种办法虽然能实现,但是如果UserVO有100个属性怎么办,一个一个set不是会设置到天荒地老?

接下来给大家介绍一个第三方jar包modelmapper,看看他的神器。

引入maven

1
2
3
4
5
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>0.7.7</version>
</dependency>

改造UserVo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class UserVo {
private Long id;
private String UserName;
private String cityName;
private String gender;
public static String[] genders={"男","女","未知"};
/**
* User转UserVo自定义映射规则
*/
public static PropertyMap<User, UserVo> UserToUserVoMap = new PropertyMap<User, UserVo>() {
protected void configure() {
using(toGender).map(source.getGender(),destination.getGender());
}
};
/**
* 自定义转换规则,将int的genderId翻译为String类型的gender,如1-->"女"
*/
public static Converter<Integer, String> toGender = new AbstractConverter<Integer, String>() {
protected String convert(Integer genderId) {
return genders[genderId];
}
};
/**
* City转UserVo自定义映射规则
*/
public static PropertyMap<City, UserVo> CityToUserVoMap = new PropertyMap<City, UserVo>() {
protected void configure() {
map(source.getName(),destination.getCityName());
}
};
}

编写测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Main {
public static void main(String[] args) {
//模拟数据库查询出来的数据
User user = new User(1L,"jack","123456",1,2L);
City city = new City(2L,"重庆",0L);
System.out.println(user.toString());
System.out.println(city.toString());
ModelMapper modelMapper = new ModelMapper();
modelMapper.addMappings(UserVo.UserToUserVoMap);
modelMapper.addMappings(UserVo.CityToUserVoMap);
UserVo userVo =modelMapper.map(city,UserVo.class);
modelMapper.map(user,userVo);
System.out.println(userVo.toString());
}
}

运行结果

注意

如果user转userVO时,两个类属性名都相同,就没必要写自定义映射规则。

如果VO属性很多,也不用像传统一样傻傻的一个一个赋值,因为属性名相同占多数,属性名不相同才需要自定义映射规则。