您好,登錄后才能下訂單哦!
本篇內容主要講解“如何獲取表結構”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何獲取表結構”吧!
一、介紹
我記得最早剛步入互聯網行業的時候,當時按照 MVC 的思想和模型,每次開發新功能,會依次編寫 dao、service、controller相關服務類,包括對應的 dto、entity、vo 等等實體類,如果有多張單表,也會重復的編寫相似的代碼,現在回想起來,感覺當時自己好像處于石器時代!
實際上,當仔細的總結一下,對于任何一張單表的操作,基本都是圍繞增(Create )、刪(Delete )、改(Update )、查(Retrieve )四個方向進行數據操作,簡稱 CRUD!
他們除了表名和存儲空間不一樣,基本的 CRUD 思路基本都是一樣的。
為了解決這些重復勞動的痛點,業界逐漸開源了一批代碼生成器,目的也很簡單,就是為了減少手工操作的繁瑣,集中精力在業務開發上,提升開發效率。
而今天,我們所要介紹的也是代碼生成器,很多初學者可能覺得代碼生成器很高深。代碼生成器其實是一個很簡單的東西,一點都不高深。
當你看完本文的時候,你會完全掌握代碼生成器的邏輯,甚至可以根據自己的項目情況,進行深度定制。
二、實現思路
下面我們就以SpringBoot項目為例,數據持久化操作采用Mybatis,數據庫采用Mysql,編寫一個自動生成增、刪、改、查等基礎功能的代碼生成器,內容包括controller、service、dao、entity、dto、vo等信息。
實現思路如下:
第一步:獲取表字段名稱、類型、表注釋等信息
第二步:基于 freemarker 模板引擎,編寫相應的模板
第三步:根據對應的模板,生成相應的 java 代碼
2.1、獲取表結構
首先我們創建一張test_db表,腳本如下:
CREATE TABLE test_db ( id bigint(20) unsigned NOT NULL COMMENT '主鍵ID', name varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '名稱', is_delete tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否刪除 1:已刪除;0:未刪除', create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間', update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間', PRIMARY KEY (id), KEY idx_create_time (create_time) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='測試表';
表創建完成之后,基于test_db表,我們查詢對應的表結果字段名稱、類型、備注信息,這些關鍵信息將用于后續進行代碼生成器所使用!
# 獲取對應表結構 SELECT column_name, data_type, column_comment FROM information_schema.columns WHERE table_schema = 'yjgj_base' AND table_name = 'test_db'
同時,獲取對應表注釋,用于生成備注信息!
# 獲取對應表注釋 SELECT TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'yjgj_base' AND table_name = 'test_db'
2.2、編寫模板
編寫mapper.ftl模板,涵蓋新增、修改、刪除、查詢等信息
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="${daoPackageName}.${daoName}"> <!--BaseResultMap--> <resultMap id="BaseResultMap" type="${entityPackageName}.${entityName}"> <#list columns as pro> <#if pro.proName == primaryId> <id column="${primaryId}" property="${primaryId}" jdbcType="${pro.fieldType}"/> <#else> <result column="${pro.fieldName}" property="${pro.proName}" jdbcType="${pro.fieldType}"/> </#if> </#list> </resultMap> <!--Base_Column_List--> <sql id="Base_Column_List"> <#list columns as pro> <#if pro_index == 0>${pro.fieldName}<#else>,${pro.fieldName}</#if> </#list> </sql> <!--批量插入--> <insert id="insertList" parameterType="java.util.List"> insert into ${tableName} ( <#list columns as pro> <#if pro_index == 0>${pro.fieldName},<#elseif pro_index == 1>${pro.fieldName}<#else>,${pro.fieldName}</#if> </#list> ) values <foreach collection ="list" item="obj" separator =","> <trim prefix=" (" suffix=")" suffixOverrides=","> <#list columns as pro> ${r"#{obj." + pro.proName + r"}"}, </#list> </trim> </foreach > </insert> <!--按需新增--> <insert id="insertPrimaryKeySelective" parameterType="${entityPackageName}.${entityName}"> insert into ${tableName} <trim prefix="(" suffix=")" suffixOverrides=","> <#list columns as pro> <if test="${pro.proName} != null"> ${pro.fieldName}, </if> </#list> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <#list columns as pro> <if test="${pro.proName} != null"> ${r"#{" + pro.proName + r",jdbcType=" + pro.fieldType +r"}"}, </if> </#list> </trim> </insert> <!-- 按需修改--> <update id="updatePrimaryKeySelective" parameterType="${entityPackageName}.${entityName}"> update ${tableName} <set> <#list columns as pro> <#if pro.fieldName != primaryId && pro.fieldName != primaryId> <if test="${pro.proName} != null"> ${pro.fieldName} = ${r"#{" + pro.proName + r",jdbcType=" + pro.fieldType +r"}"}, </if> </#if> </#list> </set> where ${primaryId} = ${r"#{" + "${primaryId}" + r",jdbcType=BIGINT}"} </update> <!-- 按需批量修改--> <update id="updateBatchByIds" parameterType="java.util.List"> update ${tableName} <trim prefix="set" suffixOverrides=","> <#list columns as pro> <#if pro.fieldName != primaryId && pro.fieldName != primaryId> <trim prefix="${pro.fieldName}=case" suffix="end,"> <foreach collection="list" item="obj" index="index"> <if test="obj.${pro.proName} != null"> when id = ${r"#{" + "obj.id" + r"}"} then ${r"#{obj." + pro.proName + r",jdbcType=" + pro.fieldType +r"}"} </if> </foreach> </trim> </#if> </#list> </trim> where <foreach collection="list" separator="or" item="obj" index="index" > id = ${r"#{" + "obj.id" + r"}"} </foreach> </update> <!-- 刪除--> <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> delete from ${tableName} where ${primaryId} = ${r"#{" + "${primaryId}" + r",jdbcType=BIGINT}"} </delete> <!-- 查詢詳情 --> <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long"> select <include refid="Base_Column_List"/> from ${tableName} where ${primaryId} = ${r"#{" + "${primaryId}" + r",jdbcType=BIGINT}"} </select> <!-- 按需查詢 --> <select id="selectByPrimaryKeySelective" resultMap="BaseResultMap" parameterType="${entityPackageName}.${entityName}"> select <include refid="Base_Column_List"/> from ${tableName} </select> <!-- 批量查詢--> <select id="selectByIds" resultMap="BaseResultMap" parameterType="java.util.List"> select <include refid="Base_Column_List"/> from ${tableName} <where> <if test="ids != null"> and ${primaryId} in <foreach item="item" index="index" collection="ids" open="(" separator="," close=")"> ${r"#{" + "item" + r"}"} </foreach> </if> </where> </select> <!-- 根據條件查詢 --> <select id="selectByMap" resultMap="BaseResultMap" parameterType="java.util.Map"> select <include refid="Base_Column_List"/> from ${tableName} </select> <!-- 查詢${entityName}總和 --> <select id="countPage" resultType="int" parameterType="${dtoPackageName}.${dtoName}"> select count(${primaryId}) from ${tableName} </select> <!-- 查詢${entityName}列表 --> <select id="selectPage" resultMap="BaseResultMap" parameterType="${dtoPackageName}.${dtoName}"> select <include refid="Base_Column_List"/> from ${tableName} limit ${r"#{" + "start,jdbcType=INTEGER" + r"}"},${r"#{" + "end,jdbcType=INTEGER" + r"}"} </select> </mapper>
編寫dao.ftl數據訪問模板
package ${daoPackageName}; import com.example.generator.core.BaseMapper; import java.util.List; import ${entityPackageName}.${entityName}; import ${dtoPackageName}.${dtoName}; /** * * @ClassName: ${daoName} * @Description: 數據訪問接口 * @author ${authorName} * @date ${currentTime} * */ public interface ${daoName} extends BaseMapper<${entityName}>{ int countPage(${dtoName} ${dtoName?uncap_first}); List<${entityName}> selectPage(${dtoName} ${dtoName?uncap_first}); }
編寫service.ftl服務接口模板
package ${servicePackageName}; import com.example.generator.core.BaseService; import com.example.generator.common.Pager; import ${voPackageName}.${voName}; import ${dtoPackageName}.${dtoName}; import ${entityPackageName}.${entityName}; /** * * @ClassName: ${serviceName} * @Description: ${entityName}業務訪問接口 * @author ${authorName} * @date ${currentTime} * */ public interface ${serviceName} extends BaseService<${entityName}> { /** * 分頁列表查詢 * @param request */ Pager<${voName}> getPage(${dtoName} request); }
編寫serviceImpl.ftl服務實現類模板
package ${serviceImplPackageName}; import com.example.generator.common.Pager; import com.example.generator.core.BaseServiceImpl; import com.example.generator.test.service.TestEntityService; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import ${daoPackageName}.${daoName}; import ${entityPackageName}.${entityName}; import ${dtoPackageName}.${dtoName}; import ${voPackageName}.${voName}; @Service public class ${serviceImplName} extends BaseServiceImpl<${daoName}, ${entityName}> implements ${serviceName} { private static final Logger log = LoggerFactory.getLogger(${serviceImplName}.class); /** * 分頁列表查詢 * @param request */ public Pager<${voName}> getPage(${dtoName} request) { List<${voName}> resultList = new ArrayList(); int count = super.baseMapper.countPage(request); List<${entityName}> dbList = count > 0 ? super.baseMapper.selectPage(request) : new ArrayList<>(); if(!CollectionUtils.isEmpty(dbList)){ dbList.forEach(source->{ ${voName} target = new ${voName}(); BeanUtils.copyProperties(source, target); resultList.add(target); }); } return new Pager(request.getCurrPage(), request.getPageSize(), count, resultList); } }
編寫controller.ftl控制層模板
package ${controllerPackageName}; import com.example.generator.common.IdRequest; import com.example.generator.common.Pager; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Objects; import ${servicePackageName}.${serviceName}; import ${entityPackageName}.${entityName}; import ${dtoPackageName}.${dtoName}; import ${voPackageName}.${voName}; /** * * @ClassName: ${controllerName} * @Description: 外部訪問接口 * @author ${authorName} * @date ${currentTime} * */ @RestController @RequestMapping("/${entityName?uncap_first}") public class ${controllerName} { @Autowired private ${serviceName} ${serviceName?uncap_first}; /** * 分頁列表查詢 * @param request */ @PostMapping(value = "/getPage") public Pager<${voName}> getPage(@RequestBody ${dtoName} request){ return ${serviceName?uncap_first}.getPage(request); } /** * 查詢詳情 * @param request */ @PostMapping(value = "/getDetail") public ${voName} getDetail(@RequestBody IdRequest request){ ${entityName} source = ${serviceName?uncap_first}.selectById(request.getId()); if(Objects.nonNull(source)){ ${voName} result = new ${voName}(); BeanUtils.copyProperties(source, result); return result; } return null; } /** * 新增操作 * @param request */ @PostMapping(value = "/save") public void save(${dtoName} request){ ${entityName} entity = new ${entityName}(); BeanUtils.copyProperties(request, entity); ${serviceName?uncap_first}.insert(entity); } /** * 編輯操作 * @param request */ @PostMapping(value = "/edit") public void edit(${dtoName} request){ ${entityName} entity = new ${entityName}(); BeanUtils.copyProperties(request, entity); ${serviceName?uncap_first}.updateById(entity); } /** * 刪除操作 * @param request */ @PostMapping(value = "/delete") public void delete(IdRequest request){ ${serviceName?uncap_first}.deleteById(request.getId()); } }
編寫entity.ftl實體類模板
package ${entityPackageName}; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; /** * * @ClassName: ${entityName} * @Description: ${tableDes!}實體類 * @author ${authorName} * @date ${currentTime} * */ public class ${entityName} implements Serializable { private static final long serialVersionUID = 1L; <#--屬性遍歷--> <#list columns as pro> <#--<#if pro.proName != primaryId && pro.proName != 'remarks' && pro.proName != 'createBy' && pro.proName != 'createDate' && pro.proName != 'updateBy' && pro.proName != 'updateDate' && pro.proName != 'delFlag' && pro.proName != 'currentUser' && pro.proName != 'page' && pro.proName != 'sqlMap' && pro.proName != 'isNewRecord' ></#if>--> /** * ${pro.proDes!} */ private ${pro.proType} ${pro.proName}; </#list> <#--屬性get||set方法--> <#list columns as pro> public ${pro.proType} get${pro.proName?cap_first}() { return this.${pro.proName}; } public ${entityName} set${pro.proName?cap_first}(${pro.proType} ${pro.proName}) { this.${pro.proName} = ${pro.proName}; return this; } </#list> }
編寫dto.ftl實體類模板
package ${dtoPackageName}; import com.example.generator.core.BaseDTO; import java.io.Serializable; /** * @ClassName: ${dtoName} * @Description: 請求實體類 * @author ${authorName} * @date ${currentTime} * */ public class ${dtoName} extends BaseDTO { }
編寫vo.ftl視圖實體類模板
package ${voPackageName}; import java.io.Serializable; /** * @ClassName: ${voName} * @Description: 返回視圖實體類 * @author ${authorName} * @date ${currentTime} * */ public class ${voName} implements Serializable { private static final long serialVersionUID = 1L; }
可能細心的網友已經看到了,在模板中我們用到了BaseMapper、BaseService、BaseServiceImpl等等服務類。
之所以有這三個類,是因為在模板中,我們有大量的相同的方法名包括邏輯也相似,除了所在實體類不一樣以外,其他都一樣,因此我們可以借助泛型類來將這些服務抽成公共的部分。
BaseMapper,主要負責將dao層的公共方法抽出來
package com.example.generator.core; import org.apache.ibatis.annotations.Param; import java.io.Serializable; import java.util.List; import java.util.Map; /** * @author pzblog * @Description * @since 2020-11-11 */ public interface BaseMapper<T> { /** * 批量插入 * @param list * @return */ int insertList(@Param("list") List<T> list); /** * 按需插入一條記錄 * @param entity * @return */ int insertPrimaryKeySelective(T entity); /** * 按需修改一條記錄(通過主鍵ID) * @return */ int updatePrimaryKeySelective(T entity); /** * 批量按需修改記錄(通過主鍵ID) * @param list * @return */ int updateBatchByIds(@Param("list") List<T> list); /** * 根據ID刪除 * @param id 主鍵ID * @return */ int deleteByPrimaryKey(Serializable id); /** * 根據ID查詢 * @param id 主鍵ID * @return */ T selectByPrimaryKey(Serializable id); /** * 按需查詢 * @param entity * @return */ List<T> selectByPrimaryKeySelective(T entity); /** * 批量查詢 * @param ids 主鍵ID集合 * @return */ List<T> selectByIds(@Param("ids") List<? extends Serializable> ids); /** * 查詢(根據 columnMap 條件) * @param columnMap 表字段 map 對象 * @return */ List<T> selectByMap(Map<String, Object> columnMap); }
BaseService,主要負責將service層的公共方法抽出來
package com.example.generator.core; import java.io.Serializable; import java.util.List; import java.util.Map; /** * @author pzblog * @Description 服務類 * @since 2020-11-11 */ public interface BaseService<T> { /** * 新增 * @param entity * @return boolean */ boolean insert(T entity); /** * 批量新增 * @param list * @return boolean */ boolean insertList(List<T> list); /** * 通過ID修改記錄(如果想全部更新,只需保證字段都不為NULL) * @param entity * @return boolean */ boolean updateById(T entity); /** * 通過ID批量修改記錄(如果想全部更新,只需保證字段都不為NULL) * @param list * @return boolean */ boolean updateBatchByIds(List<T> list); /** * 根據ID刪除 * @param id 主鍵ID * @return boolean */ boolean deleteById(Serializable id); /** * 根據ID查詢 * @param id 主鍵ID * @return */ T selectById(Serializable id); /** * 按需查詢 * @param entity * @return */ List<T> selectByPrimaryKeySelective(T entity); /** * 批量查詢 * @param ids * @return */ List<T> selectByIds(List<? extends Serializable> ids); /** * 根據條件查詢 * @param columnMap * @return */ List<T> selectByMap(Map<String, Object> columnMap); }
BaseServiceImpl,service層的公共方法具體實現類
package com.example.generator.core; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import java.io.Serializable; import java.util.List; import java.util.Map; /** * @author pzblog * @Description 實現類( 泛型說明:M 是 mapper 對象,T 是實體) * @since 2020-11-11 */ public abstract class BaseServiceImpl<M extends BaseMapper<T>, T> implements BaseService<T>{ @Autowired protected M baseMapper; /** * 新增 * @param entity * @return boolean */ @Override @Transactional(rollbackFor = {Exception.class}) public boolean insert(T entity){ return returnBool(baseMapper.insertPrimaryKeySelective(entity)); } /** * 批量新增 * @param list * @return boolean */ @Override @Transactional(rollbackFor = {Exception.class}) public boolean insertList(List<T> list){ return returnBool(baseMapper.insertList(list)); } /** * 通過ID修改記錄(如果想全部更新,只需保證字段都不為NULL) * @param entity * @return boolean */ @Override @Transactional(rollbackFor = {Exception.class}) public boolean updateById(T entity){ return returnBool(baseMapper.updatePrimaryKeySelective(entity)); } /** * 通過ID批量修改記錄(如果想全部更新,只需保證字段都不為NULL) * @param list * @return boolean */ @Override @Transactional(rollbackFor = {Exception.class}) public boolean updateBatchByIds(List<T> list){ return returnBool(baseMapper.updateBatchByIds(list)); } /** * 根據ID刪除 * @param id 主鍵ID * @return boolean */ @Override @Transactional(rollbackFor = {Exception.class}) public boolean deleteById(Serializable id){ return returnBool(baseMapper.deleteByPrimaryKey(id)); } /** * 根據ID查詢 * @param id 主鍵ID * @return */ @Override public T selectById(Serializable id){ return baseMapper.selectByPrimaryKey(id); } /** * 按需查詢 * @param entity * @return */ @Override public List<T> selectByPrimaryKeySelective(T entity){ return baseMapper.selectByPrimaryKeySelective(entity); } /** * 批量查詢 * @param ids * @return */ @Override public List<T> selectByIds(List<? extends Serializable> ids){ return baseMapper.selectByIds(ids); } /** * 根據條件查詢 * @param columnMap * @return */ @Override public List<T> selectByMap(Map<String, Object> columnMap){ return baseMapper.selectByMap(columnMap); } /** * 判斷數據庫操作是否成功 * @param result 數據庫操作返回影響條數 * @return boolean */ protected boolean returnBool(Integer result) { return null != result && result >= 1; } }
在此,還封裝來其他的類,例如 dto 公共類BaseDTO,分頁類Pager,還有 id 請求類IdRequest。
BaseDTO公共類
public class BaseDTO implements Serializable { /** * 請求token */ private String token; /** * 當前頁數 */ private Integer currPage = 1; /** * 每頁記錄數 */ private Integer pageSize = 20; /** * 分頁參數(第幾行) */ private Integer start; /** * 分頁參數(行數) */ private Integer end; /** * 登錄人ID */ private String loginUserId; /** * 登錄人名稱 */ private String loginUserName; public String getToken() { return token; } public BaseDTO setToken(String token) { this.token = token; return this; } public Integer getCurrPage() { return currPage; } public BaseDTO setCurrPage(Integer currPage) { this.currPage = currPage; return this; } public Integer getPageSize() { return pageSize; } public BaseDTO setPageSize(Integer pageSize) { this.pageSize = pageSize; return this; } public Integer getStart() { if (this.currPage != null && this.currPage > 0) { start = (currPage - 1) * getPageSize(); return start; } return start == null ? 0 : start; } public BaseDTO setStart(Integer start) { this.start = start; return this; } public Integer getEnd() { return getPageSize(); } public BaseDTO setEnd(Integer end) { this.end = end; return this; } public String getLoginUserId() { return loginUserId; } public BaseDTO setLoginUserId(String loginUserId) { this.loginUserId = loginUserId; return this; } public String getLoginUserName() { return loginUserName; } public BaseDTO setLoginUserName(String loginUserName) { this.loginUserName = loginUserName; return this; } }
Pager分頁類
public class Pager<T extends Serializable> implements Serializable { private static final long serialVersionUID = -6557244954523041805L; /** * 當前頁數 */ private int currPage; /** * 每頁記錄數 */ private int pageSize; /** * 總頁數 */ private int totalPage; /** * 總記錄數 */ private int totalCount; /** * 列表數據 */ private List<T> list; public Pager(int currPage, int pageSize) { this.currPage = currPage; this.pageSize = pageSize; } public Pager(int currPage, int pageSize, int totalCount, List<T> list) { this.currPage = currPage; this.pageSize = pageSize; this.totalPage = (int) Math.ceil((double) totalCount / pageSize);; this.totalCount = totalCount; this.list = list; } public int getCurrPage() { return currPage; } public Pager setCurrPage(int currPage) { this.currPage = currPage; return this; } public int getPageSize() { return pageSize; } public Pager setPageSize(int pageSize) { this.pageSize = pageSize; return this; } public int getTotalPage() { return totalPage; } public Pager setTotalPage(int totalPage) { this.totalPage = totalPage; return this; } public int getTotalCount() { return totalCount; } public Pager setTotalCount(int totalCount) { this.totalCount = totalCount; return this; } public List<T> getList() { return list; } public Pager setList(List<T> list) { this.list = list; return this; } }
IdRequest公共請求類
public class IdRequest extends BaseDTO { private Long id; public Long getId() { return id; } public IdRequest setId(Long id) { this.id = id; return this; } }
2.3、編寫代碼生成器
前兩部分主要介紹的是如何獲取對應的表結構,以及代碼器運行之前的準備工作。
其實代碼生成器,很簡單,其實就是一個main方法,沒有想象中的那么復雜。
處理思路也很簡單,過程如下:
1、定義基本變量,例如包名路徑、模塊名、表名、轉換后的實體類、以及數據庫連接配置,我們可以將其寫入配置文件
2、讀取配置文件,封裝對應的模板中定義的變量
3、根據對應的模板文件和變量,生成對應的java文件
2.3.1、創建配置文件,定義變量
小編我用的是application.properties配置文件來定義變量,這個沒啥規定,你也可以自定義文件名,內容如下:
#包前綴 packageNamePre=com.example.generator #模塊名稱 moduleName=test #表 tableName=test_db #實體類名稱 entityName=TestEntity #主鍵ID primaryId=id #作者 authorName=pzblog #數據庫名稱 databaseName=yjgj_base #數據庫服務器IP地址 ipName=127.0.0.1 #數據庫服務器端口 portName=3306 #用戶名 userName=root #密碼 passWord=123456 #文件輸出路徑,支持自定義輸出路徑,如果為空,默認取當前工程的src/main/java路徑 outUrl=
2.3.2、根據模板生成對應的java代碼
首先,讀取配置文件變量
public class SystemConstant { private static Properties properties = new Properties(); static { try { // 加載上傳文件設置參數:配置文件 properties.load(SystemConstant.class.getClassLoader().getResourceAsStream("application.properties")); } catch (IOException e) { e.printStackTrace(); } } public static final String tableName = properties.getProperty("tableName"); public static final String entityName = properties.getProperty("entityName"); public static final String packageNamePre = properties.getProperty("packageNamePre"); public static final String outUrl = properties.getProperty("outUrl"); public static final String databaseName = properties.getProperty("databaseName"); public static final String ipName = properties.getProperty("ipName"); public static final String portName = properties.getProperty("portName"); public static final String userName = properties.getProperty("userName"); public static final String passWord = properties.getProperty("passWord"); public static final String authorName = properties.getProperty("authorName"); public static final String primaryId = properties.getProperty("primaryId"); public static final String moduleName = properties.getProperty("moduleName"); }
然后,封裝對應的模板中定義的變量
public class CodeService { public void generate(Map<String, Object> templateData) { //包前綴 String packagePreAndModuleName = getPackagePreAndModuleName(templateData); //支持對應實體插入在前面,需要帶上%s templateData.put("entityPackageName", String.format(packagePreAndModuleName + ".entity", templateData.get("entityName").toString().toLowerCase())); templateData.put("dtoPackageName", String.format(packagePreAndModuleName + ".dto", templateData.get("entityName").toString().toLowerCase())); templateData.put("voPackageName", String.format(packagePreAndModuleName + ".vo", templateData.get("entityName").toString().toLowerCase())); templateData.put("daoPackageName", String.format(packagePreAndModuleName + ".dao", templateData.get("entityName").toString().toLowerCase())); templateData.put("mapperPackageName", packagePreAndModuleName + ".mapper"); templateData.put("servicePackageName", String.format(packagePreAndModuleName + ".service", templateData.get("entityName").toString().toLowerCase())); templateData.put("serviceImplPackageName", String.format(packagePreAndModuleName + ".service.impl", templateData.get("entityName").toString().toLowerCase())); templateData.put("controllerPackageName", String.format(packagePreAndModuleName + ".web", templateData.get("entityName").toString().toLowerCase())); templateData.put("apiTestPackageName", String.format(packagePreAndModuleName + ".junit", templateData.get("entityName").toString().toLowerCase())); templateData.put("currentTime", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); //======================生成文件配置====================== try { // 生成Entity String entityName = String.format("%s", templateData.get("entityName").toString()); generateFile("entity.ftl", templateData, templateData.get("entityPackageName").toString(), entityName+".java"); // 生成dto String dtoName = String.format("%sDTO", templateData.get("entityName").toString()); templateData.put("dtoName", dtoName); generateFile("dto.ftl", templateData, templateData.get("dtoPackageName").toString(), dtoName + ".java"); // 生成VO String voName = String.format("%sVO", templateData.get("entityName").toString()); templateData.put("voName", voName); generateFile("vo.ftl", templateData, templateData.get("voPackageName").toString(), voName + ".java"); // 生成DAO String daoName = String.format("%sDao", templateData.get("entityName").toString()); templateData.put("daoName", daoName); generateFile("dao.ftl", templateData, templateData.get("daoPackageName").toString(), daoName + ".java"); // 生成Mapper String mapperName = String.format("%sMapper", templateData.get("entityName").toString()); generateFile("mapper.ftl", templateData, templateData.get("mapperPackageName").toString(), mapperName+".xml"); // 生成Service String serviceName = String.format("%sService", templateData.get("entityName").toString()); templateData.put("serviceName", serviceName); generateFile("service.ftl", templateData, templateData.get("servicePackageName").toString(), serviceName + ".java"); // 生成ServiceImpl String serviceImplName = String.format("%sServiceImpl", templateData.get("entityName").toString()); templateData.put("serviceImplName", serviceImplName); generateFile("serviceImpl.ftl", templateData, templateData.get("serviceImplPackageName").toString(), serviceImplName + ".java"); // 生成Controller String controllerName = String.format("%sController", templateData.get("entityName").toString()); templateData.put("controllerName", controllerName); generateFile("controller.ftl", templateData, templateData.get("controllerPackageName").toString(), controllerName + ".java"); // // 生成junit測試類 // String apiTestName = String.format("%sApiTest", templateData.get("entityName").toString()); // templateData.put("apiTestName", apiTestName); // generateFile("test.ftl", templateData, templateData.get("apiTestPackageName").toString(), // apiTestName + ".java"); } catch (Exception e) { e.printStackTrace(); } } /** * 生成文件 * @param templateName 模板名稱 * @param templateData 參數名 * @param packageName 包名 * @param fileName 文件名 */ public void generateFile(String templateName, Map<String, Object> templateData, String packageName, String fileName) { templateData.put("fileName", fileName); DaseService dbService = new DaseService(templateData); // 獲取數據庫參數 if("entity.ftl".equals(templateName) || "mapper.ftl".equals(templateName)){ dbService.getAllColumns(templateData); } try { // 默認生成文件的路徑 FreeMakerUtil freeMakerUtil = new FreeMakerUtil(); freeMakerUtil.generateFile(templateName, templateData, packageName, fileName); } catch (Exception e) { e.printStackTrace(); } } /** * 封裝包名前綴 * @return */ private String getPackagePreAndModuleName(Map<String, Object> templateData){ String packageNamePre = templateData.get("packageNamePre").toString(); String moduleName = templateData.get("moduleName").toString(); if(StringUtils.isNotBlank(moduleName)){ return packageNamePre + "." + moduleName; } return packageNamePre; } }
接著,獲取模板文件,并生成相應的模板文件
public class FreeMakerUtil { /** * 根據Freemark模板,生成文件 * @param templateName:模板名 * @param root:數據原型 * @throws Exception */ public void generateFile(String templateName, Map<String, Object> root, String packageName, String fileName) throws Exception { FileOutputStream fos=null; Writer out =null; try { // 通過一個文件輸出流,就可以寫到相應的文件中,此處用的是絕對路徑 String entityName = (String) root.get("entityName"); String fileFullName = String.format(fileName, entityName); packageName = String.format(packageName, entityName.toLowerCase()); String fileStylePackageName = packageName.replaceAll("\\.", "/"); File file = new File(root.get("outUrl").toString() + "/" + fileStylePackageName + "/" + fileFullName); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } file.createNewFile(); Template template = getTemplate(templateName); fos = new FileOutputStream(file); out = new OutputStreamWriter(fos); template.process(root, out); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (fos != null){ fos.close(); } if(out != null){ out.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * * 獲取模板文件 * * @param name * @return */ public Template getTemplate(String name) { try { Configuration cfg = new Configuration(Configuration.VERSION_2_3_23); cfg.setClassForTemplateLoading(this.getClass(), "/ftl"); Template template = cfg.getTemplate(name); return template; } catch (IOException e) { e.printStackTrace(); } return null; } }
最后,我們編寫一個main方法,看看運行之后的效果
public class GeneratorMain { public static void main(String[] args) { System.out.println("生成代碼start......"); //獲取頁面或者配置文件的參數 Map<String, Object> templateData = new HashMap<String, Object>(); templateData.put("tableName", SystemConstant.tableName); System.out.println("表名=="+ SystemConstant.tableName); templateData.put("entityName", SystemConstant.entityName); System.out.println("實體類名稱=="+ SystemConstant.entityName); templateData.put("packageNamePre", SystemConstant.packageNamePre); System.out.println("包名前綴=="+ SystemConstant.packageNamePre); //支持自定義輸出路徑 if(StringUtils.isNotBlank(SystemConstant.outUrl)){ templateData.put("outUrl", SystemConstant.outUrl); } else { String path = GeneratorMain.class.getClassLoader().getResource("").getPath() + "../../src/main/java"; templateData.put("outUrl", path); } System.out.println("生成文件路徑為=="+ templateData.get("outUrl")); templateData.put("authorName", SystemConstant.authorName); System.out.println("以后代碼出問題找=="+ SystemConstant.authorName); templateData.put("databaseName", SystemConstant.databaseName); templateData.put("ipName", SystemConstant.ipName); templateData.put("portName", SystemConstant.portName); templateData.put("userName", SystemConstant.userName); templateData.put("passWord", SystemConstant.passWord); //主鍵ID templateData.put("primaryId", SystemConstant.primaryId); //模塊名稱 templateData.put("moduleName", SystemConstant.moduleName); CodeService dataService = new CodeService(); try { //生成代碼文件 dataService.generate(templateData); } catch (Exception e) { e.printStackTrace(); } System.out.println("生成代碼end......"); } }
結果如下:
生成的 Controller 層代碼如下
/** * * @ClassName: TestEntityController * @Description: 外部訪問接口 * @author pzblog * @date 2020-11-16 * */ @RestController @RequestMapping("/testEntity") public class TestEntityController { @Autowired private TestEntityService testEntityService; /** * 分頁列表查詢 * @param request */ @PostMapping(value = "/getPage") public Pager<TestEntityVO> getPage(@RequestBody TestEntityDTO request){ return testEntityService.getPage(request); } /** * 查詢詳情 * @param request */ @PostMapping(value = "/getDetail") public TestEntityVO getDetail(@RequestBody IdRequest request){ TestEntity source = testEntityService.selectById(request.getId()); if(Objects.nonNull(source)){ TestEntityVO result = new TestEntityVO(); BeanUtils.copyProperties(source, result); return result; } return null; } /** * 新增操作 * @param request */ @PostMapping(value = "/save") public void save(TestEntityDTO request){ TestEntity entity = new TestEntity(); BeanUtils.copyProperties(request, entity); testEntityService.insert(entity); } /** * 編輯操作 * @param request */ @PostMapping(value = "/edit") public void edit(TestEntityDTO request){ TestEntity entity = new TestEntity(); BeanUtils.copyProperties(request, entity); testEntityService.updateById(entity); } /** * 刪除操作 * @param request */ @PostMapping(value = "/delete") public void delete(IdRequest request){ testEntityService.deleteById(request.getId()); } }
至此,一張單表的90%的基礎工作量全部開發完畢!
到此,相信大家對“如何獲取表結構”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。