订单无法对应客户信息是怎么回事(订单中订单客户出现哪些问题)订单无法对应客户信息是怎么回事(订单中订单客户出现哪些问题)

关注健康
关注真实体验

订单无法对应客户信息是怎么回事(订单中订单客户出现哪些问题)

订单无法对应客户信息是怎么回事(订单中订单客户出现哪些问题) 问题诞生

相信99%的Java开发者都接触过一张表:订单表。订单表是业务系统交易信息的基本表,订单的基本要素包含买家、商品、交易金额,订单的查询是很常见的业务系统的功能,包括买家查询自己的下单记录、系统管理员查看所有的买家订单。那么做查询的时候就会面临一个问题,订单主体信息存在了订单表,用户主体信息存在了用户表,商品主体信息存在了商品表,做订单信息查询的时候需要聚合查询这几个信息,怎么查最优雅呢?

几个思路联表查询。类似于 select o.* , u.name from order o left join user u on o.uid = u.id,这么解决最直接,很容易能想到。但是弊端也很明显,联表查询本身性能开销比较大,SQL把所有字段暴露出来肯定是不合适的,暴露出部分字段的话,在需求修改的时候,就会比较麻烦,需要修改SQL以及上层的代码。字段冗余。在order一系列表里面冗余用户、商品等等字段。这种方式也是不推荐的,不能适应需求的修改,很多需求的细节是不能预判的,字段加多了浪费,加少了再去修改更是心累。但是有一种方式可以考虑,就是将订单信息聚合后放到一个查询库,类似于将Mysql里面的订单信息结构化之后放到es,用es专做订单的查询,只是这种方案成本高一点。思考升级

订单表查询关联信息,只是业务系统查询的一个缩影。实际还有很多场景,场景的主表只存关键的信息,存个关系数据,在业务查询的时候,需要带出各个关系主体的信息。比如商品收藏,数据表只存储 user_id , commodity_id , create_time,查询的时候需要展示商品封面、商品名称,那么我们怎么从系统的横向开发角度去考虑,做个通用的组件,进行数据的查询呢?

一种AOP实现

这就需要从AOP的角度去考虑,下面介绍一种实现,假设此处存在一个订单表,表内有user_id,commodity_id,分别对应用户表一个用户,商品表一个商品。

构造一个注解,该注解作用于特定的字段,这个字段作用的也就是我们需要联表展示的信息结构。怎么用呢,接着往下看。

构造OrderDTO作为查询的返回对象,其中使用注解 NeedConvert,两个字段,commodity代表一个商品对象,也就是订单对应的商品;user表示一个用户对象,也就是订单对应的买家。

再来看NeedConvert是怎么用的。service ,method,resField,refField结合使用,其中service表示spring的bean,这个bean有一个方法 method,method的入参是一个List,这个list实际取值就是当前对象OrderDTO的refField字段,然后,方法的返回对象里面有一个resField与refField对应,然后通过一系列处理,将方法的返回值对象,填充到返回对象。

上面讲的比较抽象,举个例子:UserSimpleDTO是一个用户对象,此处它放在OrderDTO里面,UserService有一个listByIds的方法,入参是List<Long> userIds,返回值是List<User>对象,那么service=UserService.class,method=listByIds,resField=id,refField=userId。

上面还提到一个一系列处理,那么这个处理怎么实现呢?

关键部分代码实现

这里笔者选择在接口Controller方法层做切面,来处理这个关联内嵌对象的查询与填充,首先定义一个方法层的注解,表示有这个注解的才进行查询填充。

然后对ContainsConversion进行实现。定义切点,判断,取值,处理。

此处的关键就是process方法,需要使用反射的一些处理。判断注解是不是存在,然后把需要处理的字段及注解分别提取出来,放到map里面。

对单个注解的处理,就比较简单粗暴了。主要的脉络就是取出NeedConvert的四个参数方法,service,method,refField,resField。拿到一个List结果后,再进行处理。这个list的处理有一个细节,如果service.method的返回值与注解的字段类型相同,就直接进行赋值处理。如果不同,则用copyProperties的方式进行处理。方法内用到的反射工具类就不截图了,通用的反射工具类就能实现这些功能。

不足与优化

文中提到的方式算是一个小戏法,能相对减少一些工作量,尤其是查询方面。假设使用的是mybatisplus/jooq/jpa等等成熟的持久层框架,那么分页、列表等查询是不需要重复开发的,都可以提取公共实现。所以在开发新业务的分页查询的时候,如果使用本文的注解形式,工作量就会集中到业务DTO的定义,产品经理想要什么字段、信息,我们都可以通过增减DTO字段、注解的形式,完成工作,何其快哉!

未经允许不得转载: 九月健康网» 订单无法对应客户信息是怎么回事(订单中订单客户出现哪些问题)
分享到: 更多 ( 0)