在Java中 VO、 PO、DO、DTO、 BO、 QO、DAO、POJO的概念中介绍过Java中的各类模型概念。
在这里简单再总结一下:html
在平常的项目开发中,
VO
对应于页面上须要显示的数据(表单),DO
对应于数据库中存储的数据(数据表),DTO
对应于除两者以外须要进行传递的数据。前端
不少人可能对VO和DTO并非那么熟悉,相反对DO却比较熟悉,那是由于在不少项目中因为种种缘由咱们只使用了DO,缘由可能有如下几种:java
一、项目过小,对于一种业务实体,封装成一个DO就够了。spring
二、并不熟悉DTO、VO,更不知道他们之间的区别。sql
三、了解DO\DTO\VO之间的区别,可是懒得用。数据库
那么,这里,博主再啰嗦一下为何要引入这么多概念,为何我要建议你们在本身的项目中使用这些实体对象。安全
咱们来看这样一个例子。假如咱们的项目中由User这样一个实体。咱们在建立User表的时候通常包含一下属性:app
针对这个实体,咱们一般须要建立一个DO类,用来封装这个User实体。工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public
class
UserDO {
private
Integer id;
//惟一主键
private
Date createdTime;
//建立时间
private
Date updatedTime;
//最后更新时间
private
String name;
//姓名
private
Integer age;
//年龄
private
String gender;
//性别
private
String address;
//住址
private
String password;
//密码
private
String nickName;
//昵称
private
Date birthday;
//生日
private
String politicalStatus;
//政治面貌,1表示群众,2表示团员,3表示党员,4表示其余,100表示未知
private
Integer companyId;
//公司的ID
private
Integer status;
//数据状态,1表示可用,0表示不可用
//setter and getter
}
|
而后,在代码中,从DAO一直到前端展现,咱们都经过这个UserDO类的对象来进行数据传输。这样作会有什么问题嘛?测试
if/else
的方式来分状况展现。还有不少问题,这这里就不详细介绍了。
可见,使用一个DO从头用到尾(从数据库到前端页面)并非一种好的设计。
对于上面的例子,咱们能够将他设计成如下类。因为模型并不复杂,这里只须要再引入VO就能够了。
UserDO已经和数据库字段一一对应了,这里不须要修改。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public
class
UserDO {
private
Integer id;
//惟一主键
private
Date createdTime;
//建立时间
private
Date updatedTime;
//最后更新时间
private
String name;
//姓名
private
Integer age;
//年龄
private
String gender;
//性别
private
String address;
//住址
private
String password;
//密码
private
String nickName;
//昵称
private
Date birthday;
//生日
private
String education;
//学历
private
String politicalStatus;
//政治面貌,1表示群众,2表示团员,3表示党员,4表示其余,100表示未知
private
Integer companyId;
//公司的ID
private
Integer status;
//数据状态,1表示可用,0表示不可用
//setter and getter
}
|
引入UserVO,用于封装传递到前端须要展现的字段。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public
class
UserVO {
private
Integer id;
//惟一主键
private
String name;
//姓名
private
Integer age;
//年龄
private
String gender;
//性别
private
String address;
//住址
private
String nickName;
//昵称
private
Date birthday;
//生日
private
String education;
//学历
private
String politicalStatus;
//政治面貌,群众、团员、党员等
private
Company company;
//公司
//setter and getter
}
|
UserVO中只包含了展现所须要的字段,并不须要展现的字段在这里不须要包含。
在引入了这个类以后,咱们就可在进行数据库查询的时候使用UserDO,而后再须要传递到前端的时候把DO转换成VO。
看到这里,你可能已经发现,UserDO和UserVO中包含了大量的相同字段。难道真的有必要再单独设计个VO嘛?我能够明确告诉你的是,当你的系统愈来愈大,表中的字段愈来愈多的时候,使用DO\DTO\VO等概念进行分层处理是绝对有好处的。至于如何进行有效的在不一样的实体类间进行转换是我接下来要介绍的。
Dozer 是一个对象转换工具。
Dozer能够在JavaBean到JavaBean之间进行递归数据复制,而且这些JavaBean能够是不一样的复杂的类型。
全部的mapping,Dozer将会很直接的将名称相同的fields进行复制,若是field名不一样,或者有特别的对应要求,则能够在xml中进行定义。
前面咱们介绍的DO\DTO\VO不就是JavaBean嘛。正好可使用Dozer进行转换呀。
除了使用Dozer,固然你还由其余选择:
典型的解决方案就是手动拷贝,弊端很明显,代码中充斥大量Set 和Get方法,真正的业务被埋藏值与值的拷贝之中。
另外一种方案就是使用BeanUtil,但BeanUtil不够很好的灵活性,又时候还不得不手动拷贝。Dozer能够灵活的对对象进行转换,且使用简单。
Dozer 支持的转换类型
Primitive
基本数据类型 , 后面带 Wrapper
是包装类 Complex Type
是复杂类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
• Primitive to Primitive Wrapper
• Primitive to Custom Wrapper
• Primitive Wrapper to Primitive Wrapper
• Primitive to Primitive
• Complex Type to Complex Type
• String to Primitive
• String to Primitive Wrapper
• String to Complex Type
if
the Complex Type contains a String constructor
• String 到复杂类型 , 若是复杂类型包含一个 String 类型的构造器
• String to Map
• Collection to Collection
• Collection to Array
• Map to Complex Type
• Map to Custom Map Type
• Enum to Enum
• Each of these can be mapped to one another: java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp, java.util.Calendar, java.util.GregorianCalendar
• String to any of the supported Date/Calendar Objects.
• Objects containing a toString() method that produces a
long
representing time in (ms) to any supported Date/Calendar object.
|
在pom.xml中增长依赖
1
2
3
4
5
|
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>
5.5
.
1
</version>
</dependency>
|
使用Dozer进行类转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public
class
Main {
public
static
void
main(String[] args) {
DozerBeanMapper mapper =
new
DozerBeanMapper();
UserDO userDO =
new
UserDO();
userDO.setName(
"hollis"
);
userDO.setAddress(
"hz"
);
userDO.setAge(
25
);
userDO.setCompanyId(
1
);
userDO.setBirthday(
new
Date());
userDO.setGender(
"male"
);
userDO.setEducation(
"1"
);
userDO.setNickName(
"hollis"
);
userDO.setPoliticalStatus(
"3"
);
UserVO userVO = (UserVO) mapper.map(userDO, UserVO.
class
);
System.out.println(userVO);
}
}
|
特殊的字段转换
在使用mapper进行转换前,设置一个或多个mapping文件
1
2
3
|
List myMappingFiles =
new
ArrayList();
myMappingFiles.add(
"dozer-mapping.xml"
);
mapper.setMappingFiles(myMappingFiles);
|
配置dozer-mapping.xml文件
数据类型不一致,或者名称不相同或者有级联关系等状况下,能够经过文件dozer-mapping.xml
来进行定制Bean的转换
1
2
3
4
5
6
7
8
9
10
|
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<mappings xmlns=
"http://dozer.sourceforge.net"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://dozer.sourceforge.net
http:
//dozer.sourceforge.net/schema/beanmapping.xsd">
<mapping>
<
class
-a>com.hollis.lab.UserDO</
class
-a>
<
class
-b>com.hollis.lab.UserVO</
class
-b>
</mapping>
</mappings>
|
在pom.xml中增长依赖
1
2
3
4
5
|
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>
5.5
.
1
</version>
</dependency>
|
使用Spring集成dozer
1
2
3
4
5
6
7
8
9
10
11
|
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"
>
<beans>
<bean id=
"baseMapper"
class
=
"org.dozer.spring.DozerBeanMapperFactoryBean"
>
<property name=
"mappingFiles"
>
<list>
<value>classpath:mapping/dozer-mapping.xml</value>
</list>
</property>
</bean>
</beans>
|
使用baseMapper进行Bean的转换
1
2
3
4
5
6
7
8
|
@Autowired
private
Mapper baseMapper;
private
UserVO doToVo(UserDO userDO){
if
(userDO ==
null
)
return
null
;
UserVO vo = baseMapper.map(userDO, UserVO.getClass());
if
(userDO.getCompanyId !=
null
) getCompany(vo);
return
vo;
}
|
经过以上的代码加配置,咱们就实现了从DO转换到VO的部分操做,之因此说是部分操做,是由于咱们在dozer-mapping.xml
并无作多余的配置,只是使用dozer将DO中和VO中共有的属性转换了过来。对于其余的类型不一样或者名称不一样等的转换能够参考官网例子经过设置dozer-mapping.xml
文件来实现。
上面还有一个getCompany()
没有实现。这个方法其实就是经过companyId查询出company实体而后在赋值给UserVO中的company属性。
在使用了dozer以后,咱们能够把UserDO中的部分属性赋值到UserVO中,其实,转化的过程是经过调用UserDO中的getter方法和UserVO中的setter方法来实现的。读者能够作个实验,对于UserVO中的部分属性不写Setter方法看看还能不能把属性值转换过来,博主已经测试过了,是不能的。