摘要:原博地址本文介紹如何用編寫高度自定義的代碼生成器是一款優秀的持久層框架,它支持定制化存儲過程以及高級映射。避免了幾乎所有的代碼和手動設置參數以及獲取結果集。
原博地址https://laboo.top/2018/11/26/a-db/#more
本文介紹如何用Java編寫高度自定義的代碼生成器
MyBatis 是一款優秀的持久層框架,它支持定制化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或注解來配置和映射原生信息。
上面這一段話來自Mybatis官網的介紹, 初用Mybatis時感覺這個框架相比于JDBC優雅多了, 用起來也如官網說的非常簡單。但是用了一段時間之后, 弊端就慢慢凸顯出來了
使用Mybatis時不得不為每個表創建一個Entity.java、Mapper.xml(Mapper可以融合入Dao中)、Dao.java,Service.java 層次很清晰, 但是太多重復性的工作了, 費時間且易于出錯
并且當數據庫發生一點改動的時候... 苦不堪言
后來出現了自動生成代碼的插件, 但是總是不盡人意, 不能隨心所欲地控制, 畢竟每個人的需求都不一樣
本文就來介紹如何簡單的編寫一個自己的代碼生成器
項目源碼mybatis-generator
代碼實現實現的思路很簡單, 首先查詢數據庫的表結構, 得到列名, 列類型...等信息
創建文件模版, 將這些信息插入模版中, 最后打包模版進壓縮包導出
代碼實現 一共五個Java類
TableDO
ColumnDO
GeneratorMapper
GeneratorUtils
GeneratorService
首先來看兩個實體類
TableDO 和 ColumnDOTableDO 存放表名, 對于的類名, 以及列信息
完整類代碼 TableDO.java
public class TableDO { private String tableName; private Listcolumns; private String className; private String suffix; // get()... set()... }
ColumnDO 存放列名, 數據庫字段類型, 以及對應Java中的屬性名和類型
完整類代碼 ColumnDO.java
public class ColumnDO { private String columnName; private String dataType; private String attrName; private String attrLowerName; private String attrType; // get()... set()... }GeneratorMapper
在GeneratorMapper 中, 我們通過表名查詢表自動的信息
完整類代碼 GeneratorMapper.java
@Mapper public interface GeneratorMapper { @Select("select column_name columnName, data_type dataType from information_schema.columns where table_name = #{tableName} and table_schema = (select database()) order by ordinal_position") ListGeneratorUtilslistColumns(String tableName); }
在GeneratorUtils 中進行類信息與模版之間的轉換
完整類代碼 GeneratorUtils.java
將表信息放入Velocity模版的上下文中
Mapmap = new HashMap<>(); map.put("tableName", table.getTableName()); map.put("className", table.getClassName()); map.put("pathName", getPackageName().substring(getPackageName().lastIndexOf(".") + 1)); map.put("columns", table.getColumns()); map.put("package", getPackageName()); map.put("suffix", table.getSuffix()); Properties prop = new Properties(); prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); Velocity.init(prop); VelocityContext context = new VelocityContext(map);
添加模版
Listtemplates = new ArrayList<>(); templates.add("mybatis/Model.java.vm"); templates.add("mybatis/Query.java.vm"); templates.add("mybatis/Dao.java.vm"); templates.add("mybatis/Mapper.xml.vm"); templates.add("mybatis/Service.java.vm");
編譯模版
StringWriter sw = new StringWriter(); Template tpl = Velocity.getTemplate(template, "UTF-8"); tpl.merge(context, sw);
Utils類完成了生成代碼的主要工作, 但是代碼也是比較簡單的
GeneratorService在Service 中注入Mapper 查詢列信息, 并用Utils生成代碼, 然后導出壓縮包
完整類代碼 GeneratorService.java
@Service public class GeneratorService { @Resource private GeneratorMapper generatorMapper; @Resource private Environment environment; public void generateZip(String[] tableNames, String zipPath) throws IOException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(outputStream); for (String tableName : tableNames) { TableDO table = new TableDO(); table.setTableName(tableName); table.setColumns(generatorMapper.listColumns(tableName)); GeneratorUtils.generatorCode(table, zip,getConfig()); } IOUtils.closeQuietly(zip); FileOutputStream file = new FileOutputStream(zipPath); file.write(outputStream.toByteArray()); file.close(); } // getConfig ... }VM模版
自己寫代碼生成器的好處就是, 可以根據需求定制自己的模版, 下面是我的幾個模版可以供參考
Mapper.xml.vm
Dao.java.vm
Service.java.vm
Model.java.vm
Query.java.vm
生成的代碼是在commons-mybatis架構下使用的
Dao.java.vmpackage ${package}.database.dao; import ${package}.database.model.${className}${suffix}; import org.apache.ibatis.annotations.Mapper; import org.laziji.commons.mybatis.dao.${suffix}Dao; @Mapper public interface ${className}Dao extends ${suffix}Dao<${className}${suffix}> { }...
其余模版
使用 配置文件在resources下創建application-${name}.yml文件, ${name}隨意, 例如: application-example.yml, 可創建多個
配置文件內容如下, 填入數據庫配置, 以及生成代碼的包名, 源文件路徑
spring: datasource: url: jdbc:mysql://xxx.xxx.xxx.xxx:3306/xxxx?characterEncoding=utf-8 username: xxxxxx password: xxxxxx generator: package: com.xxx.xxx resources: mapperTest
在test文件下創建測試類
@ActiveProfiles("example")中填入剛才配置文件名的name
tableNames需要生成的表, 可以多個
zipPath 代碼導出路徑
運行測試方法即可
package pg.laziji.generator; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; import pg.laziji.generator.mybatis.GeneratorService; import javax.annotation.Resource; import java.io.IOException; @ActiveProfiles("example") @RunWith(SpringRunner.class) @SpringBootTest public class ExampleTest { @Resource private GeneratorService generatorService; @Test public void test() throws IOException { String[] tableNames = new String[]{"example_table1", "example_table2"}; String zipPath = "/home/code.zip"; generatorService.generateZip(tableNames,zipPath); } }
歡迎關注我的博客公眾號
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72444.html
摘要:通過插件更優雅地生成和的樣板代碼通過插件不污染地實現優雅分頁。使用步驟引入依賴,在或的配置中進行配置。提供語法提示自動補全錯誤提示導航功能。該插件提供了類似的功能,根據接口的方法名推斷含義,然后在中直接生成對應的。 團隊使用Mybatis作為數據庫訪問框架。不同于Hibernate這種采用經典面向對象思想設計的ORM框架,Mybatis是面向過程的,它只做了過程到SQL語句的映射。兩者...
摘要:一級緩存值得注意的地方默認就是支持一級緩存的,并不需要我們配置和整合后進行代理開發,不支持一級緩存,和整合,按照的模板去生成代理對象,模板中在最后統一關閉。總結的一級緩存是級別的。 前言 本文主要講解Mybatis的以下知識點: Mybatis緩存 一級緩存 二級緩存 與Ehcache整合 Mapper代理 使用Mapper代理就不用寫實現類了 逆向工程 自動生成代碼 ...
摘要:是最流行的關系型數據庫管理系統之一,在應用方面,是最好的,關系數據庫管理系統應用軟件。是一種關系數據庫管理系統,關系數據庫將數據保存在不同的表中,而不是將所有數據放在一個大倉庫內,這樣就增加了速度并提高了靈活性。 本章主要是對MyBatis-Plus的初步介紹,包括一些背景知識、環境搭建、初步使用等知識和例子。對于背景知識,主要包含對MyBatis-Plus的特性介紹、為什么使用MyB...
摘要:最終能和面試官聊的開心愉快投緣的叫面霸。能夠與很好的集成提供映射標簽,支持對象與數據庫的字段關系映射提供對象關系映射標簽,支持對象關系組件維護。使用可以有效的防止注入,提高系統安全性。 showImg(https://segmentfault.com/img/bVbsSlt?w=358&h=269); 一、概述 面試,難還是不難?取決于面試者的底蘊(氣場+技能)、心態和認知及溝通技巧。...
摘要:得到用戶信息,將用戶信息存儲到一級緩存中。如果中間去執行操作執行插入更新刪除,則會清空中的一級緩存,這樣做的目的為了讓緩存中存儲的是最新的信息,避免臟讀。 基礎: 1、 概念:Java當中的一個持久層框架。2、 特點、優勢:(1)把java代碼和SQL代碼做了一個完全分離。(2)良好支持復雜對象的映射(輸入映射、輸出映射)(3)使用動態SQL,可以預防SQL注入。3、 ...
閱讀 2683·2021-09-26 10:19
閱讀 2136·2021-09-24 10:27
閱讀 2520·2021-09-01 10:42
閱讀 2302·2019-08-29 16:09
閱讀 2485·2019-08-29 15:17
閱讀 1447·2019-08-29 15:09
閱讀 633·2019-08-29 11:14
閱讀 2301·2019-08-26 13:25