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的差异化

  1. 入参规范

DTO以服务商身份面对用户,VO又以用户身份直面前端

1. 参数命名规则不一(驼峰、下划线)
2. VO操作空间大,可对字段类型格式或命名转换(使用@JsonProperty接收转换参数命名),或者判空等额外操作,DTO只负责源数据格式传输
  1. 时间格式

DTO可以只有Date的源类型,VO面向不同前端呈现多种格式

1. Long类型时间戳(时区)
2. String类型字符串时间(YYYY-MM-dd HH:mm:ss)
3. Date类型时间
4. VO层出入参对时间有控制权,在跟DTO交互前后可以是多种格式(Date、Long、String)
  1. 枚举使用

可以在DTO中使用,不能出现在VO中

1. 在真实业务中,存在大量状态参数
2. 使用枚举对象作为DTO属性,限制入参的上下界限,给定范围
3. 增加容错,提高健壮性,规避不必要的SQL执行,节省资源
  1. 多表操作

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>
  1. 使用 like CONCAT 用来做字符串的模糊匹配的拼接,等于 like %xxx%
  2. &gt;=是 >=的写法,同样还有<= &lt;=