Entity与DTO区别及其使用

为什么不能直接用实体模型实现层与层传递?

DTO(Data Tansfer Object)即数据传输对象。不明白有些框架中为什么要专门定义DTO来绑定表现层中的数据,为什么不能直接用实体模型实现层与层之间的数据传输,有了DTO同时还要维护DTO与Model之间的映射关系与转换?

表现层与应用层之间是通过数据传输对象(DTO)进行交互的,数据传输对象是没有行为的POJO对象,它 的目的只是为了对领域对象进行数据封装,实现层与层之间的数据传递。为何不能直接将领域对象用于 数据传递?因为领域对象更注重领域,而DTO更注重数据。不仅如此,由于“富领域模型”的特点,这样做会直接将领域对象的行为暴露给表现层。

需要了解的是,数据传输对象DTO本身并不是业务对象。数据传输对象是根据UI的需求进行设计的,而不 是根据领域对象进行设计的。比如,Customer领域对象可能会包含一些诸如FirstName, LastName, Email, Address等信息。但如果UI上不打算显示Address的信息,那么CustomerDTO中也无需包含这个Address的数据。

简单来说Model面向业务,我们是通过业务来定义Model的。而DTO是面向界面UI,是通过UI的需求来定义的。通过DTO我们实现了表现层与Model之间的解耦,表现层不引用Model,如果开发过程中我们的模型改变了,而界面没变,我们就只需要改Model而不需要去改表现层中的东西。

为什么要用DTO

这里是列表文本

  • JavaEE各层之间解耦,这是从设计角度来说的。也就是说Domain Object(PO)直接封死在Dao层。高内聚,低耦合是我们追求的一个目标。但由于在一般的应用中大量的PO,VO转换,增加了工作量,也有些人说是过度设计。
  • 这里是列表文本隔离变化。当在一些大型的应用场景以及Domain经常变化的系统里,View层可以只关注DTO对象,不用关心Domain层PO对象,如hibernate entity的不断变化。
  • 这里是列表文本利于发挥个人技术特长,特别是按层来分工开发的团队。如有人专注于Web层,只做SpringMVC和界面这部分。还有人专门做Spring和Hibernate部分。两组的开发人员定义好接口数据就行,也就是DTO(VO)。我们当时做的电子商务网站就是这样的。
  • 这里是列表文本当系统发展大后,扩展成各种前端界面后,可以有效隔离核心应用层。如又有web界面,又有swing的cs界面,又有手机客户端。
  • 这里是列表文本当分层部署时,也就是Web层(jsp,Struts2)和App层(Spring,dao)在不同机器上时,用Remote协议通迅,DTO是必需的。如处理hibernate lazy load和序列化等问题。在电子商务应用中分层部署的主要好处是减少各层负载量,提高性能。
  • 这里是列表文本在一些特定场景,如需要防火墙的地方,需要把核心数据层(Service,Dao,DB)放在防火墙内。

JPA的OTD使用方式

假设有一个DTO,其属性包括两张表的属性,需要将sql语句查询得到的内容转为一个DTO对象,其解决方法如下:

方法一:

SQLQuery query = session.createSQLQuery("select a.id as areaId,a.name as areaName,c.id as screenId,c.name as screenName from HPS_ParkingLotArea a left join HPS_ParkingLotScreen c on a.screenId = c.id ");
List list = query
.addScalar("areaId",Hibernate.INTEGER)
.addScalar("areaName",Hibernate.STRING)
.addScalar("screenId",Hibernate.INTEGER)
.addScalar("screenName",Hibernate.STRING)
.setResultTransformer(Transformers.aliasToBean(AreaWithScreen.class)).list();
return list;

在执行完sql语句之后,取到相应的属性,并赋予其类型,最后借助aliasToBean来转化为相应的类的实例。(此类无需有其他构造方法)

方法二:

Query q = session.createQuery("select new com.hibernate.MsgInfo(m.id, m.cont, m.topic.title, m.topic.category.name) from Msg m");  
List<MsgInfo> list=q.list();  

其中,MsgInfo是DTO。值得留意的是,第二种方法中DTO必须提供带参数的构造方法,并且HQL语句中属性的位置要与构造方法中的位置逐一对应。

对于DTO对象要注意,是int还是Integer。如果是int,但set方法中的方法也是int,则如果为空,会报错。

参考博客

DTO与实体对象的区别:http://blog.csdn.net/wzhjdls/article/details/26938909

生成DTO的两种方式:http://blog.csdn.net/angus_17/article/details/8500103

猜你喜欢

转载自my.oschina.net/u/1033181/blog/1573923