pigx开发示范之旅:客户模块开发

本文在

//www.greatytc.com/p/d614ac030e7c: 在pigx-visual之外构建微服务

//www.greatytc.com/p/353793d668ab: pigx数据库操作示例

//www.greatytc.com/p/bd81ad89035a:pigx开发示范之旅:项目规划

基础上开始,本模块主要示范多对多的开发。

一、用 代码生成工具 生成客户模块相关表文件

客户模块涉及三张表,cst_customer、bas_qualification、cst_customer_qualification

其中:cst_customer、cst_customer_qualification属于customer模块,bas_qualification属于base模块,它们分别对应目录结构中的customer及base目录。

生成三张表的文件后,将生成的后端代码复制到相应目录,注意还有mpper.xml文件。

二、修改 实体 类

由于表的主键采用UUID,所以需要修改实体类的Id属性,如下

原来为:

@TableId

private Stringid;

改为:

@TableId(value="id",type=IdType.UUID)

private Stringid;

这里只修改customer、qualification实体

三、客户模块功能设计

实现客户的增删改查

增加实现客户和客户的资质一起增加,即客户表和客户的资质表一起保存,增加是时,如果客户id、客户名称已存在,则提示:客户已存在,保存失败!

删除实现客户和客户的资质一起删除

修改实现客户和客户的资质一起修改,如果修改后的客户名称已存在,则提示:客户名称重复,更新失败!

查询实现按关键字匹配客户名称、资质名称,同时资质表在前端作为下拉查询条件匹配资质名称

四、值对象设计

从需求来看,客户对象包含客户资质对象,在customer实体中只有cst_customer表的字段属性,由于customer实体是自动生成的,考虑需求变化对表结构的影响,因此不在customer实体中添加对客户资质对象的引用,单独建立一个值对象CustomerVO来负责与前端交互,增删改查操作的对象都将是CustomerVO。

package com.mycompany.mydemo.customer.vo;

import com.mycompany.mydemo.base.entity.Qualification;

import lombok.Data;

import java.io.Serializable;

import java.util.List;

@Data

public class CustomerVO  implements Serializable {

    private static final long serialVersionUID = 1L;

    /**

    * 主键

    */

    private String id;

    /**

    * 客户名称

    */

    private String name;

    /**

    * 资质列表

    */

    private List<Qualification> qualificationList;

}

在客户查询这个需求上,有两个查询条件,一个是关键字、另一个是资质名称,在前端会以对象的形式传到后端,因此后端需要一个对象接收,为保持单一性,特建立一个CustomerRVO的类来接收前端的查询条件数据。

package com.mycompany.mydemo.customer.vo;

import lombok.Data;

import java.io.Serializable;

/**

* 查询客户的查询条件VO

*/

@Data

public class CustomerRVO  implements Serializable {

    private static final long serialVersionUID = 1L;

    /**

    * 关键字

    */

    private String keyWord;

    /**

    * 资质名称

    */

    private String qualificationName;

}

五、Service与Controller设计

在生成的代码中,已有三张表的Service、Controller,但在项目中,从前端操作来看,只会有客户及资质的概念,而客户资质属于客户,因此,对三个Service、Controller的职责做如下界定:

1:接入前端只有CustomerController 和 QualificationController,它们各自负责客户及资质的交互,CustomerQualificationController删除掉。

2:对于CustomerQualificationService,只负责关系表的增删改的操作,并且是批量操作,这些操作由CustomerService调用。

3:Controller只负责中转请求和返回Service执行的结果(包括异常),每一个请求后调用Service的一个方法,Service负责业务规则、业务逻辑的检查、计算及抛出异常,特别注意:如果抛出自定义异常,这个异常类必须继承RuntimeException,不能继承于Exception,否则Controller捕获不到异常,无法将异常消息以R对象的形式返回给前端。

CustomerService示例代码

package com.mycompany.mydemo.customer.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.mycompany.common.exception.BussinessException;

import com.mycompany.mydemo.customer.entity.Customer;

import com.mycompany.mydemo.customer.mapper.CustomerMapper;

import com.mycompany.mydemo.customer.service.CustomerService;

import com.mycompany.mydemo.customer.service.CustomerQualificationService;

import com.mycompany.mydemo.customer.vo.CustomerRVO;

import com.mycompany.mydemo.customer.vo.CustomerVO;

import lombok.AllArgsConstructor;

import lombok.SneakyThrows;

import org.springframework.beans.BeanUtils;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;

import java.util.List;

/**

*

*

* @author pigx code generator

* @date 2019-05-29 14:41:33

*/

@Service

@AllArgsConstructor

public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements CustomerService {

    private final CustomerQualificationService customerQualificationService;

    //region 自定义的方法块

    /**

    * 按关键字查询客户

    * @param keyWord

    * @return

    */

    @SneakyThrows

    public List<CustomerVO> getCustomerListByKeyWord(String keyWord){

        return baseMapper.getCustomerListByKeyWord(keyWord);

    }

    /**

    * 查询客户列表

    * @param customerRVO

    * @return

    */

    @SneakyThrows

    public List<CustomerVO> getCustomerList(CustomerRVO customerRVO){

        return baseMapper.getCustomerList(customerRVO);

    }

    /**

    * 新增客户及客户资质

    * @param customerVO

    * @return

    */

    @SneakyThrows

    @Transactional(rollbackFor = Exception.class)

    public boolean addCustomer(CustomerVO customerVO) {

        if (baseMapper.selectById(customerVO.getId()) != null){

            throw new BussinessException("客户已存在,保存失败!");

        }

        Customer customer = new Customer();

        //复制属性值

        BeanUtils.copyProperties(customerVO, customer);

        baseMapper.insert(customer);

        //保存客户资质表

        return customerQualificationService.saveCustomerQualification(customerVO);

    }

    /**

    * 更新客户及客户资质

    * @param customerVO

    * @return

    */

    @SneakyThrows

    @Transactional(rollbackFor = Exception.class)

    public boolean updateCustomer(CustomerVO customerVO) {

        Customer customer = baseMapper.selectById(customerVO.getId());

        if (customer == null) {

            throw new BussinessException("客户不存在,更新失败!");

        }

        //复制属性值

        BeanUtils.copyProperties(customerVO, customer);

        baseMapper.updateById(customer);

        //保存客户资质表

        return customerQualificationService.saveCustomerQualification(customerVO);

    }

    //endregion

    //region 重载基类的方法块

    /**

    * 按 Id 删除客户及客户资质

    * @param id

    * @return

    */

    @Override

    @SneakyThrows

    @Transactional(rollbackFor = Exception.class)

    public boolean removeById(Serializable id){

        //删除客户资质

        customerQualificationService.deleteByCustomerId(id);

        return super.removeById(id);

    }

    //endregion

}

CustomerQualificationService示例

package com.mycompany.mydemo.customer.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.mycompany.mydemo.customer.entity.CustomerQualification;

import com.mycompany.mydemo.customer.mapper.CustomerQualificationMapper;

import com.mycompany.mydemo.customer.service.CustomerQualificationService;

import com.mycompany.mydemo.customer.vo.CustomerVO;

import org.springframework.stereotype.Service;

import java.io.Serializable;

import java.util.List;

import java.util.stream.Collectors;

/**

*

*

* @author pigx code generator

* @date 2019-05-29 15:02:09

*/

@Service

public class CustomerQualificationServiceImpl extends ServiceImpl<CustomerQualificationMapper, CustomerQualification> implements CustomerQualificationService {

    //region 自定义的方法块

    /**

    * 保存客户资质

    * @param customerVO

    * @return

    */

    public boolean saveCustomerQualification(CustomerVO customerVO){

        //先删除再添加

        this.deleteByCustomerId(customerVO.getId());

        //保存客户资质表

        List<CustomerQualification> customerQualificationList = customerVO.getQualificationList()

                .stream().map(qualification -> {

                    CustomerQualification customerQualification = new CustomerQualification();

                    customerQualification.setCustomerId(customerVO.getId());

                    customerQualification.setQualificationId(qualification.getId());

                    return customerQualification;

                }).collect(Collectors.toList());

        return this.saveBatch(customerQualificationList);

    }

    /**

    * 按客户Id 删除客户资质

    * @param customerId

    * @return

    */

    public boolean deleteByCustomerId(Serializable customerId){

        return baseMapper.deleteByCustomerId(customerId);

    }

    //endregion

}

六、Mapper映射

CustomerMapper.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.mycompany.mydemo.customer.mapper.CustomerMapper">

    <resultMap id="customerVoMap" type="com.mycompany.mydemo.customer.vo.CustomerVO">

        <id property="id" column="id"/>

        <result property="name" column="name"/>

        <collection property="qualificationList" ofType="com.mycompany.mydemo.base.entity.Qualification">

            <id property="id" column="qualification_id"/>

            <result property="name" column="qualification_name"/>

        </collection>

    </resultMap>

    <sql id="customerQualificationSql">

        select ta.id, ta.name, tc.id as qualification_id, tc.name as qualification_name

        from cst_customer as ta

        left join cst_customer_qualification as tb on ta.id = tb.customer_id

        left join bas_qualification as tc on tb.qualification_id = tc.id

    </sql>

    <select id="getCustomerListByKeyWord" resultMap="customerVoMap">

        <include refid="customerQualificationSql"/>

        where ta.name LIKE CONCAT('%',#{keyWord},'%') or tc.name LIKE CONCAT('%',#{keyWord},'%')

    </select>

    <select id="getCustomerList" resultMap="customerVoMap">

        <include refid="customerQualificationSql"/>

        <where>

            <if test="query.keyWord != null and query.keyWord != ''">

                and ta.name LIKE CONCAT('%',#{query.keyWord},'%') or tc.name LIKE CONCAT('%',#{query.keyWord},'%')

            </if>

            <if test="query.qualificationName != null and query.qualificationName != ''">

                and tc.name = #{query.qualificationName}

            </if>

        </where>

    </select>

</mapper>

CustomerQualificationMapper.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.mycompany.mydemo.customer.mapper.CustomerQualificationMapper">

    <resultMap id="customerQualificationMap" type="com.mycompany.mydemo.customer.entity.CustomerQualification">

        <result property="customerId" column="customer_id"/>

        <result property="qualificationId" column="qualification_id"/>

    </resultMap>

    <!--根据客户Id删除该客户的资质关系-->

    <delete id="deleteByCustomerId">

DELETE FROM cst_customer_qualification WHERE customer_id = #{customerId}

</delete>

</mapper>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,376评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,126评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,966评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,432评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,519评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,792评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,933评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,701评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,143评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,488评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,626评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,292评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,896评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,494评论 2 348