基于jeecgboot复杂sql查询的列表自定义列实现

简介: 基于jeecgboot复杂sql查询的列表自定义列实现

      一般简单的sql列表实现,可以通过系统自带的在线开发里的online表单开发实现,但一些复杂的混合多表的实现,同时对需要查询出来的结果进行数据更新,这种复杂的数据列表只能通过我们自己手工实现了。

     下面就举一个出入库的商品选择的例子,这个商品选择的时候需要进行多表联合查询,同时还需要进行库存的更新。

     一、ErpGoodsDto数据结构类

package com.nbcio.modules.erp.goods.dto;
import java.io.Serializable;
import lombok.Data;
@Data
public class ErpGoodsDto implements Serializable {
    private static final long serialVersionUID = 1L;
  /**ID*/
    private java.lang.String id;
    
  /**编号*/
    private java.lang.String code;
    
  /**名称*/
    private java.lang.String name;
    
  /**SPU编号*/
    //private java.lang.String spuId;
    
  /**类别编号*/
    private java.lang.String categoryId;
    
    /**类别名称*/
    private java.lang.String categoryName;
    
  /**品牌编号*/
    private java.lang.String brandId;
    
    /**品牌名称*/
    private java.lang.String brandName;
    
  /**规格*/
    private java.lang.String spec;
    
  /**单位*/
    private java.lang.String unit;
    
    /**采购价格*/
    private java.math.BigDecimal purchasePrice;
    
    /**销售价格*/
    private java.math.BigDecimal salePrice;
    
    /**零售价格*/
    private java.math.BigDecimal retailPrice;
    
    /**税率(%)*/
    private java.math.BigDecimal taxRate;
    
    /**数量*/
    private java.lang.Integer num;
    
    /**总价格*/
    private java.math.BigDecimal totalPrice;
    
    /**库存数量*/
    private java.lang.Integer stockNum;
}

二、ErpGoodsDtoController类

package com.nbcio.modules.erp.goods.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.jeecg.common.api.vo.Result;
import com.nbcio.modules.erp.goods.dto.ErpGoodsDto;
import com.nbcio.modules.erp.goods.service.IErpGoodsDtoService;
import com.nbcio.modules.erp.goods.vo.QueryGoodsVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.aspect.annotation.AutoLog;
 /**
 * @Description: erp_goods_dto
 * @Author: nbacheng
 * @Date:   2023-02-09
 * @Version: V1.0
 */
@Api(tags="erp_goods_dto")
@RestController
@RequestMapping("/goods/erpGoodsDto")
@Slf4j
public class ErpGoodsDtoController extends JeecgController<ErpGoodsDto, IErpGoodsDtoService> {
  @Autowired
  private IErpGoodsDtoService erpGoodsDtoService;
  
  
  /**
   * 分页列表查询
   *
   * @param erpGoods
   * @param pageNo
   * @param pageSize
   * @param req
   * @return
   */
  @AutoLog(value = "erp_goods-商品信息列表查询")
  @ApiOperation(value="erp_goods-商品信息列表查询", notes="erp_goods-商品信息列表查询")
  @GetMapping(value = "/list")
  public Result<?> queryGoodsList(QueryGoodsVo queryGoodsvo,
                   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
                   HttpServletRequest req) {
    Page<ErpGoodsDto> page = new Page<ErpGoodsDto>(pageNo, pageSize);
    IPage<ErpGoodsDto> pageList = erpGoodsDtoService.queryGoodsList(page, queryGoodsvo);
    return Result.OK(pageList);
  }
  
}

三、ErpGoodsDtoMapper 类

package com.nbcio.modules.erp.goods.mapper;
import com.nbcio.modules.erp.goods.dto.ErpGoodsDto;
import com.nbcio.modules.erp.goods.vo.QueryGoodsVo;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
/**
 * @Description: erp_goods_dto
 * @Author: nbacheng
 * @Date:   2023-02-09
 * @Version: V1.0
 */
public interface ErpGoodsDtoMapper extends BaseMapper<ErpGoodsDto> {
   List<ErpGoodsDto> queryGoodsList(Page<ErpGoodsDto> page, @Param("vo") QueryGoodsVo vo);
   public List<ErpGoodsDto> getByIds(@Param("idArray") String[] idArray);
}

四、ErpGoodsDtoMapper.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.nbcio.modules.erp.goods.mapper.ErpGoodsDtoMapper">
  <resultMap id="ErpGoodsDtoMap" type="com.nbcio.modules.erp.goods.dto.ErpGoodsDto">
        <id column="id" property="id"/>
        <result column="code" property="code"/>
        <result column="name" property="name"/>
        <result column="category_id" property="categoryId"/>
        <result column="category_name" property="categoryName"/>
        <result column="brand_id" property="brandId"/>
        <result column="brand_name" property="brandName"/>
        <result column="spec" property="spec"/>
        <result column="unit" property="unit"/>
        <result column="purchase_price" property="purchasePrice"/>
        <result column="sale_price" property="salePrice"/>
        <result column="retail_price" property="retailPrice"/>
        <result column="tax_rate" property="taxRate"/>
        <result column="num" property="num"/>
        <result column="total_price" property="totalPrice"/>
    </resultMap>
    <sql id="ErpGoodsDto_sql">
        SELECT
            a.id,
            a.code,
            a.name,
            c.id AS category_id,
            c.name AS category_name,
            b.id AS brand_id,
            b.name AS brand_name,
            a.spec,
            a.unit,
            price.purchase AS purchase_price,
            price.sale AS sale_price,
            price.retail AS retail_price,
      a.tax_rate,
      1 as num,
      price.sale*1 as total_price
        FROM erp_goods AS a
        LEFT JOIN erp_goods_price AS price ON price.id = a.id
        LEFT JOIN erp_goods_category AS c ON c.id = a.category_id
        LEFT JOIN erp_goods_brand AS b ON b.id = a.brand_id
    </sql>
    <select id="queryGoodsList" resultMap="ErpGoodsDtoMap">
        <include refid="ErpGoodsDto_sql"/>
        <where>
           <if test="vo != null">
              <if test="vo.condition != null and vo.condition != ''">
                  AND (
                  a.id LIKE CONCAT('%', #{vo.condition}, '%')
                  OR a.code LIKE CONCAT('%', #{vo.condition}, '%')
                  OR a.name LIKE CONCAT('%', #{vo.condition}, '%')
                  )
              </if>
              <if test="vo.brandId != null and vo.brandId != ''">
                  AND b.id = #{vo.brandId}
              </if>
              <if test="vo.categoryId != null and vo.categoryId != ''">
                  AND (c.id = #{vo.categoryId} 
              </if>
            </if>
            AND a.status = '1' 
        </where>
        ORDER BY a.code
    </select>
    
    
</mapper>

五、IErpGoodsDtoService类

package com.nbcio.modules.erp.goods.service;
import com.nbcio.modules.erp.goods.dto.ErpGoodsDto;
import com.nbcio.modules.erp.goods.vo.QueryGoodsVo;
import java.util.List;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * @Description: erp_goods_dto
 * @Author: nbacheng
 * @Date:   2023-02-09
 * @Version: V1.0
 */
public interface IErpGoodsDtoService extends IService<ErpGoodsDto> {
  IPage<ErpGoodsDto> queryGoodsList(Page<ErpGoodsDto> page, QueryGoodsVo queryGoodsVo);
}

六、ErpGoodsDtoServiceImpl类

package com.nbcio.modules.erp.goods.service.impl;
import com.nbcio.modules.erp.goods.dto.ErpGoodsDto;
import com.nbcio.modules.erp.goods.mapper.ErpGoodsDtoMapper;
import com.nbcio.modules.erp.goods.service.IErpGoodsDtoService;
import com.nbcio.modules.erp.goods.vo.QueryGoodsVo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
 * @Description: erp_goods
 * @Author: nbacheng
 * @Date:   2022-08-30
 * @Version: V1.0
 */
@Service
public class ErpGoodsDtoServiceImpl extends ServiceImpl<ErpGoodsDtoMapper, ErpGoodsDto> implements IErpGoodsDtoService {
  @Autowired
  private ErpGoodsDtoMapper erpGoodsDtoMapper;
  
  @Override
  public IPage<ErpGoodsDto> queryGoodsList(Page<ErpGoodsDto> page, QueryGoodsVo queryGoodsVo) {
    List<ErpGoodsDto> erpGoodsDtoLists = this.baseMapper.queryGoodsList(page, queryGoodsVo);
        //这里后面还要根据仓库id进行库存数据的更新
        return page.setRecords(erpGoodsDtoLists);
  }
}

七、前端的显示实现

<template>
  <a-modal
    :width="1200"
    :visible="visible"
    :title="title"
    @ok="handleSubmit"
    @cancel="close"
    cancelText="关闭"
    style="top:5%;height: 100%;overflow-y: hidden"
    wrapClassName="ant-modal-cust-warp"
  >
    <a-row :gutter="10" style="padding: 10px; margin: -10px">
      <a-col :md="24" :sm="24">
        <!-- 查询区域 -->
        <div class="table-page-search-wrapper">
          <!-- 搜索区域 -->
          <a-form layout="inline" @keyup.enter.native="onSearch">
            <a-row :gutter="24">
              <a-col :md="6" :sm="8">
                <a-form-item label="商品" :labelCol="{span: 5}" :wrapperCol="{span: 18, offset: 1}">
                  <a-input ref="goods" placeholder="编码或名称模糊查询" v-model="queryParam.condition"></a-input>
                </a-form-item>
              </a-col>
              <a-col :md="6" :sm="8">
                <a-form-item label="类别" :labelCol="{span: 5}" :wrapperCol="{span: 18, offset: 1}">
                  <a-input ref="goods" placeholder="类别" v-model="queryParam.categoryId"></a-input>
                </a-form-item>
              </a-col>
              <a-col :md="6" :sm="8">
                <a-form-item label="品牌" :labelCol="{span: 5}" :wrapperCol="{span: 18, offset: 1}">
                  <a-input ref="goods" placeholder="品牌" v-model="queryParam.brandId"></a-input>
                </a-form-item>
              </a-col>
              <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
                <a-col :md="6" :sm="24">
                  <a-button type="primary" @click="loadGoodsData(1)">查询</a-button>
                  <a-button style="margin-left: 8px" @click="searchReset(1)">重置</a-button>
                </a-col>
              </span>
            </a-row>
          </a-form>
          <a-table
            ref="table"
            :scroll="scrollTrigger"
            size="middle"
            rowKey="id"
            :columns="columns"
            :dataSource="dataSource"
            :pagination="ipagination"
            :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange,type: getType}"
            :loading="loading"
            :customRow="rowAction"
            @change="handleTableChange">
            <template slot="customRenderEnableSerialNumber" slot-scope="enableSerialNumber">
              <a-tag v-if="enableSerialNumber==1" color="green">有</a-tag>
              <a-tag v-if="enableSerialNumber==0" color="orange">无</a-tag>
            </template>
            <template slot="customRenderEnableBatchNumber" slot-scope="enableBatchNumber">
              <a-tag v-if="enableBatchNumber==1" color="green">有</a-tag>
              <a-tag v-if="enableBatchNumber==0" color="orange">无</a-tag>
            </template>
          </a-table>
        </div>
      </a-col>
    </a-row>
  </a-modal>
</template>
<script>
  import { httpAction, getAction } from '@/api/manage'
  import {filterObj} from '@/utils/util'
  import { NbcioListMixin } from '@/mixins/NbcioListMixin'
  import Vue from 'vue'
  export default {
    name: 'NbcioSelectGoodsModal',
    mixins:[NbcioListMixin],
    components: {},
    props: ['modalWidth', 'rows', 'multi', 'goodsIds'],
    data() {
      return {
        queryParam: {
          condition: '',
          category: {},
          brand: {}
        },
        labelCol: {
          xs: { span: 24 },
          sm: { span: 5 },
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 16 },
        },
        categoryTree:[],
        columns: [
          {dataIndex: 'id', title: '商品ID'},
          {dataIndex: 'code', title: '编码'},
          {dataIndex: 'name', title: '名称'},
          {dataIndex: 'categoryName', title: '类别'},
          {dataIndex: 'brandName', title: '品牌'},
          {dataIndex: 'unit', title: '单位'},
          {dataIndex: 'spec', title: '规格'},
          {dataIndex: 'salePrice', title: '销售价格'},
          {dataIndex: 'taxRate', title: '税率(%)'},
          {dataIndex: 'stockNum', title: '库存数量'}, 
        ],
        scrollTrigger: {},
        dataSource: [],
        selectedRowKeys: [],
        selectGoodsRows: [],
        selectGoodsIds: [],
        title: '选择商品',
        ipagination: {
          current: 1,
          pageSize: 10,
          pageSizeOptions: ['10', '20', '30'],
          showTotal: (total, range) => {
            return range[0] + '-' + range[1] + ' 共' + total + '条'
          },
          showQuickJumper: true,
          showSizeChanger: true,
          total: 0
        },
        visible: false,
        form: this.$form.createForm(this),
        loading: false,
        expandedKeys: [],
        disableMixinCreated: true,
        goodsType: [],
        url: {
          goodslist: "/goods/erpGoodsDto/list", 
        },
      }
    },
    computed: {
      // 计算属性的 getter
      getType: function () {
        return this.multi == true ? 'checkbox' : 'radio';
      }
    },
    watch: {
      goodId: {
        immediate: true,
        handler() {
          this.initcode()
        }
      },
    },
    created() {
      // 该方法触发屏幕自适应
      this.resetScreenSize()
    },
    methods: {
      initcode() {
        if (this.goodId) {
          this.$emit('initComp', this.goodCode)
        } else {
          // JSelectUserByDep组件bug issues/I16634
          this.$emit('initComp', '')
        }
      },
      loadGoodsData(arg) {
        if (arg === 1) {
          this.ipagination.current = 1;
        }
        this.loading = true
        let params = this.getQueryParams()//查询条件
        console.log("loadGoodsData params",params)
        getAction(this.url.goodslist,params).then((res) => {
          if (res) {
            console.log("goodslist res.result = ",res.result);
            this.dataSource = res.result.records;
            this.ipagination.total = res.result.total;
            if(res.total ===1) {
              this.title = '选择商品'
              this.$nextTick(() => this.$refs.goods.focus());
            } else {
              this.title = '选择商品'
            }
          }
        }).finally(() => {
          this.loading = false
        })
      },
      // 触发屏幕自适应
      resetScreenSize() {
        let screenWidth = document.body.clientWidth;
        if (screenWidth < 500) {
          this.scrollTrigger = {x: 800};
        } else {
          this.scrollTrigger = {};
        }
      },
      showModal(goodId) {
        this.visible = true;
        this.title = '选择商品'
        this.queryParam.condition = goodId;
        this.$nextTick(() => this.$refs.goods.focus());
        this.loadGoodsData();
        this.form.resetFields();
      },
      getQueryParams() {
        let param = Object.assign({}, this.buildSearchFormData());
        param.page = this.ipagination.current;
        param.rows = this.ipagination.pageSize;
        return filterObj(param);
      },
      // 查询前构建具体的查询参数
      buildSearchFormData() {
        return {
          scId: this.scId,
          condition: this.queryParam.condition,
          categoryId: this.queryParam.category.id || '',
          brandId: this.queryParam.brand.id || ''
        }
      },
      getQueryField() {
        let str = 'id,';
        for (let a = 0; a < this.columns.length; a++) {
          str += ',' + this.columns[a].dataIndex;
        }
        return str;
      },
      searchReset(num) {
        let that = this;
        if (num !== 0) {
          that.queryParam = {};
          that.loadGoodsData(1);
        }
        that.selectedRowKeys = [];
        that.selectGoodsIds = [];
      },
      close() {
        this.searchReset(0);
        this.visible = false;
      },
      handleTableChange(pagination, filters, sorter) {
        this.ipagination = pagination;
        this.loadGoodsData();
      },
      handleSubmit() {
        let that = this;
        this.getSelectGoodsRows();
        that.$emit('ok', that.selectGoodsRows, that.selectGoodsIds);
        that.searchReset(0)
        that.close();
      },
      //获取选择信息
      getSelectGoodsRows(rowId) {
        let dataSource = this.dataSource;
        console.log("getSelectGoodsRows datasource=",dataSource);
        let goodsIds = "";
        this.selectGoodsRows = [];
        for (let i = 0, len = dataSource.length; i < len; i++) {
          if (this.selectedRowKeys.includes(dataSource[i].id)) {
            this.selectGoodsRows.push(dataSource[i]);
            goodsIds = goodsIds + "," + dataSource[i].id;
          }
        }
        this.selectGoodsIds = goodsIds.substring(1);
        console.log("getSelectGoodsRows selectGoodsRows=",this.selectGoodsRows);
        console.log("getSelectGoodsRows selectGoodsIds=",this.selectGoodsIds);
      },
      onSelectChange(selectedRowKeys, selectionRows) {
        this.selectedRowKeys = selectedRowKeys;
        this.selectionRows = selectionRows;
      },
      onSearch() {
        if(this.dataSource && this.dataSource.length===1) {
          if(this.queryParam.q === this.dataSource[0].code||
            this.queryParam.q === this.dataSource[0].name) {
            let arr = []
            arr.push(this.dataSource[0].id)
            this.selectedRowKeys = arr
            this.handleSubmit()
          } else {
            this.loadGoodsData(1)
          }
        } else {
          this.loadGoodsData(1)
        }
      },
      modalFormOk() {
        this.loadGoodsData()
      },
      rowAction(record, index) {
        return {
          on: {
            click: () => {
              let arr = []
              arr.push(record.id)
              this.selectedRowKeys = arr
            },
            dblclick: () => {
              let arr = []
              arr.push(record.id)
              this.selectedRowKeys = arr
              this.handleSubmit()
            }
          }
        }
      }
    }
  }
</script>
<style scoped>
  .ant-table-tbody .ant-table-row td {
    padding-top: 10px;
    padding-bottom: 10px;
  }
  #components-layout-demo-custom-trigger .trigger {
    font-size: 18px;
    line-height: 64px;
    padding: 0 24px;
    cursor: pointer;
    transition: color .3s;
  }
</style>

八、效果图:


相关文章
|
12天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
3天前
|
SQL 监控 关系型数据库
SQL语句当前及历史信息查询-performance schema的使用
本文介绍了如何使用MySQL的Performance Schema来获取SQL语句的当前和历史执行信息。Performance Schema默认在MySQL 8.0中启用,可以通过查询相关表来获取详细的SQL执行信息,包括当前执行的SQL、历史执行记录和统计汇总信息,从而快速定位和解决性能瓶颈。
|
14天前
|
SQL 存储 缓存
如何优化SQL查询性能?
【10月更文挑战第28天】如何优化SQL查询性能?
59 10
|
8天前
|
SQL 关系型数据库 MySQL
|
22天前
|
SQL 数据库 开发者
功能发布-自定义SQL查询
本期主要为大家介绍ClkLog九月上线的新功能-自定义SQL查询。
|
29天前
|
SQL 移动开发 Oracle
SQL语句实现查询连续六天数据的方法与技巧
在数据库查询中,有时需要筛选出符合特定时间连续性条件的数据记录
|
1月前
|
SQL Java 数据库连接
如何使用`DriverManager.getConnection()`连接数据库,并利用`PreparedStatement`执行参数化查询,有效防止SQL注入。
【10月更文挑战第6天】在代码与逻辑交织的世界中,我从一名数据库新手出发,通过不断探索与实践,最终成为熟练掌握JDBC的开发者。这段旅程充满挑战与惊喜,从建立数据库连接到执行SQL语句,再到理解事务管理和批处理等高级功能,每一步都让我对JDBC有了更深的认识。示例代码展示了如何使用`DriverManager.getConnection()`连接数据库,并利用`PreparedStatement`执行参数化查询,有效防止SQL注入。
84 5
|
1月前
|
SQL 数据挖掘 数据库
SQL查询每秒的数据:技巧、方法与性能优化
id="">SQL查询功能详解 SQL(Structured Query Language,结构化查询语言)是一种专门用于与数据库进行沟通和操作的语言
|
1月前
|
SQL 移动开发 大数据
SQL语句查询连续六天满足条件的记录
在数据库管理和数据分析中,我们经常需要查询符合特定时间范围内连续几天的记录
|
1月前
|
SQL 数据挖掘 关系型数据库
SQL查询次数大于1的记录:高效技巧与方法
在数据库管理中,经常需要统计某些操作的次数,特别是当需要找出哪些记录或值出现的次数超过一定阈值(如大于1次)时