动手写个java快速开发框架-(2)集成mybatis plus

对于一个快速开发框架来说,离不开一个很重要的功能模块那就是数据库访问,目前在日常开发中用的最多的当然就是mybatis了,但是mybatis同样也会给我们带来很多重复的开发工作,例如一般的CRUD,也有很多开源框架在mybatis的基础上又封装了基础CRUD的基础类,但是这样的坏处也显而易见,和mybatis耦合很强,这里在我们的框架中,我们直接集成国内比较好的mybatis组件-mybatis plus,这个组件在github上的人气也很高,因为其底层原理很简单,所以大家也可以借助于该组件做一些深度二开,并且与mybatis没有强耦合,是两个独立的jar包。mybatis plus基于mybatis定义了很多Base范性基类,开发者只要将自己的Mapper和service继承自这些范性基类就可以直接继承基础的CRUD的方法,可以大幅减少代码量。

下面我们就拿上一篇提到的系统日志记录数据库的功能来举例子,让大家体验下在自己的框架中集成mybatis plus。

POM增加依赖

在之前框架的POM中新增以下依赖,因为我们框架是基于springboot开发所以这里我们直接使用mybatis plus为springboot开发的组件‘mybatis-plus-boot-starter’,可以更加方便和springboot集成,当然你也可以依赖mybatis plus基础库,但是要做些配置,具体可以参考官网文档,所以这里偷懒直接用了boot组件。

除了依赖mybatis plus的库,当然访问数据库还要依赖相关数据库的connector,只要是mybatis支持的数据库,当然plus也都可以支持,例子中我们用了大家日常用的最多的mysql,使用其他数据库的需要替换掉依赖的数据库connector,yml或property里的配置也需要进行调整。

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>${mybatis-plus-boot-starter.version}</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql.version}</version>
</dependency>

mybatis plus相关资料可以查看github,里面的文档还是比较完善的:https://github.com/baomidou/mybatis-plus

配置

因为mybatis plus功能太完善,框架中不需要做任何二开,直接使用,我们直接拿上一篇提到的日志模块来举例,上一篇是写到文件中,这里我们将同样的数据写到数据库中。

首先我们在数据库中建立一张名叫sys_log的表,具体的建表sql可以参看sql目录下的建表语句,里面的字段和上一篇定义的SysLog实体类的字段一样,具体参看源码。

接下来在application-xxx.yml中配置datasource:

spring:
  datasource:
    url: jdbc:mysql://123.206.118.12:3306/mkframework?useUnicode=true&characterEncoding=utf-8
    username: root
    password: Dnn198411!
    driverClassName: com.mysql.jdbc.Driver

在application.yml中配置mybatis-plus相关信息,plus中有很多配置参数,这里只是配置了日常会用到的一些参数配置,还有其他的配置大家可以参考plus的github官方文档资料。

#mybatis
mybatis-plus:
  mapper-locations: classpath:/mapper/*Mapper.xml
  #实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.monkey01.common.domain
#  typeEnumsPackage: com.baomidou.springboot.entity.enums
  global-config:
    # 数据库相关配置
    db-config:
      #主键类型  AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
      id-type: id_worker
      #字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"
      field-strategy: not_empty
      #驼峰下划线转换
      column-underline: true
      #数据库大写下划线转换
      #capital-mode: true
      #逻辑删除配置
      logic-delete-value: 0
      logic-not-delete-value: 1
      db-type: h2
    #刷新mapper 调试神器
    refresh: true
  # 原生配置
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: false

定义DO、Mapper、Service类

数据库sys_log我们需要定义一个对应的DO和它进行ORM映射。

@TableName("sys_log")
public class SysLogDO implements Serializable {
    @TableId
    private Long id;
    //用户名
    private String username;
    //用户操作
    private String operation;
    //请求方法
    private String method;
    //请求URL
    private String url;
    //请求参数
    private String params;
    //执行时长(毫秒)
    private Long time;
    //IP地址
    private String ip;
    //创建时间
    private Date createDate;
    //...省略setter、getter
    }

大家一定注意到这里和其他的POJO的区别,那就是在类名前面和id字段定义前面都有注解,这里简单解释下。和mybatis一样,我们日常将一个DO类和数据库表关联起来有两种方法,一种是使用传统的mapper.xml将DO类和数据库表关联起来,字段名如果不一样的,也需要进行字段之间的映射关系定义,还有一定方法是在DO类中定义注解,来将原先定义在XML中的信息定义到注解里。当然plus会对这种传统的定义方法进行改良,我们只需要在DO类前面加上@TableName(“XXX”)在注解的value中写上数据库表名就可以将该DO类与对应的数据库表映射起来了。如果表中的字段和我们定义的DO类的字段名称完全一样或者数据库表字段只是用下划线替代了DO类中字段的驼峰结构,那么plus会自动进行映射字段,如果是将下划线转为驼峰定义需要在上面的配置中将转换设置为true,column-underline: true

还可以看到我们在id字段定义的前面加上了@TableID,该注解只可以定义在使用int或者Long定义的字段上用于自增id生成,在plus的配置中还可以配置生成id的算法,这里plus官方推荐的是使用开源sequence项目生成的id,只需要在yml中plus配置下配置id-type: id_worker就可以了。

定义好了DO后,还需要和mybatis一样,还需要定义mapper接口,下面我们看下我们要实现SysLog的增删改查需要怎样定义一个mapper接口。

@Mapper
public interface SysLogMapper extends BaseMapper<SysLogDO> {
}

就是这么简单,如果只是基本的增删改查就是这么简单,一个方法都不需要定义,只需要让mapper接口继承自BaseMapper这个范性基类,里面的范型定义为需要操作的DO类。我们看下BaseMapper源码就知道为什么这么简单就可以实现常用的增删改查功能了。

public interface BaseMapper<T> {
    Integer insert(T var1);
    Integer deleteById(Serializable var1);
    Integer deleteByMap(@Param("cm") Map<String, Object> var1);
    Integer delete(@Param("ew") Wrapper<T> var1);
    Integer deleteBatchIds(@Param("coll") Collection<? extends Serializable> var1);
    Integer updateById(@Param("et") T var1);
    Integer update(@Param("et") T var1, @Param("ew") Wrapper<T> var2);
    T selectById(Serializable var1);
    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> var1);
    List<T> selectByMap(@Param("cm") Map<String, Object> var1);
    T selectOne(@Param("ew") Wrapper<T> var1);
    Integer selectCount(@Param("ew") Wrapper<T> var1);
    List<T> selectList(@Param("ew") Wrapper<T> var1);
    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> var1);
    List<Object> selectObjs(@Param("ew") Wrapper<T> var1);
    IPage<T> selectPage(IPage<T> var1, @Param("ew") Wrapper<T> var2);
    IPage<Map<String, Object>> selectMapsPage(IPage<T> var1, @Param("ew") Wrapper<T> var2);
}

是不是从这里就能发现,我们常用的一些数据库操作都包涵在里面了,包括分页也都在里面,是不是一下子效率提升了很多。

当然dao的mapper类定义好了以后就是定义service层的service类了。

@Service("sysLogService")
public class SysLogServiceImpl extends ServiceImpl<SysLogMapper, SysLogDO> implements SysLogService {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public void saveSysLog(SysLogDO sysLogDO) {
        this.saveSysLogFile(sysLogDO);
        this.saveSysLogDB(sysLogDO);
    }
    private void saveSysLogFile(SysLogDO sysLogDO){
        logger.info(sysLogDO.toString());
    }
    private boolean saveSysLogDB(SysLogDO sysLogDO) {
        return this.save(sysLogDO);
    }
}

从这里可以发现只需要让service实现类继承plus的ServiceImpl范型类就可以了,在范型类中需要定义上这个service对应的mapper类和实体DO类,然后在service实现类中就可以通过this调用上面我们看到的常用的数据库表操作方法了。

能解决大量重复代码的开发工作的核心就是这个ServiceImpl范型类和上面提到的BaseMapper接口,这里建议大家都可以看看ServiceImpl的源码,这里的设计方法其实可以用到很多我们常用的代码中。

自动代码生成

当然大家也会发现上面写的DO、Mapper、Service类也是一个重复的过程,我们可以通过plus为我们提供的自动代码生成方法来自动生成这些DO、Mapper、Service代码,这里我们可以很方便的实现这些重复的代码,具体可以参考test目录下的GeneratorServiceEntity类,在类里面需要配置数据库的相关信息,还有需要自动生成的类信息。都配置好厚直接执行这个Test方法就可以自动生成这些类了,减少了很多重复的工作。

总结

因为目前的mybatis和mybatis plus在orm这块已经做的非常完善了,真的没必要再自研一套,直接拿来用,对于mybatis的源码建议大家有空也可以读读,不难,但是里面涉及到很多好的框架设计方法,值得去学习。

本篇对应的代码tag是v0.2,大家以点击下载https://github.com/feiweiwei/MkFramework4java/releases/tag/v0.2,当然也可以通过git clone –b v0.2 https://github.com/feiweiwei/MkFramework4java.git下载。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,165评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,503评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,295评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,589评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,439评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,342评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,749评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,397评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,700评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,740评论 2 313
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,523评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,364评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,755评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,024评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,297评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,721评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,918评论 2 336

推荐阅读更多精彩内容