5-12 数据模型与接口规范
一、常用数据模型
- VO(controller)
View Object、Value Object
视图对象、值对象
最有争议的模型,规范写法只存在于controller层,因为swagger注解只作用于VO中的属性上
mapper -> service -> controller
优势:高效,无视层级,直接出参
技巧:根据数据展示端(app、web)的实际需求,定义属性 - DTO(service)
Data Transfer Object
数据传输对象
只存在于service层,DTO控制VO入参的风险控制和PO出参的数据保护
原则上只做数据传输,不携带额外信息,比如swagger注解 。
入参:VO -> DTO -> PO
出参:PO -> DTO -> VO - PO(mapper)
Persistent Object
持久化对象、数据库模型
只存在于mapper层,此对象称为最原始的数据模型,跟表字段对应(比如 UserBean)。
入参:VO -> DTO -> PO
出参:PO -> DTO -> VO - BO
Business Object
业务对象
综合的业务对象,包含一个或多个PO(如用户信息、订单信息)、也包含业务所需的额外属性(如 page、rows)。分页查询、多表查询综合数据的场景。
入参:VO -> DTO -> BO
出参:BO -> DTO -> VO / BO -> VO - DO
Domain Object
领域对象
不常用
入参:VO -> DTO -> DO -> PO
二、DTO和VO的差异化
- 入参规范
DTO以服务商身份面对用户,VO又以用户身份直面前端
1. 参数命名规则不一(驼峰、下划线)
2. VO操作空间大,可对字段类型格式或命名转换(使用@JsonProperty接收转换参数命名),或者判空等额外操作,DTO只负责源数据格式传输
- 时间格式
DTO可以只有Date的源类型,VO面向不同前端呈现多种格式
1. Long类型时间戳(时区)
2. String类型字符串时间(YYYY-MM-dd HH:mm:ss)
3. Date类型时间
4. VO层出入参对时间有控制权,在跟DTO交互前后可以是多种格式(Date、Long、String)
- 枚举使用
可以在DTO中使用,不能出现在VO中
1. 在真实业务中,存在大量状态参数
2. 使用枚举对象作为DTO属性,限制入参的上下界限,给定范围
3. 增加容错,提高健壮性,规避不必要的SQL执行,节省资源
- 多表操作
VO只有一个对象作为出入参规范,DTO通常多个对象对应多个PO
三、Mapper.xml新语法学习
以下是一个联表查询的示例:
根据品牌id,查询所有子品牌的集合 (分页)
<select id="getAllCarSubBrands" parameterType="java.lang.Integer" resultType="com.a2j.beans.bo.CarSubBrandPagesBO">
select csb.*,
cb.id as brandId,
cb.name as brandName,
csb.id as subBrandId,
csb.name as subBrandName
from car_brand cb
left join car_sub_brand csb
on cb.id = csb.brand_id
<where>
<if test="brandName != null and brandName != ''">
cb.name like CONCAT('%', #{brandName}, '%')
</if>
<if test="subBrandName != null and subBrandName != ''">
and csb.name like CONCAT('%', #{subBrandName}, '%')
</if>
<if test="sourceType != null">
and csb.source_type = #{sourceType}
</if>
<if test="createTime != null">
and csb.create_time ">>= #{createTime}
</if>
<if test="enable != null">
and csb.enable = #{enable}
</if>
</where>
limit #{page}, #{rows}
</select>
- 使用 like
CONCAT
用来做字符串的模糊匹配的拼接,等于 like %xxx% -
>=
是 >=的写法,同样还有<=<=