Talk is cheap,show me the code.
/**
* 功能:根據提供的數據庫表結構文件(.sql文件),自動生成對應的model類。
*
* 根據數據庫表的建表語句,生成對應的實體類。
* JDK版本1.8
* 數據庫使用的是mysql
*
* 注意事項:
* 1,必須要有COMMENT,並且COMMENT用英文單引號包圍起來。
* 2,請注意sql文件格式。我這裏會提供一個模板供大家參考。
* 3,請確保在D盤下的目錄是對的。可以根據自己的情況,修改代碼中硬編碼的路徑。
*
*/
自己寫的,可以直接跑。如有問題,請聯繫,謝謝。
一,程序入口核心類:GenEntityMappingForDatabase.java
import org.apache.commons.lang.StringUtils;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 功能:根據提供的數據庫表結構文件(.sql文件),自動生成對應的model類。
*
* 根據數據庫表的建表語句,生成對應的實體類。
* JDK版本1.8
* 數據庫使用的是mysql
*
* 注意事項:
* 1,必須要有COMMENT,並且COMMENT用英文單引號包圍起來。
* 2,請注意sql文件格式。我這裏會提供一個模板供大家參考。
* 3,請確保在D盤下的目錄是對的。可以根據自己的情況,修改代碼中硬編碼的路徑。
*
*/
public class GenEntityMappingForDatabase {
/**
* 源文件路徑
*/
private static final String SOURCE_FILE_PATH = "D:\\sourcefile\\";
/**
* 源文件名稱
*/
private static final String SOURCE_FILE_NAME = "table_create";
/**
* 源文件後綴
*/
private static final String SOURCE_FILE_SUFFIX = "sql";
/**
* 目標文件路徑
*/
private static final String TARGET_FILE_PATH = "D:\\targetfile\\";
/**
* 目標文件名稱
*/
private static final String TARGET_FILE_NAME = "TableMappedModel";
/**
* 目標文件後綴
*/
private static final String TARGET_FILE_SUFFIX = "java";
/**
* 換行符
*/
private static final String LINE_BREAK = "\r\n";
/**
* Mysql建表語句關鍵字
*/
private final static Map<String, String> MYSQL_KEY_WORD_MAP = new HashMap();
static {
MYSQL_KEY_WORD_MAP.put("ENGINE", "ENGINE");
MYSQL_KEY_WORD_MAP.put("CHARACTER", "CHARACTER");
MYSQL_KEY_WORD_MAP.put("COLLATE", "COLLATE");
}
public static void main(String[] args) {
File fileObj = new File(SOURCE_FILE_PATH + SOURCE_FILE_NAME + "." + SOURCE_FILE_SUFFIX);
GenEntityMappingForDatabase genEntityMappingForDatabase = new GenEntityMappingForDatabase();
TableInfo tableInfo = genEntityMappingForDatabase.getFieldInfo(fileObj);
genEntityMappingForDatabase.genJavaFileBaseMysql(tableInfo);
}
/**
* 解析sql建表語句文件,得到FieldInfo集合
* @param fileObj
* @return
*/
public TableInfo getFieldInfo(File fileObj) {
BufferedReader reader = null;
InputStream in = null;
TableInfo tableInfo = new TableInfo();
List<FieldInfo> list = new ArrayList<>();
List<FieldInfo> listParsed = null;
try {
reader = new BufferedReader(new FileReader(fileObj));
in = new FileInputStream(fileObj);
String line = null;
int count = 0;
while((line = reader.readLine()) != null) {
// 第一行
if (line.toUpperCase().contains("CREATE TABLE")) {
tableInfo.setTableName(parseTableName(line));
continue;
}
// PRIMARY KEY 行
if (line.toUpperCase().contains("PRIMARY KEY")) {
tableInfo.setPrimaryKeyDB(line.substring(line.indexOf("(") + 1, line.indexOf(")")));
continue;
}
// 建表語句結束的右括號 行
if (line.trim().startsWith(")")) {
continue;
}
// 表備註信息
if (line.trim().toUpperCase().startsWith("COMMENT")) {
continue;
}
boolean keyWordFlag = false;
for (Map.Entry<String, String> entry : MYSQL_KEY_WORD_MAP.entrySet()) {
if (line.toUpperCase().contains(entry.getKey())) {
keyWordFlag = true;
break;
}
}
if (keyWordFlag){
continue;
}
// 遞歸處理,拿到字段名/字段類型/字段備註信息,然後存入ArrayList
parseFiledInfo(line, list);
}
listParsed = convertMysql2Java(list, tableInfo);
tableInfo.setFieldList(listParsed);
} catch (IOException e) {
System.out.println(" catch 分支 IOException " + e);
} finally {
try {
in.close();
} catch (IOException e){
System.out.println(" finally 分支 IOException " + e);
}
}
return tableInfo;
}
public void genJavaFileBaseMysql(TableInfo tableInfo) {
genTargetFile(tableInfo);
}
private String parseTableName(String line) {
return line.replaceFirst("CREATE", "").replaceFirst("TABLE", "").replaceFirst("\\(", "").trim().toLowerCase();
}
private List<FieldInfo> parseFiledInfo(String line, List<FieldInfo> list) {
// 去掉每行前面的空格
String lineWithoutFrontBlank = parLineFrontBlank(line);
// 字段名
String fieldNameDB = lineWithoutFrontBlank.substring(0, lineWithoutFrontBlank.indexOf(" "));
// 字段備註信息
String comment = lineWithoutFrontBlank.substring(lineWithoutFrontBlank.indexOf("'") + 1, lineWithoutFrontBlank.lastIndexOf("'"));
String lineNotStartsWithBlankAndFieldName = parLineFrontBlank(lineWithoutFrontBlank.substring(lineWithoutFrontBlank.indexOf(" ")));
// 字段數據類型
String dataTypeMysql = lineNotStartsWithBlankAndFieldName.substring(0, lineNotStartsWithBlankAndFieldName.indexOf(" "));
// 去掉數據類型後面的括號內容
if (dataTypeMysql.trim().endsWith(")")) {
dataTypeMysql = dataTypeMysql.substring(0, dataTypeMysql.indexOf("("));
}
FieldInfo fieldInfo = new FieldInfo(fieldNameDB, null, dataTypeMysql, null, comment);
list.add(fieldInfo);
return list;
}
/**
* 遞歸去掉每行前面的空格
* @param tempStr
* @return
*/
private String parLineFrontBlank(String tempStr) {
if (tempStr.startsWith(" ")) {
String newTempStr = tempStr.substring(1);
return parLineFrontBlank(newTempStr);
}
return tempStr;
}
private void genTargetFile(TableInfo tableInfo) {
List<FieldInfo> listParsed = tableInfo.getFieldList();
FileOutputStream fos = null;
try {
File f1 = new File(TARGET_FILE_PATH + TARGET_FILE_NAME + "." + TARGET_FILE_SUFFIX);
if (!f1.exists()){
f1.getParentFile().mkdirs();
}
fos = new FileOutputStream(f1);
// 生成文件頭
fos.write(("/**" + LINE_BREAK).getBytes());
fos.write((" @author Changqing Yang" + LINE_BREAK).getBytes());
fos.write((" * @date 2019/10/30" + LINE_BREAK).getBytes());
fos.write((" */" + LINE_BREAK).getBytes());
fos.write(("public class " + TARGET_FILE_NAME + " {" + LINE_BREAK).getBytes());
fos.write(LINE_BREAK.getBytes());
// 循環寫入字段
for (FieldInfo fieldInfo : listParsed) {
String filedNameJava = fieldInfo.getFieldNameJava();
String dataTypeJava = fieldInfo.getDataTypeJava();
String comment = fieldInfo.getComment();
fos.write((" // " + comment + LINE_BREAK).getBytes());
fos.write((" private " + dataTypeJava + " " + filedNameJava + ";" + LINE_BREAK).getBytes());
}
// 生成getter/setter方法
genGetterAndSetter(fos, listParsed);
// 生成文件尾部
fos.write(("}" + LINE_BREAK).getBytes());
} catch (IOException e) {
System.out.println("catch " + e);
} finally {
try {
fos.close();
} catch (IOException e) {
System.out.println("finally " + e);
}
}
}
private List<FieldInfo> convertMysql2Java(List<FieldInfo> list, TableInfo tableInfo) {
List<FieldInfo> listParsed = new ArrayList<>();
for (FieldInfo fieldInfo : list) {
// 如果該字段是主鍵
if (StringUtils.equals(fieldInfo.getFieldNameJava(), tableInfo.getPrimaryKeyJava())) {
tableInfo.setPrimaryKeyJava(mappingMysqlFieldName2Java(tableInfo.getPrimaryKeyDB()));
tableInfo.setPrimaryKeyDataType(fieldInfo.getDataTypeMysql());
}
// mysql字段轉java字段
fieldInfo.setFieldNameJava(mappingMysqlFieldName2Java(fieldInfo.getFieldNameDB()));
// mysql字段類型 轉 java 數據類型
fieldInfo.setDataTypeJava(mappingMysqlDataType2Java(fieldInfo.getDataTypeMysql()));
listParsed.add(fieldInfo);
}
return listParsed;
}
private String mappingMysqlDataType2Java(String dataTypeMysql) {
//
// // 去掉數據類型後面的括號內容
// if (dataTypeMysql.trim().endsWith(")")) {
// dataTypeMysql = dataTypeMysql.substring(0, dataTypeMysql.indexOf("("));
// }
// 字符串
if (MysqlDataTypeConstants.MYSQL_DATA_TYPE_VARCHAR.containsValue(dataTypeMysql.toLowerCase())) {
return "String";
}
// 整形
if (MysqlDataTypeConstants.MYSQL_DATA_TYPE_INT.containsValue(dataTypeMysql.toLowerCase())) {
return "Integer";
}
// 長整形
if (MysqlDataTypeConstants.MYSQL_DATA_TYPE_LONG.containsValue(dataTypeMysql.toLowerCase())) {
return "Long";
}
// date
if (MysqlDataTypeConstants.MYSQL_DATA_TYPE_DATE.containsValue(dataTypeMysql.toLowerCase())) {
return "Date";
}
return dataTypeMysql;
}
/**
* Mysql字段名稱轉java字段名稱
* @param filedName
* @return
*/
private String mappingMysqlFieldName2Java(String filedName) {
// 去掉數據類型後面的括號內容
if (!filedName.contains("_")) {
return filedName;
}
return parseUnderLine(filedName);
}
/**
* 遞歸處理Mysql字段名稱中的下劃線
*/
private String parseUnderLine(String filedName) {
int underLineIndex = filedName.indexOf("_");
String parsedFieldName = filedName.replaceFirst(filedName.substring(underLineIndex, underLineIndex + 2), filedName.substring(underLineIndex + 1, underLineIndex + 2).toUpperCase());
if (!parsedFieldName.contains("_")) {
return parsedFieldName;
}
return parseUnderLine(parsedFieldName);
}
/**
* 根據字段名,生成getter/setter
*/
private void genGetterAndSetter(FileOutputStream fos, List<FieldInfo> list) {
String fieldNameJava = null;
String fieldNameUpperCase = null;
String dataTypeJava = null;
for (FieldInfo fieldInfo : list) {
fieldNameJava = fieldInfo.getFieldNameJava();
dataTypeJava = fieldInfo.getDataTypeJava();
// 字段名首字母轉大寫
fieldNameUpperCase = fieldNameJava.substring(0, 1).toUpperCase().concat(fieldNameJava.substring(1));
try {
fos.write(LINE_BREAK.getBytes());
fos.write((" public " + dataTypeJava + " get" + fieldNameUpperCase + "() {" + LINE_BREAK).getBytes());
fos.write((" return " + fieldNameJava + ";" + LINE_BREAK).getBytes());
fos.write((" }" + LINE_BREAK).getBytes());
fos.write(LINE_BREAK.getBytes());
fos.write((" public void set" + fieldNameUpperCase + "(" + dataTypeJava + " " + fieldNameJava + ") {" + LINE_BREAK).getBytes());
fos.write((" this." + fieldNameJava + " = " + fieldNameJava + ";" + LINE_BREAK).getBytes());
fos.write((" }" + LINE_BREAK).getBytes());
} catch (IOException e) {
System.out.println("genGetterAndSetter catch " + e);
}
}
}
}
二,建表語句中所有表字段封裝實體類:FieldInfo.java
/**
* 建表語句中所有表字段封裝實體類
*/
public class FieldInfo {
/**
* 字段名(數據庫字段格式)
*/
private String fieldNameDB;
/**
* 字段名(java駝峯格式)
*/
private String fieldNameJava;
/**
* mysql數據類型
*/
private String dataTypeMysql;
/**
* java數據類型
*/
private String dataTypeJava;
/**
* 字段conmment備註信息
*/
private String comment;
public FieldInfo(String fieldNameDB, String fieldNameJava, String dataTypeMysql, String dataTypeJava, String comment) {
this.fieldNameDB = fieldNameDB;
this.fieldNameJava = fieldNameJava;
this.dataTypeMysql = dataTypeMysql;
this.dataTypeJava = dataTypeJava;
this.comment = comment;
}
public String getFieldNameDB() {
return fieldNameDB;
}
public void setFieldNameDB(String fieldNameDB) {
this.fieldNameDB = fieldNameDB;
}
public String getFieldNameJava() {
return fieldNameJava;
}
public void setFieldNameJava(String fieldNameJava) {
this.fieldNameJava = fieldNameJava;
}
public String getDataTypeMysql() {
return dataTypeMysql;
}
public void setDataTypeMysql(String dataTypeMysql) {
this.dataTypeMysql = dataTypeMysql;
}
public String getDataTypeJava() {
return dataTypeJava;
}
public void setDataTypeJava(String dataTypeJava) {
this.dataTypeJava = dataTypeJava;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
}
三,建表語句對應實體類:TableInfo.java
import java.util.List;
/**
* 建表語句對應實體類
*/
public class TableInfo {
/**
* 表名
*/
private String tableName;
/**
* 主鍵(數據庫字段名格式)
*/
private String primaryKeyDB;
/**
* 主鍵(java駝峯命名格式)
*/
private String primaryKeyJava;
/**
* 主鍵的數據類型
*/
private String primaryKeyDataType;
/**
* 表字段集合
*/
private List<FieldInfo> fieldList;
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public String getPrimaryKeyDB() {
return primaryKeyDB;
}
public void setPrimaryKeyDB(String primaryKeyDB) {
this.primaryKeyDB = primaryKeyDB;
}
public String getPrimaryKeyJava() {
return primaryKeyJava;
}
public void setPrimaryKeyJava(String primaryKeyJava) {
this.primaryKeyJava = primaryKeyJava;
}
public String getPrimaryKeyDataType() {
return primaryKeyDataType;
}
public void setPrimaryKeyDataType(String primaryKeyDataType) {
this.primaryKeyDataType = primaryKeyDataType;
}
public List<FieldInfo> getFieldList() {
return fieldList;
}
public void setFieldList(List<FieldInfo> fieldList) {
this.fieldList = fieldList;
}
}
四,常量定義類:MysqlDataTypeConstants.java
import java.util.HashMap;
import java.util.Map;
/**
* 常量定義類
*/
public class MysqlDataTypeConstants {
/**
* Mysql數據類型之字符串(整理的可能不夠完整,歡迎大家補充。)
*/
public final static Map<String, String> MYSQL_DATA_TYPE_VARCHAR = new HashMap();
static {
MYSQL_DATA_TYPE_VARCHAR.put("varchar", "varchar");
MYSQL_DATA_TYPE_VARCHAR.put("json", "json");
MYSQL_DATA_TYPE_VARCHAR.put("char", "char");
}
/**
* Mysql數據類型之整形(整理的可能不夠完整,歡迎大家補充。)
*/
public final static Map<String, String> MYSQL_DATA_TYPE_INT = new HashMap();
static {
MYSQL_DATA_TYPE_INT.put("int", "int");
MYSQL_DATA_TYPE_INT.put("bit", "bit");
}
/**
* Mysql數據類型之長整形(整理的可能不夠完整,歡迎大家補充。)
*/
public final static Map<String, String> MYSQL_DATA_TYPE_LONG = new HashMap();
static {
MYSQL_DATA_TYPE_LONG.put("bigint", "bigint");
MYSQL_DATA_TYPE_LONG.put("long", "long");
}
/**
* Mysql數據類型之整形(整理的可能不夠完整,歡迎大家補充。)
*/
public final static Map<String, String> MYSQL_DATA_TYPE_DATE = new HashMap();
static {
MYSQL_DATA_TYPE_DATE.put("datetime", "datetime");
MYSQL_DATA_TYPE_DATE.put("timestamp", "timestamp");
}
}
五,sql文件模板:table_create.sql
注意,這個文件的路徑是:D:\sourcefile,如果需要修改,請把源碼中的對應路徑也修改掉。
CREATE TABLE product_info (
product_id bigint COMMENT '產品編號' NOT NULL,
product_name varchar(128) COMMENT '產品名稱' NOT NULL,
status varchar(20) COMMENT '產品狀態 0-未上架 1-已上架 2-已下架 3-已刪除',
create_time timestamp COMMENT '創建時間' NOT NULL,
update_time timestamp COMMENT '最後更新時間' NOT NULL,
PRIMARY KEY(activity_id) USING BTREE
)
COMMENT = '產品信息'
ENGINE = InnoDB
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
六,運行生成的model文件示例TableMappedModel.java
默認生成文件的路徑是:D:\targetfile,如果需要修改,請把源碼中的對應路徑也修改掉。
/**
@author Changqing Yang
* @date 2019/10/30
*/
public class TableMappedModel {
// 產品編號
private Long productId;
// 產品名稱
private String productName;
// 產品狀態 0-未上架 1-已上架 2-已下架 3-已刪除
private String status;
// 創建時間
private Date createTime;
// 最後更新時間
private Date updateTime;
public Long getProductId() {
return productId;
}
public void setProductId(Long productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
}