背景

在开发过程中,你肯定会遇到这样一个场景:

“获取订单列表,需要显示订单id,下单人member_id,下单人姓名member_name。数据库订单表只有member_id字段,member_name字段在用户会员表中。”

这时候你肯定会使用链表查询

select o.id,o.member_id,m.name from order o,member m where o.member_id = m.id;

一行SQL搞定,很简单嘛。

但是随着时间推移,系统越来越大,单体服务会拆分为微服务。每个服务有自己的库。

这时候你就不好做跨库查询了吧。

不过你用的Spring Cloud框架,这套框架可以将远程调用变得和本地调用一样简单。

你可能会有如下代码:

其中订单实体Order(作了简化,只保留本次案例用的字段)

@Data@AllArgsConstructor@NoArgsConstructorpublic class Order {    /**     * 订单id     */    private String id;    /**     * 下单用户id     */    private String memberId;}

OrderVo为:

@Data@NoArgsConstructor@EqualsAndHashCode(callSuper = false)public class OrderVo {    private String id;    private String memberId;    /**     * 获取订单用户name     */    private String memberName;}

用户会员实体Member为:

@Data@AllArgsConstructor@NoArgsConstructorpublic class Member implements Serializable {    private static final long serialVersionUID = 1L;    @Id    private String id;    private String name;}

测试结果为:

在listOrderVo()方法中,我们只有两步:

“从数据库中查询Order从用户服务中获取用户名”

其中第2步的memberService.getById(memberId)是远程跨库调用。

你发现就算不是以前的连表查询,也不难嘛。

关于上面跨库查询的思考

上面的场景我也经历过,看了代码,我思考:步骤2在这个方法listOrderVo()中是否显得多余呢。我只是需要订单信息,却有大段的代码是如何获取memberName。这里只是订单信息要显示memberName,那么物流信息可能也要显示memberName。还有其他的业务比如:后台要展示用户签到记录也需要显示memberName。都要写步骤2的代码,太麻烦了。

可不可以将步骤2封装呢?

思来想去,发现使用注解可以优雅的解决这个问题。

注解封装

我们先来定义几个注解:

NeedSetValue

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface NeedSetValue {    Class> beanClass();    String param();    String method();    String targetFiled();}

NeedSetValue注解用于字段上,下面来解释下这几个属性的含义:

“beanClass:表示获取值的方法在哪个类上param:表示字段值的方法的传入参数method:表示获取字段值的方法targetFiled:表示方法的返回的某个字段值赋给当前字段”

NeedSetValueField

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface NeedSetValueField {}

作用与方法上,表示该方法的返回值会通过注解处理获得。

我们来开发NeedSetValue注解的功能

@Component@Aspectpublic class SetFieldValueAspect {    @Autowired    BeanUtil beanUtil;    @Around("@annotation(com.lvshen.demo.annotation.NeedSetValueField)")    public Object doSetFieldValue(ProceedingJoinPoint point) throws Throwable {        Object o = point.proceed();        if (o instanceof Collection) {            this.beanUtil.setFieldValueForCol(((Collection) o));        } else {            //返回结果不是集合的逻辑        }        return o;    }}

使用AOP,执行方法后会执行后置处理this.beanUtil.setFieldValueForCol(((Collection) o));这里我只写了方法返回式集合的处理。

setFieldValueForCol方法如下:

由于代码过长,这里我转成图片了。这个方法主要做几件事:

1.获取有NeedSetValue注解的字段

2.反射获取注解上的参数,方法,返回值

3.执行注解上的方法,获取返回值

4.将返回的这个值赋给标注注解的这个字段

如果上面的代码没有看明白,那先看看我下面的使用例子吧

首先OrderVo代码如下:

@Data@NoArgsConstructor@EqualsAndHashCode(callSuper = false)public class OrderVo{    private String id;    private String memberId;    /**     * 获取订单用户name     */    @NeedSetValue(beanClass = MemberService.class, param = "memberId", method = "getById", targetFiled = "name")    private String memberName;}

上面的注解表示:memberName的值是通过MemberService#getById方法获取的,该方法的参数为字段memberId,并将方法值的name赋给memberName。

我们刚才获取订单展示的方法改造如下:

@NeedSetValueFieldpublic List listOrderVoByAnnotation() {    //1.从数据库中查询Order    List orderList = this.listOrder();    log.info("数据库中的数据orderList:{}",orderList);    //list之间的转换    return OrderConverter.INSTANCE.listentity2Vo(orderList);}

只需要添加@NeedSetValueField注解即可。省了步骤2。

测试结果如下:

你看,我没有写步骤2,一样获取到了memberName。

有的开发认为写注解是多此一举,但是步骤2实际上是违反了设计原则:单一职责原则和开闭原则。

如果想要看源码的可以访问下面地址:

https://github.com/lvshen9/demo/blob/lvshen-dev/src/main/java/com/lvshen/demo/annotation

欢迎大家完善。

查询blob字段_一次注解开发实战-我使用注解对微服务的跨库查询做了封装相关推荐

  1. 微服务架构开发实战日志与监控:微服务日志管理将面临的挑战

    微服务的日志与监控:微服务日志管理将面临的挑战 日志来自正在运行的进程的事件流.对于传统的JavaEE应用程序而言,有许多框架和库可用于日志记录.Java Logging (JUL)是Java自身所提 ...

  2. mysql单台跨数据库查询_在MySQL中怎样进行跨库查询?

    在MySQL中跨库查询主要分为两种情况,一种是同服务的跨库查询:另一种是不同服务的跨库查询:它们进行跨库查询是不同的,下面就具体介绍这两种跨库查询. 一.同服务的跨库查询 同服务的跨库查询只需要在关联 ...

  3. mysql跨库查询 索引_MySQL中跨库查询怎么搞?

    导读 在MySQL中跨库查询主要分为两种情况,一种是同服务的跨库查询;另一种是不同服务的跨库查询;它们进行跨库查询是不同的,下面就具体介绍这两种跨库查询. 在MySQL中跨库查询主要分为两种情况,一种 ...

  4. 在MySQL中怎样进行跨库查询?

    在MySQL中跨库查询主要分为两种情况,一种是同服务的跨库查询:另一种是不同服务的跨库查询:它们进行跨库查询是不同的,下面就具体介绍这两种跨库查询. 一.同服务的跨库查询 同服务的跨库查询只需要在关联 ...

  5. 微服务跨数据库联合查询_微服务架构下,解决数据库跨库查询的一些思路

    加关注,不迷路! 前言 在服务做微服务改造后,原先单库join查询已经不能满足要求,每个拆分的微服务对应一个数据库实例,而且部署在不同的服务器上,那么解决"跨库查询"就势在必行了. ...

  6. mysql ef 分布式事务_分布式事务系列--分布式跨库查询解决方案 mysql federated引擎的使用...

    背景 在服务高度拆分,数据库不断细化切分的情况下,我们经常有连接多台数据库查询的需求,如果不断的把数据库连接的逻辑添加在代码中,那么这种耦合会越来越严重,这会给程序的拓展和维护带来很大的麻烦. mys ...

  7. 微服务跨数据库联合查询_数据库跨库查询

    由于微服务技术发展迅猛,在我们的架构中,每个微服务都会相应的对接一个数据库,各个数据库之间有关联的表(比如用户表.业务表等)会互相同步数据,其他的数据操作各自独立(如日志表.操作表等),这么设计是基于 ...

  8. 分布式微服务下的跨库查询解决思路

    分布式微服务下的跨库查询解决思路 参考文章: https://mp.weixin.qq.com/s/_DPunClmcTDJLcC3S9Y4og 微服务架构下,解决数据库跨库查询的一些思路 看了文章后 ...

  9. 微服务架构下,解决数据库跨库查询的一些思路

    开局先总结一下:现在很多厂都进行了微服务的开发模式,但是呢,业务的拆分的时候如果存在交叉是一件非常头大的事情,所以大家写微服务尽量不要交叉的写,比如新增用户如果已经存在在userservice里面了那 ...

最新文章

  1. Java中父类构造方法对子类构造方法的影响(不是一句话可以说清的)
  2. 构建之法 学习笔记06
  3. 神经网络迭代次数的数学构成
  4. on条件与where条件的区别
  5. C语言中最常用标准库
  6. Python学习系列day5-python基础
  7. 1.3.1 操作系统的运行机制和体系结构(大内核、小内核)
  8. 2---多线程文件读写
  9. 6、jeecg 笔记之 自定义excel 模板导出(一)
  10. 知网又火了!续订费近千万且连年上涨 中科院:不堪重负 停用
  11. [bzoj2299][HAOI2011]向量
  12. 设计模式_单例模式回顾_C#版不使用锁保证多线程安全
  13. rsync文件同步应用--客户端的配置
  14. 关于无法卸载和安装VISIO2010的问题
  15. Fiddler的使用介绍及抓包分析(详解)
  16. mysql导入access2016_将 Access 2.0 和 Access 95 数据库导入到当前版本
  17. IE提示当前安全设置不允许下载该文件怎么办?
  18. 【2】深度神经网络的损失函数/激活函数
  19. 相对免赔额和绝对免赔额是什么意思,有什么区别?
  20. Weka中分类器指标的说明

热门文章

  1. 终端怎么进入hadoop_Ubuntu中使用终端运行Hadoop程序
  2. 2 环境设置_VS Code 虚拟环境设置
  3. sentinel卫星_IKONOS卫星 遥感影像解译数据 波段
  4. SQL left join 、right join 、inner join
  5. PYTHON2.day06
  6. PTS 有奖征稿活动官方示例
  7. redis高级命令2
  8. 再流弊的技术,也抵不过一次事故:兼谈技术管理
  9. Objective-C:NSArray的常见操作
  10. 去360总部参加网络信息安全会议经历