對于一個快速開發(fā)框架來說,離不開一個很重要的功能模塊那就是數(shù)據(jù)庫訪問椿猎,目前在日常開發(fā)中用的最多的當(dāng)然就是mybatis了,但是mybatis同樣也會給我們帶來很多重復(fù)的開發(fā)工作寿弱,例如一般的CRUD犯眠,也有很多開源框架在mybatis的基礎(chǔ)上又封裝了基礎(chǔ)CRUD的基礎(chǔ)類,但是這樣的壞處也顯而易見症革,和mybatis耦合很強筐咧,這里在我們的框架中,我們直接集成國內(nèi)比較好的mybatis組件-mybatis plus噪矛,這個組件在github上的人氣也很高量蕊,因為其底層原理很簡單,所以大家也可以借助于該組件做一些深度二開艇挨,并且與mybatis沒有強耦合残炮,是兩個獨立的jar包。mybatis plus基于mybatis定義了很多Base范性基類缩滨,開發(fā)者只要將自己的Mapper和service繼承自這些范性基類就可以直接繼承基礎(chǔ)的CRUD的方法势就,可以大幅減少代碼量。
下面我們就拿上一篇提到的系統(tǒng)日志記錄數(shù)據(jù)庫的功能來舉例子脉漏,讓大家體驗下在自己的框架中集成mybatis plus苞冯。
POM增加依賴
在之前框架的POM中新增以下依賴,因為我們框架是基于springboot開發(fā)所以這里我們直接使用mybatis plus為springboot開發(fā)的組件‘mybatis-plus-boot-starter’鸠删,可以更加方便和springboot集成抱完,當(dāng)然你也可以依賴mybatis plus基礎(chǔ)庫,但是要做些配置,具體可以參考官網(wǎng)文檔汗唱,所以這里偷懶直接用了boot組件亿虽。
除了依賴mybatis plus的庫谍夭,當(dāng)然訪問數(shù)據(jù)庫還要依賴相關(guān)數(shù)據(jù)庫的connector阅羹,只要是mybatis支持的數(shù)據(jù)庫熟丸,當(dāng)然plus也都可以支持是钥,例子中我們用了大家日常用的最多的mysql讥巡,使用其他數(shù)據(jù)庫的需要替換掉依賴的數(shù)據(jù)庫connector老翘,yml或property里的配置也需要進行調(diào)整芹啥。
<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相關(guān)資料可以查看github,里面的文檔還是比較完善的:https://github.com/baomidou/mybatis-plus
配置
因為mybatis plus功能太完善铺峭,框架中不需要做任何二開墓怀,直接使用,我們直接拿上一篇提到的日志模塊來舉例卫键,上一篇是寫到文件中傀履,這里我們將同樣的數(shù)據(jù)寫到數(shù)據(jù)庫中。
首先我們在數(shù)據(jù)庫中建立一張名叫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相關(guān)信息,plus中有很多配置參數(shù)梆暮,這里只是配置了日常會用到的一些參數(shù)配置,還有其他的配置大家可以參考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:
# 數(shù)據(jù)庫相關(guān)配置
db-config:
#主鍵類型 AUTO:"數(shù)據(jù)庫ID自增", INPUT:"用戶輸入ID",ID_WORKER:"全局唯一ID (數(shù)字類型唯一ID)", UUID:"全局唯一ID UUID";
id-type: id_worker
#字段策略 IGNORED:"忽略判斷",NOT_NULL:"非 NULL 判斷"),NOT_EMPTY:"非空判斷"
field-strategy: not_empty
#駝峰下劃線轉(zhuǎn)換
column-underline: true
#數(shù)據(jù)庫大寫下劃線轉(zhuǎn)換
#capital-mode: true
#邏輯刪除配置
logic-delete-value: 0
logic-not-delete-value: 1
db-type: h2
#刷新mapper 調(diào)試神器
refresh: true
# 原生配置
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
定義DO、Mapper治专、Service類
數(shù)據(jù)庫sys_log我們需要定義一個對應(yīng)的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;
//請求參數(shù)
private String params;
//執(zhí)行時長(毫秒)
private Long time;
//IP地址
private String ip;
//創(chuàng)建時間
private Date createDate;
//...省略setter遭顶、getter
}
大家一定注意到這里和其他的POJO的區(qū)別张峰,那就是在類名前面和id字段定義前面都有注解,這里簡單解釋下棒旗。和mybatis一樣喘批,我們?nèi)粘⒁粋€DO類和數(shù)據(jù)庫表關(guān)聯(lián)起來有兩種方法,一種是使用傳統(tǒng)的mapper.xml將DO類和數(shù)據(jù)庫表關(guān)聯(lián)起來铣揉,字段名如果不一樣的饶深,也需要進行字段之間的映射關(guān)系定義,還有一定方法是在DO類中定義注解逛拱,來將原先定義在XML中的信息定義到注解里敌厘。當(dāng)然plus會對這種傳統(tǒng)的定義方法進行改良,我們只需要在DO類前面加上@TableName(“XXX”)在注解的value中寫上數(shù)據(jù)庫表名就可以將該DO類與對應(yīng)的數(shù)據(jù)庫表映射起來了朽合。如果表中的字段和我們定義的DO類的字段名稱完全一樣或者數(shù)據(jù)庫表字段只是用下劃線替代了DO類中字段的駝峰結(jié)構(gòu)俱两,那么plus會自動進行映射字段饱狂,如果是將下劃線轉(zhuǎn)為駝峰定義需要在上面的配置中將轉(zhuǎn)換設(shè)置為true,column-underline: true
宪彩。
還可以看到我們在id字段定義的前面加上了@TableID休讳,該注解只可以定義在使用int或者Long定義的字段上用于自增id生成,在plus的配置中還可以配置生成id的算法尿孔,這里plus官方推薦的是使用開源sequence項目生成的id俊柔,只需要在yml中plus配置下配置id-type: id_worker
就可以了。
定義好了DO后活合,還需要和mybatis一樣雏婶,還需要定義mapper接口,下面我們看下我們要實現(xiàn)SysLog的增刪改查需要怎樣定義一個mapper接口白指。
@Mapper
public interface SysLogMapper extends BaseMapper<SysLogDO> {
}
就是這么簡單尚骄,如果只是基本的增刪改查就是這么簡單,一個方法都不需要定義侵续,只需要讓mapper接口繼承自BaseMapper這個范性基類倔丈,里面的范型定義為需要操作的DO類。我們看下BaseMapper源碼就知道為什么這么簡單就可以實現(xiàn)常用的增刪改查功能了状蜗。
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);
}
是不是從這里就能發(fā)現(xiàn)需五,我們常用的一些數(shù)據(jù)庫操作都包涵在里面了,包括分頁也都在里面轧坎,是不是一下子效率提升了很多宏邮。
當(dāng)然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);
}
}
從這里可以發(fā)現(xiàn)只需要讓service實現(xiàn)類繼承plus的ServiceImpl范型類就可以了缸血,在范型類中需要定義上這個service對應(yīng)的mapper類和實體DO類蜜氨,然后在service實現(xiàn)類中就可以通過this調(diào)用上面我們看到的常用的數(shù)據(jù)庫表操作方法了。
能解決大量重復(fù)代碼的開發(fā)工作的核心就是這個ServiceImpl范型類和上面提到的BaseMapper接口捎泻,這里建議大家都可以看看ServiceImpl的源碼飒炎,這里的設(shè)計方法其實可以用到很多我們常用的代碼中。
自動代碼生成
當(dāng)然大家也會發(fā)現(xiàn)上面寫的DO笆豁、Mapper郎汪、Service類也是一個重復(fù)的過程,我們可以通過plus為我們提供的自動代碼生成方法來自動生成這些DO闯狱、Mapper煞赢、Service代碼,這里我們可以很方便的實現(xiàn)這些重復(fù)的代碼哄孤,具體可以參考test目錄下的GeneratorServiceEntity類照筑,在類里面需要配置數(shù)據(jù)庫的相關(guān)信息,還有需要自動生成的類信息。都配置好厚直接執(zhí)行這個Test方法就可以自動生成這些類了凝危,減少了很多重復(fù)的工作饭弓。
總結(jié)
因為目前的mybatis和mybatis plus在orm這塊已經(jīng)做的非常完善了,真的沒必要再自研一套媒抠,直接拿來用弟断,對于mybatis的源碼建議大家有空也可以讀讀,不難趴生,但是里面涉及到很多好的框架設(shè)計方法阀趴,值得去學(xué)習(xí)。
本篇對應(yīng)的代碼tag是v0.2苍匆,大家以點擊下載https://github.com/feiweiwei/MkFramework4java/releases/tag/v0.2刘急,當(dāng)然也可以通過git clone –b v0.2 https://github.com/feiweiwei/MkFramework4java.git
下載。