解决需求中的 三级联动

  • 2019 年 10 月 3 日
  • 筆記

解决需求中的 三级联动

什么是三级联动

所谓三级,即使三个级别,联动代表这三个级别相互依赖与嵌套,唯有这样才能实现三级联动;

在平时生活中,网上填一些表格时就可以预见到,例如:某某省(一级)某某市(二级)某某区(三级);

看到这里就可以快速理解了吧,这就是所谓id三级联动;

如何实现

其实,解决这个需求并不难,首先,三级代表三个属性,也就意味着,你需要三个属性表,现在我们可以举例电商项目的类型;

比如,商品表里面的属性有 商品id 商品名称 商品类型 这个类型就是三级联动里面的最后一个级别,也可以理解成最终类型表,所以商品类型表关联的就是第三级别表的id;

实现步骤

1.先将三个级别分别创建出三张表,先建出来省级表:

省级表id 省名称`

再建出来市级,现在就要注意啦,因为上面我也提到了,如果想联动,那就务必相互依赖,所以,在市级中有三个字段,分别是:

市级id 省级id 市区名称   

以下就以此类推:

区级表:

区级id 市级id 区域名称

 

小结:从上可见,三张表均有相互嵌套相相互依赖的关系,唯有这样才能实现三级联动;

 

使用规则

因为,三级联动需要链接三张表,所以我们需要建立一个自定义返回类(DTO),或者业务拓展类,在这里还是推荐使用DTO;

直接在dao层下建立一个dto包,这个包均是需要多张表链接查询用的;

值得注意的是,如果是两张表链接,那么就可以不使用DTO的方式去返回结果,只要在Mapper层中对应映射关系即可,但是如果超过两张表,那么就需要额外建类了;

如图:

 

 

 在这个类中无疑就是将查询所需字段,全部填写在里面,前提是一定要添加注释,否则这个类将会很乱;

例如:

package com.qyzn.ogpc.dao.dto;    import com.qyzn.ogpc.dao.entity.OpgcSonarticletype;    import java.util.Date;    public class OpgcArticleQueryByTypeDTO {      //文章类型属性开始 start 。。。      //文章类型      private String sonarticletypeNname;        private Integer articleId;        private String articleHeadline;        private String articeRichtext;        private Integer articeRead;        private Integer articeMode;        private Integer articeEndorse;        private Integer userId;        private Date articePublishtime;      /**       * 第三级表外键对象属性       */      private OpgcSonarticletype sonarticletype;        private String articletypeCover;        private Integer articeCommentnum;        private String articeResource;        private Double articePrice;        private Integer articeRecommend;      //文章类型属性结束 end 。。。        //一级属性开始 start。。。      private Integer articletypeId;        private String articletypeName;      //一级属性结束 end。。。        //二级属性开始 start。。。      private Integer childtypeId;        private Integer parentArticletypeId;        private String childtypeName;      //二级属性结束 end。。。        //三级属性开始 start。。。      private Integer sonarticletypeId;        private String sonarticletypeName;        private Integer parentChildtypeId;      //三级属性结束 end。。。          public String getSonarticletypeNname() {          return sonarticletypeNname;      }        public void setSonarticletypeNname(String sonarticletypeNname) {          this.sonarticletypeNname = sonarticletypeNname;      }        public Integer getArticleId() {          return articleId;      }        public void setArticleId(Integer articleId) {          this.articleId = articleId;      }        public String getArticleHeadline() {          return articleHeadline;      }        public void setArticleHeadline(String articleHeadline) {          this.articleHeadline = articleHeadline;      }        public String getArticeRichtext() {          return articeRichtext;      }        public void setArticeRichtext(String articeRichtext) {          this.articeRichtext = articeRichtext;      }        public Integer getArticeRead() {          return articeRead;      }        public void setArticeRead(Integer articeRead) {          this.articeRead = articeRead;      }        public Integer getArticeMode() {          return articeMode;      }        public void setArticeMode(Integer articeMode) {          this.articeMode = articeMode;      }        public Integer getArticeEndorse() {          return articeEndorse;      }        public void setArticeEndorse(Integer articeEndorse) {          this.articeEndorse = articeEndorse;      }        public Integer getUserId() {          return userId;      }        public void setUserId(Integer userId) {          this.userId = userId;      }        public Date getArticePublishtime() {          return articePublishtime;      }        public void setArticePublishtime(Date articePublishtime) {          this.articePublishtime = articePublishtime;      }        public OpgcSonarticletype getSonarticletype() {          return sonarticletype;      }        public void setSonarticletype(OpgcSonarticletype sonarticletype) {          this.sonarticletype = sonarticletype;      }        public String getArticletypeCover() {          return articletypeCover;      }        public void setArticletypeCover(String articletypeCover) {          this.articletypeCover = articletypeCover;      }        public Integer getArticeCommentnum() {          return articeCommentnum;      }        public void setArticeCommentnum(Integer articeCommentnum) {          this.articeCommentnum = articeCommentnum;      }        public String getArticeResource() {          return articeResource;      }        public void setArticeResource(String articeResource) {          this.articeResource = articeResource;      }        public Double getArticePrice() {          return articePrice;      }        public void setArticePrice(Double articePrice) {          this.articePrice = articePrice;      }        public Integer getArticeRecommend() {          return articeRecommend;      }        public void setArticeRecommend(Integer articeRecommend) {          this.articeRecommend = articeRecommend;      }        public Integer getArticletypeId() {          return articletypeId;      }        public void setArticletypeId(Integer articletypeId) {          this.articletypeId = articletypeId;      }        public String getArticletypeName() {          return articletypeName;      }        public void setArticletypeName(String articletypeName) {          this.articletypeName = articletypeName;      }        public Integer getChildtypeId() {          return childtypeId;      }        public void setChildtypeId(Integer childtypeId) {          this.childtypeId = childtypeId;      }        public Integer getParentArticletypeId() {          return parentArticletypeId;      }        public void setParentArticletypeId(Integer parentArticletypeId) {          this.parentArticletypeId = parentArticletypeId;      }        public String getChildtypeName() {          return childtypeName;      }        public void setChildtypeName(String childtypeName) {          this.childtypeName = childtypeName;      }        public Integer getSonarticletypeId() {          return sonarticletypeId;      }        public void setSonarticletypeId(Integer sonarticletypeId) {          this.sonarticletypeId = sonarticletypeId;      }        public String getSonarticletypeName() {          return sonarticletypeName;      }        public void setSonarticletypeName(String sonarticletypeName) {          this.sonarticletypeName = sonarticletypeName;      }        public Integer getParentChildtypeId() {          return parentChildtypeId;      }        public void setParentChildtypeId(Integer parentChildtypeId) {          this.parentChildtypeId = parentChildtypeId;      }        @Override      public String toString() {          return "OpgcArticleQueryByTypeDTO{" +                  "sonarticletypeNname='" + sonarticletypeNname + ''' +                  ", articleId=" + articleId +                  ", articleHeadline='" + articleHeadline + ''' +                  ", articeRichtext='" + articeRichtext + ''' +                  ", articeRead=" + articeRead +                  ", articeMode=" + articeMode +                  ", articeEndorse=" + articeEndorse +                  ", userId=" + userId +                  ", articePublishtime=" + articePublishtime +                  ", sonarticletype=" + sonarticletype +                  ", articletypeCover='" + articletypeCover + ''' +                  ", articeCommentnum=" + articeCommentnum +                  ", articeResource='" + articeResource + ''' +                  ", articePrice=" + articePrice +                  ", articeRecommend=" + articeRecommend +                  ", articletypeId=" + articletypeId +                  ", articletypeName='" + articletypeName + ''' +                  ", childtypeId=" + childtypeId +                  ", parentArticletypeId=" + parentArticletypeId +                  ", childtypeName='" + childtypeName + ''' +                  ", sonarticletypeId=" + sonarticletypeId +                  ", sonarticletypeName='" + sonarticletypeName + ''' +                  ", parentChildtypeId=" + parentChildtypeId +                  '}';      }  }

而在Mapper.xml文件中,需要返回的接口,直接返回DTO的类即可:

    <select id="SelectAllByType" resultType="com.qyzn.ogpc.dao.dto.OpgcArticleQueryByTypeDTO">

接口编写

在接口这边,因为是三级联动,所以呢,我们需要提供三个参数,再配上动态sql去使用,才能达到联动的效果!

先看dao层接口:

/**       * 三级联动查询       * @param articletypeId 属于一级类型id       * @param childtypeId 属于二级类型id       * @param sonarticletypeId 属于 三级类型id       * @return mapper xml层建立返回的 dto 对象,包含的博文[商品]数据、各层级数据       */      List<OpgcArticleQueryByTypeDTO> SelectAllByType(@Param("articletypeId")Integer articletypeId, @Param("childtypeId") Integer childtypeId, @Param("sonarticletypeId")Integer sonarticletypeId);

Service:

/**       * 三级联动查询       * @param articletypeId 属于一级类型id       * @param childtypeId 属于二级类型id       * @param sonarticletypeId 属于 三级类型id       * @return       */      Map<String , Object> SelectAllByType(int articletypeId, int childtypeId, int sonarticletypeId);

impl:

/**       * 三级联动查询       * @param articletypeId 属于一级类型id       * @param childtypeId 属于二级类型id       * @param sonarticletypeId 属于 三级类型id       * @return       */      @Override      public Map<String, Object> SelectAllByType(int articletypeId, int childtypeId, int sonarticletypeId) {          Map<String , Object> map = new ConcurrentHashMap<>();          int code = 200;          String msg = "查询成功";          try {              List<OpgcArticleQueryByTypeDTO> dtos = opgcArticleMapper.SelectAllByType(articletypeId, childtypeId, sonarticletypeId);              map.put("data",dtos);          }catch (Exception e)          {              code = 500;              msg = "查询错误";              e.printStackTrace();              throw new RuntimeException(e);          }finally {              map.put("code",code);              map.put("msg",msg);          }          return map;      }

Controller:

/**       * 现在三级联动查询基本结束,只用建立测试就行       * @param articletypeId 一级 ID       * @param childtypeId 二级 ID       * @param sonarticletypeId 三级 ID       * @return 返回数据结果       */      @ApiOperation(value = "三级联动,建立出返回值的dto类,抽取出共有的属性")      @GetMapping("/SelectAllByType")      public Map<String , Object> SelectAllByType(@RequestParam("articletypeId")Integer articletypeId, @RequestParam("childtypeId") Integer childtypeId, @RequestParam("sonarticletypeId")Integer sonarticletypeId){          return opgcArticleService.SelectAllByType(articletypeId,childtypeId,sonarticletypeId);      };

Mapper.xml:

 <!-- 建立出返回值的 dto 类,抽取出共有的属性,返回值中建立好了列的别名,别名和 dto 的对象属性一致,便直接返回 resultType -->      <select id="SelectAllByType" resultType="com.qyzn.ogpc.dao.dto.OpgcArticleQueryByTypeDTO">          SELECT          q.artice_commentnum articeCommentnum,q.artice_endorse articeEndorse,q.artice_mode articeMode,q.artice_price articePrice,q.artice_publishtime articePublishtime,q.artice_read articeRead,q.artice_recommend articeRecommend,q.artice_resource articeResource,q.artice_richtext articeRichtext,q.article_headline articleHeadline,q.article_id articleId,q.articletype_cover articletypeCover,q.sonarticletype_id articeSonarticletypeId , q.user_id userId,          a.articletype_id articletypeId,a.articletype_name articletypeName,          b.childtype_id childtypeId,b.childtype_name childtypeName,b.articletype_id parentArticletypeId ,          c.sonarticletype_id sonarticletypeId,c.sonarticletype_name sonarticletypeName,c.childtype_id parentChildtypeId          FROM          opgc_article q          left join opgc_sonarticletype c on q.sonarticletype_id = c.sonarticletype_id          left join opgc_childtype b on b.childtype_id = c.childtype_id          left join opgc_articletype a on a.articletype_id = b.childtype_id          where  1 = 1          <if test="articletypeId != null">              and a.articletype_id = #{articletypeId}          </if>          <if test="childtypeId != null">              and b.childtype_id = #{childtypeId}          </if>          <if test="sonarticletypeId != null">              and c.sonarticletype_id = #{sonarticletypeId}          </if>      </select>

根据动态sql的条件,传入三个不同的参数,跟随变化而变化,就此达到了三级联动的目的