项目技巧三

目录

我们现在要实现一个接口功能

1.我们先书写sql语句

 2.编写接口

3.书写业务逻辑

4.书写mapper

结果:

缺点:没有根据涨跌幅区间的大小来排序 

1.yml文件

 2.在value object包下映射这个yml文件

3.开启这个配置类进行映射,并把它交给spring管理

4.修改后的业务逻辑

5.新的结果

6.第二种业务逻辑,使用lambda表达式

实现第二个接口:获取一段时间内,特定的股票每天的最大交易点的信息数据

1.返回的数据格式

2.domain类

3.sql语句分析

4.接口编写

 5.业务逻辑

7.mapperXml文件

结果

把复杂的sql语句分步

 1.mapper

2.mapperXml文件

3.业务逻辑


我们现在要实现一个接口功能

查询当前时间下股票的涨跌幅度区间统计功能
 如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询点

股票涨跌幅区间定义: "<-7%" 、 "-7~-5%"、 "-5~-3%" 、 "-3~0%" 、"0~3%" 、 "3~5%" 、 "5~7%" 、 ">7%" 

要返回的数据

{
    "code": 1,
    "data": {
        "time": "2021-12-31 14:58:00",
        "infos": [
            {
                "count": 17,
                "title": "-3~0%"
            },
            {
                "count": 2,
                "title": "-5~-3%"
            },
			//省略......
        ]
    }
}

1.我们先书写sql语句

#统计当前时间下(精确到分钟),A股在各个涨跌区间股票的数量;
#股票涨跌幅区间定义: "<-7%" 、 "-7~-5%"、 "-5~-3%" 、 "-3~0%" 、"0~3%" 、 "3~5%" 、 "5~7%" 、 ">7%"

#1.使用的表stock_market_index_info
#2.业务分析:1.时间:当前最新交易时间点
        #2.要统计出每个个股的涨幅流水表
        #3.把每个个股的涨幅转换成涨跌幅区间  使用 case when then end
        #4.最后根据涨跌幅区间来分组统计每个组的记录数量 count
#3.返回的数据 count title(涨跌幅区间)
#1.统计每个个股的涨幅
select (cur_price-pre_close_price)/pre_close_price as ud from stock_rt_info where cur_time='2022-01-06 09:55:00';

 

#2.把涨幅字段的值转换成涨跌幅区间
select
    case
        when tmp.ud>0.07 then '>7%'  #根据条件来该字段的值
        when tmp.ud<=0.07 and tmp.ud>0.05 then '5~7%'
        when tmp.ud<=0.05 and tmp.ud>0.03 then '3~5%'
        when tmp.ud<=0.03 and tmp.ud>0 then '0~3%'
        when tmp.ud<=0 and tmp.ud>-0.03 then '-3~0%'
        when tmp.ud<=-0.03 and tmp.ud>-0.05 then '-5~-3%'
        when tmp.ud<=-0.05 and tmp.ud>=-0.07 then '-7~-5%'
        else '<-7%'
    end 'title' #给这个字段重命名
    from (select (cur_price-pre_close_price)/pre_close_price as ud from stock_rt_info where cur_time='2022-01-06 09:55:00')
    as tmp;

 

#3.根据涨跌幅区间进行分组
select count(*) as count, tmp2.title from (select
                 case
                     when tmp.ud>0.07 then '>7%'  #根据条件来该字段的值
                     when tmp.ud<=0.07 and tmp.ud>0.05 then '5~7%'
                     when tmp.ud<=0.05 and tmp.ud>0.03 then '3~5%'
                     when tmp.ud<=0.03 and tmp.ud>0 then '0~3%'
                     when tmp.ud<=0 and tmp.ud>-0.03 then '-3~0%'
                     when tmp.ud<=-0.03 and tmp.ud>-0.05 then '-5~-3%'
                     when tmp.ud<=-0.05 and tmp.ud>=-0.07 then '-7~-5%'
                     else '<-7%'
                     end 'title' #给这个字段重命名
             from (select (cur_price-pre_close_price)/pre_close_price as ud from stock_rt_info where cur_time='2022-01-06 09:55:00')
                      as tmp) as tmp2 group by tmp2.title;

 2.编写接口

    /**
     * 查询当前时间下股票的涨跌幅度区间统计功能
     * 如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询点
     * @return
     */
  
    @ApiOperation("查询最新交易时间下股票的涨跌幅度区间中各个股票的数量")
    @GetMapping("/stock/updown")
    public R<Map<String,Object>> getStockUpDown(){//这里使用的是Object,因为每个键对应的类型不一样,一个是String,一个是List集合
        return stockService.stockUpDownScopeCount();
    }

3.书写业务逻辑

/**
     * 查询当前时间下股票的涨跌幅度区间统计功能
     * 如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询点
     * @return
     */
    @Override
    public R<Map<String, Object>> stockUpDownScopeCount() {
        //1.获取当前时间的最新交易点
        DateTime datetime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date time=datetime.toDate();
        //设置mock data
        DateTime curDateTime=DateTime.parse("2022-01-06 09:55:00",DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        Date curDate = curDateTime.toDate();

        //2.根据mapper接口获取数据
        List<Map> infos=stockRtInfoMapper.getStockUpDownScopeCount(curDate);

        //3.封装数据
        Map<String,Object>data=new HashMap<>();
        data.put("time",curDateTime.toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")));
        data.put("infos",infos);
        //4.返回数据
        return R.ok(data);
    }

4.书写mapper

    /**
     * 查询当前时间下股票的涨跌幅度区间统计功能
     * 如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询点
     * @return
     */
    List<Map> getStockUpDownScopeCount(@Param("curDate") Date curDate);

5.书写mapperXml文件

<!--    如果在XML中SQL语句遇到大量特殊字符需要转义,比如:< 等,建议使用** sql 语句 **标记,这样特殊字符就不会被解析器解析
所以使用<![CDATA[]]>   -->
    <select id="getStockUpDownScopeCount" resultType="map">
        <![CDATA[
        select count(*) as count, tmp2.title from (select
        case
        when tmp.ud>0.07 then '>7%'
        when tmp.ud<=0.07 and tmp.ud>0.05 then '5~7%'
        when tmp.ud<=0.05 and tmp.ud>0.03 then '3~5%'
        when tmp.ud<=0.03 and tmp.ud>0 then '0~3%'
        when tmp.ud<=0 and tmp.ud>-0.03 then '-3~0%'
        when tmp.ud<=-0.03 and tmp.ud>-0.05 then '-5~-3%'
        when tmp.ud<=-0.05 and tmp.ud>=-0.07 then '-7~-5%'
        else '<-7%'
        end 'title'
        from (select (cur_price-pre_close_price)/pre_close_price as ud from stock_rt_info where cur_time=#{curDate})
        as tmp) as tmp2 group by tmp2.title
        ]]>
    </select>

结果:

缺点:没有根据涨跌幅区间的大小来排序 

我们可以在application-stock.yml文件中自己书写按照大小排序的涨跌幅区间,因为涨跌幅区间不能直接进行大小比较进行排序

1.yml文件

# 配置股票相关的参数
stock:
  upDownRange:
    - "<-7%"
    - "-7~-5%"
    - "-5~-3%"
    - "-3~0%"
    - "0~3%"
    - "3~5%"
    - "5~7%"
    - ">7%"

 2.在value object包下映射这个yml文件

@Data
@ConfigurationProperties(prefix = "stock")//映射yml文件中stock属性的值
//@Component//直接让其交给spring管理,TODO:我们不使用(不让它自己开启),我们让其他要使用该类的子模块来开启
public class StockInfoConfig {

    public List<String>upDownRange;//涨跌幅区间
}

3.开启这个配置类进行映射,并把它交给spring管理

@Configuration
@EnableConfigurationProperties(StockInfoConfig.class)//TODO:在这个子模块开启加载此配置类,并让它映射yml文件中的stock属性的值,再交给spring管理
public class CommonConfig {

}

4.修改后的业务逻辑

    /**
     * 查询当前时间下股票的涨跌幅度区间统计功能
     * 如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询点
     * @return
     */
    @Override
    public R<Map<String, Object>> stockUpDownScopeCount() {
        //1.获取当前时间的最新交易点
        DateTime datetime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date time=datetime.toDate();
        //设置mock data
        DateTime curDateTime=DateTime.parse("2022-01-06 09:55:00",DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        Date curDate = curDateTime.toDate();

        //2.根据mapper接口获取数据
        List<Map> infos=stockRtInfoMapper.getStockUpDownScopeCount(curDate);

        //获取涨跌幅区间(按照大小排序)
        List<String> upDownRange = stockInfoConfig.getUpDownRange();

        List<Map>orderInfos=new ArrayList<>();//创建一个新的集合,来接收新的数据

        for (String range : upDownRange) {//按照涨跌幅区间排序(升序)
            Map tmpMap =null;//创建一个临时map
            for (Map map : infos) {
                if(map.containsValue(range)){//如果包含这个涨跌幅区间,就进行赋值
                    tmpMap=map;
                    break;
                }
            }
            if(tmpMap==null) {//如果tmpMap还为null,则说明没有该涨跌幅区间
                tmpMap=new HashMap();//自己进行赋值
                tmpMap.put("count",0);
                tmpMap.put("title",range);
            }
            orderInfos.add(tmpMap);//添加
        }

        //3.封装数据
        Map<String,Object>data=new HashMap<>();
        data.put("time",curDateTime.toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")));
        data.put("infos",orderInfos);
        //4.返回数据
        return R.ok(data);
    }

5.新的结果

6.第二种业务逻辑,使用lambda表达式

    /**
     * 查询当前时间下股票的涨跌幅度区间统计功能
     * 如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询点
     * @return
     */
    @Override
    public R<Map<String, Object>> stockUpDownScopeCount() {
        //1.获取当前时间的最新交易点
        DateTime datetime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date time=datetime.toDate();
        //设置mock data
        DateTime curDateTime=DateTime.parse("2022-01-06 09:55:00",DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        Date curDate = curDateTime.toDate();

        //2.根据mapper接口获取数据
        List<Map> infos=stockRtInfoMapper.getStockUpDownScopeCount(curDate);

        //获取涨跌幅区间(按照大小排序)
        List<String> upDownRange = stockInfoConfig.getUpDownRange();

/*
        List<Map>orderInfos=new ArrayList<>();//创建一个新的集合,来接收新的数据
        for (String range : upDownRange) {//按照涨跌幅区间排序(升序)
            Map tmpMap =null;//创建一个临时map
            for (Map map : infos) {
                if(map.containsValue(range)){//如果包含这个涨跌幅区间,就进行赋值
                    tmpMap=map;
                    break;
                }
            }
            if(tmpMap==null) {//如果tmpMap还为null,则说明没有该涨跌幅区间
                tmpMap=new HashMap();//自己进行赋值
                tmpMap.put("count",0);
                tmpMap.put("title",range);
            }
            orderInfos.add(tmpMap);//添加
        }
*/
        List<Map>orderInfos=upDownRange.stream().map(range->{//使用map方法将String数据类型转换成map类型,range是upDownRange集合的每个值
            Map tmpMap=null;//创建一个临时map
            //使用之前查询出来的List<Map>集合来过滤出含有涨跌幅区间的map,并使用findFirst()进行赋值
            //这里使用 Optional来接收,是防止为null
            Optional<Map>op =infos.stream().filter(map->map.containsValue(range)).findFirst();
            if(op.isPresent()){
                tmpMap=op.get();//存在就直接进行赋值
            }else{
                tmpMap=new HashMap();//自己进行赋值
                tmpMap.put("count",0);
                tmpMap.put("title",range);
            }
            return tmpMap;
        }).collect(Collectors.toList());

        //3.封装数据
        Map<String,Object>data=new HashMap<>();
        data.put("time",curDateTime.toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")));
        data.put("infos",orderInfos);
        //4.返回数据
        return R.ok(data);
    }

实现第二个接口:获取一段时间内,特定的股票每天的最大交易点的信息数据

1.返回的数据格式

{
    "code": 1,
    "data": [
        {
            "date": "2021-12-20 10:20",//日期
            "tradeAmt": 28284252,//交易量(指收盘时的交易量,如果当天未收盘,则显示最新数据)
            "code": "000021",//股票编码
            "lowPrice": 16,//最低价格(指收盘时记录的最低价,如果当天未收盘,则显示最新数据)
            "name": "深科技",//名称
            "highPrice": 16.83,//最高价(指收盘时记录的最高价,如果当天未收盘,则显示最新数据)
            "openPrice": 16.8,//开盘价
            "tradeVol": 459088567.58,//交易金额(指收盘时记录交易量,如果当天未收盘,则显示最新数据)
            "closePrice": 16.81//当前收盘价(指收盘时的价格,如果当天未收盘,则显示最新cur_price)
            "preClosePrice": 16.81//前收盘价
        },
        //......
    ]
}

把data里面的key封装成一个domain包下的类,因为是通过与数据库进行交互并赋值的

2.domain类

/**
 * @Description 个股日K数据封装
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "个股日K数据封装")
public class Stock4EvrDayDomain {
    /**
     * 日期,eg:202201280809
     */
    @ApiModelProperty("当前日期")
    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "Asia/Shanghai")//设置返回给前端的时间数据格式
    private Date date;
    /**
     * 交易量
     */
    @ApiModelProperty("交易量")
    private Long tradeAmt;
    /**
     * 股票编码
     */
    @ApiModelProperty("股票编码")
    private String code;
    /**
     * 最低价
     */
    @ApiModelProperty("最低价")
    private BigDecimal lowPrice;
    /**
     * 股票名称
     */
    @ApiModelProperty("股票名称")
    private String name;
    /**
     * 最高价
     */
    @ApiModelProperty("最高价")
    private BigDecimal highPrice;
    /**
     * 开盘价
     */
    @ApiModelProperty("开盘价")
    private BigDecimal openPrice;
    /**
     * 当前交易总金额
     */
    @ApiModelProperty("当前交易总金额")
    private BigDecimal tradeVol;
    /**
     * 当前收盘价格指收盘时的价格,如果当天未收盘,则显示最新cur_price)
     */
    @ApiModelProperty("当前收盘价格指收盘时的价格,如果当天未收盘,则显示最新cur_price")
    private BigDecimal closePrice;
    /**
     * 前收盘价
     */
    @ApiModelProperty("前收盘价")
    private BigDecimal preClosePrice;
}

3.sql语句分析

#1.需要使用的表stock_rt_info
#2.业务分析 1.规定一个时间范围,几天到几天 between and
            #2.根据每天,即通过相同天数来分组  grouped by
            #3.然后取每个组内的最大交易时间点来查询各个信息 根据 in
#1.找到一段时间范围内每天的特定股票的最大交易点
select max(cur_time) #取每个组的最大时间交易点
from stock_rt_info where cur_time between '2022-01-01 09:30:00' and '2022-06-06 14:25:00' and stock_code='600021'
group by date_format(cur_time,'%Y%m%d');#根据天数相同来分组,所以格式化时间,去掉时分秒

#2.根据每天的最大交易点来查询特定股票的数据
select
    cur_time as date,
    trade_amount as tradeAmt,
    stock_code as code,
    min_price as lowPrice,
    stock_name as name,
    max_price as highPrice,
    open_price as openPrice,
    trade_volume as tradeVol,
    cur_price as closePrice,
    pre_close_price as preClosePrice
    from stock_rt_info
    where stock_code='600009' and
 cur_time in (select max(cur_time) #取每个组的最大时间交易点
   from stock_rt_info where cur_time between '2022-01-01 09:30:00' and '2022-06-06 14:25:00' and stock_code='600021'
   group by date_format(cur_time,'%Y%m%d')) order by cur_time;#根据时间大小进行排序

4.接口编写

    /**
     * 单个个股日K 数据查询 ,可以根据时间区间查询数日的K线数据
     * @param stockCode 股票编码
     */
    @GetMapping("/stock/screen/dkline")
    @ApiOperation("单个个股日K 数据查询 ,可以根据时间区间查询数日的K线数据")
    @ApiImplicitParams(
            @ApiImplicitParam(name="code",value = "特定股票编码",required = true)
    )
    public R<List<Stock4EvrDayDomain>> getDayKLinData(@RequestParam(value = "code",required = true) String stockCode){
        return stockService.stockCreenDkLine(stockCode);
    }

 5.业务逻辑

 /**
     * 获取一段时间内,特定的股票每天的最大交易点的信息数据
     * @param stockCode 特定股票的编码
     */
    @Override
    public R<List<Stock4EvrDayDomain>> stockCreenDkLine(String stockCode) {
        //获取当前的时间的最新交易点
        DateTime datetime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date curTime = datetime.toDate();
        //设置mock data
        curTime = DateTime.parse("2022-06-06 14:25:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //获取十天前的时间
        DateTime lastDateTime = datetime.minusDays(10);
        Date lastTime = lastDateTime.toDate();
        //设置mock data
        lastTime=DateTime.parse("2022-01-01 09:30:00",DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();

        //调用接口mapper方法
       List<Stock4EvrDayDomain>data= stockRtInfoMapper.getStockInfo4EvrDay(lastTime,curTime,stockCode);
       if(data==null){
           return R.error(ResponseCode.NO_RESPONSE_DATA);
       }
       //返回数据
        return  R.ok(data);
    }

6.mapper

/**
     * 获取一段时间内,每天的最大交易时间的特定股票的基本数据
     * @param lastTime 一段时间的开头
     * @param curTime 一段时间的末尾
     * @param stockCode 特定股票编码
     */
    List<Stock4EvrDayDomain> getStockInfo4EvrDay(@Param("lastTime") Date lastTime, @Param("curTime") Date curTime, @Param("stockCode") String stockCode);

7.mapperXml文件

    <select id="getStockInfo4EvrDay" resultType="com.hhh.stock.pojo.domain.Stock4EvrDayDomain">
        select
            cur_time as date,
    trade_amount as tradeAmt,
    stock_code as code,
    min_price as lowPrice,
    stock_name as name,
    max_price as highPrice,
    open_price as openPrice,
    trade_volume as tradeVol,
    cur_price as closePrice,
    pre_close_price as preClosePrice
        from stock_rt_info
        where stock_code=#{stockCode} and
            cur_time in (select max(cur_time)
            from stock_rt_info where cur_time between #{lastTime} and #{curTime} and stock_code=#{stockCode}
            group by date_format(cur_time,'%Y%m%d')) order by cur_time
    </select>

结果

把复杂的sql语句分步

 1.mapper

 /**
     * 获取一段时间内特定股票的每天的最大交易时间点
     * @param lastTime 一段时间的开始
     * @param curTime 一段时间的末尾
     * @param stockCode 特定股票的编码
     */
    List<Date>getStockEvrDayOfMaxTradingTime(@Param("lastTime") Date lastTime, @Param("curTime") Date curTime, @Param("stockCode") String stockCode);

    /**
     * 根据每天的最大交易时间点来查询特定股票的信息
     * @param dateList 每天的最大交易点的集合
     * @param stockCode 特定的股票编码
     */
    List<Stock4EvrDayDomain>getStockInfo4EvrDayByMaxTradingTime(@Param("dateList") List<Date>dateList, @Param("stockCode") String stockCode);

2.mapperXml文件

 <select id="getStockEvrDayOfMaxTradingTime" resultType="java.util.Date">
        select max(cur_time) as date from stock_rt_info where cur_time
         between #{lastTime} and #{curTime} and stock_code=#{stockCode}
        group by date_format(cur_time,'%Y%m%d')
    </select>
    <select id="getStockInfo4EvrDayByMaxTradingTime" resultType="com.hhh.stock.pojo.domain.Stock4EvrDayDomain">
        select
            cur_time as date,
    trade_amount as tradeAmt,
    stock_code as code,
    min_price as lowPrice,
    stock_name as name,
    max_price as highPrice,
    open_price as openPrice,
    trade_volume as tradeVol,
    cur_price as closePrice,
    pre_close_price as preClosePrice
        from stock_rt_info
        where stock_code=#{stockCode} and
            cur_time in
        <foreach collection="dateList" item="date" open="(" separator="," close=")">
            #{date}
        </foreach>
        order by cur_time
    </select>

3.业务逻辑

 /**
     * 通过分解复杂sql语句来查询一段时间内的每天的最大交易点的特定股票的数据
     * @param stockCode 特定股票的编码
     */
    @Override
    public R<List<Stock4EvrDayDomain>> stockCreenDkLine2(String stockCode) {
        //获取当前的时间的最新交易点
        DateTime datetime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date curTime = datetime.toDate();
        //设置mock data
        curTime = DateTime.parse("2022-06-06 14:25:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //获取十天前的时间
        DateTime lastDateTime = datetime.minusDays(10);
        Date lastTime = lastDateTime.toDate();
        //设置mock data
        lastTime=DateTime.parse("2022-01-01 09:30:00",DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();

        //调用mapper来获取每天的最大交易点的集合
        List<Date> dateList = stockRtInfoMapper.getStockEvrDayOfMaxTradingTime(lastTime, curTime, stockCode);
        //调用mapper根据最大交易点的集合获取特定股票的信息
        List<Stock4EvrDayDomain> data = stockRtInfoMapper.getStockInfo4EvrDayByMaxTradingTime(dateList, stockCode);
        if(data==null){
            return R.error(ResponseCode.NO_RESPONSE_DATA);
        }
        //返回数据
        return R.ok(data);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落落落sss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值