关于多数据源(除自己数据库外,另一部分数据需通过接口调取第三方获取)的查询问题

同样,还是一次工作上遇到的问题的记录,当时也是搞了挺久才搞出来的,虽然不太完美,但是误差方面在我的项目里还算可以接受,哪位老哥有更好的办法还请指导下,哪怕评论里留个网页链接我去看也好,多谢了。

具体问题描述大致如下:

  客户需要app能查询出所有订单,分页并且按时间倒序排列,现在所有的消费订单数据在我们自己的数据库里,而所有的充值订单数据其实在第三方那里(其实我们自己也记录了一笔,但是数据结果不可靠,因此还是要取用对方的),关于从第三方获取数据的参数概括是(用户唯一标识,每页显示行数,当前页数),即(userId,pageSize,pageNo),其中pageSize要求小于50。

经过思考,需要解决的问题主要在于:

  1.如何从第三方获取我需要的数据

  2.整合我们库里的数据,第三方获取的数据,进行时间倒序排列,并返回给app

实际上第二点很好解决,只要写一个排序类,对整合后的数据进行排序即可,最主要难点在于第一点,如何确定调取第三方接口的入参pageSize和pageNo,然后还要把之前已经展示过的数据排除掉。

具体解决方法如下:

  1.首先,我用了cache,用于记录app已展示的(消费记录数)(充值记录数),即(我方库数据展示量)(第三方数据展示量),暂定参数为ownother,当app端传的页数为第一页时,将这两个数据都置为0.

  2.查询接下来需要展示的数据中,我方的数据,这点没什么好说的,正常的查自己数据库即可,需要查出来的量为own<rownum<own+appPageSize,其中appPageSize是指app的入参,app端的页显示行数

  3.然后查询需要展示的数据中,第三方的数据,关于确定调取第三方接口入参的方法如下:

 1 /**
 2      * 获取第三方订单查询接口所需要的参数
 3      * @param start        起始数据量
 4      * @param end        结束数据量
 5      * @param size        展示数据量
 6      * @return
 7      * Map,包含两个参数,pagenum页数,pagesize页显示行数
 8      */
 9     public static Map<String,Integer> getWdPara(int start,int end,int size){
10         Map<String,Integer> map=new HashMap<>();
11         if (start<size||start/size<1) {
12             map.put("pagenum", 1);
13             map.put("pagesize", 10*((end/10)+1));
14         }else{
15             if (start/size==end/size) {
16                 map.put("pagenum", (end/size)+1);
17                 map.put("pagesize", size);
18             }else {
19                 map=getWdPara(start, end, size+1);
20             }
21         }
22         return map;
23     }

其中三个参数的关系是end=start+size,实际上start入参的值就是other,而size入参的值就是appPageSize。而出参的两个参数就分别是调取第三方时候的入参pageSize和pageNo了。关于如何确定这个方法可以获取想要的参数,说起来有点绕,我数学也不太好,当时打了挺久的草稿,参照如下,如果看不懂直接跳过就好。。。因为我自己也经常忘记什么意思:

默认app端展示数据量为10条,所以从第三方中获取的数据需要包含other+10条,因为根据时间倒序,这中间存在没有数据是消费数据,全是充值数据的情况,即所有展示数据均来自于第三方。

第三方数据的起始-截止数据量      pageSize参数,即s    pageNo参数,即n  实际取到的数据量

8-18                    20            1        1-20

18-28                    15             2        15-30

28-38                    20             2        20-40

。。。

一开始是这样草稿打下去的,后来找规律后发现,其实就和查自己数据库一样,保证查到的数据包含起始数据和终止数据即可,即       

( 页数-1)*页显示行数>起始数据,页数*页显示行数>终止数据

然后进行几次举例验证后,就得出上述获取参数的方法了。

至此,最难的一步已经完成了,即已经获取到所有需要的数据了。

  4.然后进行下一步,需要去除掉之前已经展示过了的数据,就如上面例子,我们获取到的数据量,其实是大于需要的数据量,有一部分数据可能之前已经展示了,因此在这里需要将之前展示了的数据去除掉,代码如下 

 1   /**
 2      * 处理订单数据,排除之前显示过的数据
 3      * @param dataList     待处理的list
 4      * @param start        数据起始
 5      * @param size         页显示行数
 6      */
 7     public static void dealList(List<Map<String, String>> dataList,int start,int size){
 8         int removeNum=start%size;
 9         for (int i = 0; i < removeNum; i++) {
10             dataList.remove(0);
11         }
12     }

即起始数据除以页显示行数,取余数,然后获取到的数据量从前往后删除这个余数量的数据即可,这个余数量即之前已经展示用过的数据量。和上面获取参数一样,这个计算方法,也是我自己写了好几个例子,然后找规律写出来的。。。数学不好,见谅,我也不知道逻辑上该怎么解释,反正根据例子找规律,发现这样写没问题。

  5.再然后就没啥问题了,要展示的充值数据,消费数据都已经全部获取到了,只要将一些参数名称处理下,确保保持一致,放在一个list里面,然后写个排序方法,根据订单时间进行倒序,排完序以后,获取前appPageSize个数据返回给前端即可,排序代码如下:

 1   /**
 2      * 数据进行排序,按照时间倒序排序
 3      * @param list
 4      */
 5     @SuppressWarnings("unchecked")
 6     public static void sortTimeMethod(List<Map<String,String>> list){
 7         Comparator comp= new Comparator<Map<String, String>>(){
 8             //返回值大于0时,两者交换顺序
 9             @Override
10             public int compare(Map<String, String> p1,Map<String, String> p2){
11                 String p1Date=Tools.processNull(p1.get("order_date"));
12                 String p2Date=Tools.processNull(p2.get("order_date"));
13                 if ("".equals(p1Date)
14                         ||"".equals(p2Date)) {
15                     return 0;
16                 }else {
17                     //如果o1时间早于等于o2时间,则o1排在后面
18                     if (!DateUtil.formatDate(p1Date).after(DateUtil.formatDate(p2Date))) {
19                         return 1;
20                     }else {
21                         return -1;
22                     }
23                 }
24             }
25         };
26         Collections.sort(list, comp);
27     }

  6.当然,这时候也别忘记更新cache里面的数据,根据最终返回给前端的数据,判断有多少消费数据和充值数据,对ownother进行相应的累加。

以上就全部完成。不过就和我之前说的,有误差,很有局限性,跟我们使用场景有关,因此不是很具备参考性,相关说明如下:

  1.我们是APP展示用的,场景中无法跳页,也就是用户只能选择先看第一页,再看第二页数据,这样依次下排,如果存在跳页,我这个方法应该不行。

  2.当用户在看订单的同时,无法进行充值或消费操作,进行充值或消费等产生订单的操作后,重新来查询必定是从第一页开始,因此那种查了一会儿,突然增加一条订单了,这种情况是不会出现的,否则我这方法会存在问题,即cache里的值不准了,导致的结果就是查询的数据也不准了,有个订单会展示两次。

 


可能看上去条理不是很清晰,有点混乱。。。但是尽力了,其实一开始没打算写,后来隔了半个多月,突然发现自己这个代码看不懂了,然后重新理解了半天,想想这个当初也是自己搞了挺久才弄出来的,怕以后又忘记了,于是此时开始写这篇随笔,本身就是隔了半个月后再写,思路就不是很清晰,结果写了一小半,客户又来事情了,于是忙去了。。。然后一段时间没闲下来,再然后忙着忙着就给忘了。。。。直到今天,已经是半年后了,再次来续写的时候,脑子就更乱了,强行看着半篇内容加自己原先的代码,将其续写完成。主要用处估计也就是以后自己如果遇到相同问题,给自己一个提点,一个思路,防止到时候自己脑子又转不过来。

            

posted @ 2019-01-07 17:43  咸鱼老李  阅读(1744)  评论(0编辑  收藏  举报