引入MybatisPlus后对分层结构的影响以及解决方案

  • Post author:
  • Post category:其他





在之前写

分层模型以及代码工程化规范

的时候写到了分层规范中有说到DAO数据层,当项目架构中只有Mybatis的时候显然mapper接口(实际是mapper接口在Mybatis中生成的代理类)本身就是DAO层,但当引入MybatisPlus以后,分层结构会收到什么样的影响呢?应该如何处理这样的影响?本文主要探讨的就是这两个问题。



一、多了一层?

显而易见的是,MybatisPlus操作数据库是对Mybatis的mapper进行了通用扩展,同时提供了通用操作的api,当使用MybatisPlus的api时,放在service个人认为并不那么合适的,原因是其api带有sql条件的构造,希望能尽量抽出一层来写MybatisPlus的代码。

但是如果抽出一层,这一层和mapper都是操作数据库的DAO层,使用和维护的时候会对程序员造成一定的困扰,service层的代码中既有Mapper又有DAO。另一方面,会造成纯sql维护在Mapper中,MybatisPlus的API使用封装在DAO中,由于Mapper中有MybatisPlus的扩展,分开维护后导致职责不清,且会造成一定的歧义和不便。

总结起来,如果多一层,一方面,两种组件一起工作,对编程造成了一定的影响,另一方面,两种组件分别各自维护,其中一个组件却拥有一部分另一个组件的能力,维护起来并不方便,且容易混淆。



二、架空Mapper

那么可以想到的是可以把Mapper架空,单独维护DAO,如果需要调用mapper,就通过DAO去调用。

当然,这样做是可以的,但是很大程度上依赖于口头约定,并且需要强手动维护DAO,每次Mapper增加方法,DAO需要同时增加方法,但是也可以不去加,而不加的话,会导致有些程序员偷懒直接去调用Mapper。

另一方面,没有约束的维护,导致规范性不强。

所以我们应该怎么做?



三、 引入装饰器模式

先说一下引入装饰器模式以后的类结构图:

在这里插入图片描述

这里使用了装饰器模式,这样做的好处是:

  1. DAO做了增强,同时整合了Mapper和MybatisPlus所有的能力,可以在同一个地方进行维护;
  2. 强制性的接口实现被迫让DAO必须和Mapper保持一致,DAO可以利用MybatisPlus的能力做自己的扩展,而Mapper扩展自己的同时强制DAO同时扩展,维护起来不会混乱,更加规范化管理和维护,维护成本更低;
  3. 架空Mapper,避免多组件同时使用。

事实上,从Mapper本身的角度来看,也是对Mybatis的一种扩展,这里使用装饰器模式刚好也符合这一特点,正如装饰器本身的作用:

允许向一个现有的对象添加新的功能,同时又不改变其结构

(另外需要说明的一点,BaseDAO的作用只是为了让装饰器模式中统一的代码放在一起,减少创建DAO时要编写的代码,并不是装饰器模式的主体部分。)



四、 沿伸

提出一个问题:这里为什么是装饰器模式,而不是代理模式?

我们知道,代理模式和装饰器模式是非常相似的,那为什么这里是装饰器模式,而不是代理模式呢?

代理模式本身更侧重于代理,它是对原始接口已有能力的一个代理和扩展,并且自己将代理对象管理起来,并不对外暴露。

而装饰器模式更侧重于功能增强,可以是已有能力,也可以是派生能力,且组合的对象可以对外暴露,由外部传入。

上述方案的组合对象由spring从外部注入,且功能上更侧重于功能增强。因此,这里采用的就是装饰器模式。



总结

其实个人在选择这样的写法之前是下意识的,可能因为平时使用的设计模式比较多,自然而然选择了装饰器模式,而回过头来分析,选择装饰器模式也确实可以带来很大的便利性,上述也分析过了。可能还有很多种解决方案,如果这篇文章有人看的话可以提出自己的想法和意见。



版权声明:本文为xzazj01原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。