簡介
前言
最近公司開展新項目,由於項目進度緊急,部分項目負責人不在現在,建表相關的使用的是Excel,由於Excel拼接過於麻煩,博豬COPY了一下大神的代碼,修改了部分代碼,以便適用於我們項目。
參照博客地址:博客地址
准備工作
Excel模板
模板可以根據自己的習慣來創建,需要注意的是建表時我們需要的參數有:數據庫名,表名,表注釋,列名,列注釋,列類型,列長度,列精度,是否主鍵,是否非空。
Database Name | your database name | Table Name (physical name) | your table name | Table Name (logical name) | 你的表名 | |
---|---|---|---|---|---|---|
Column Name (physical name) | Column Name (logical name) | Type | Length | Decimal | PK | NOT NULL |
column 1 | 列 1 | VARCHAR | 255 | * | * |
擼代碼
依賴
首先新建maven項目,並導入poi(用於操作excel)、lombok(簡化實體類代碼)依賴:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
因為我們只需要控制台輸入,並且輸出sql語句,所以只需要這3個依賴即可。
相關實體類
數據類型常量類TableTypeConstant.java
定義MySQL的數據類型
public class TableTypeConstant {
public static final String INT = "int";
public static final String VARCHAR ="varchar";
public static final String DATE = "date";
public static final String DATE_TIME="datetime";
public static final String TEXT ="text";
public static final String LONG_TEXT = "longtext";
public static final String CHAR = "char";
public static final String LONG = "long";
public static final String TIME_STAMP = "timestamp";
public static final String DECIMAL="decimal";
}
字段信息ColumnEntity.java
定義我們關注的字段的關鍵信息
@Data
public class ColumnEntity {
/*物理列名*/
private String physicalColumnName;
/*邏輯列名*/
private String logicalColumnName;
/*類型*/
private String type;
/*長度*/
private String length;
/*精度*/
private String decimal;
/*是否主鍵*/
private boolean isPrimaryKey;
/*是否非空*/
private boolean isNotNull;
}
表信息TableEntity.java
定義建表語句需要的信息
@Data
public class TableEntity {
/*列信息*/
private List<ColumnEntity> entities;
/*表物理名*/
private String physicalTableName;
/*表邏輯名*/
private String logicalTableName;
/*數據庫名*/
private String databaseName;
}
業務類
生成SQL語句Excel.java
包含3個方法
TableEntity readExcel(String excelPath)
解析Excel並返回TableEntityvoid convertSQL(TableEntity tableEntity)
根據TableEntity生成SQL語句並寫入txtvoid writeTXT(String path, String value, String fileName)
將字符串寫入txt文件
import com.bossYang.myBatisTest.bean.ColumnEntity;
import com.bossYang.myBatisTest.bean.TableEntity;
import com.bossYang.myBatisTest.bean.TableTypeConstant;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
public class Excel {
/**
* 讀取excel並轉換為表實體
*
* @param excelPath
* @return
*/
public TableEntity readExcel(String excelPath) {
// 解析模板對象List
List<ColumnEntity> entities = new ArrayList<ColumnEntity>();
// 表物理名
String physicalTableName = null;
// 表邏輯名
String logicalTableName = null;
// 數據庫名
String databaseName = null;
try {
// String encoding = "GBK";
File excel = new File(excelPath);
if (excel.isFile() && excel.exists()) { // 判斷文件是否存在
String[] split = excel.getName().split("\\."); // .是特殊字符,需要轉義!!!!!
Workbook wb;
// 根據文件后綴(xls/xlsx)進行判斷
if ("xls".equals(split[1])) {
FileInputStream fis = new FileInputStream(excel); // 文件流對象
wb = new HSSFWorkbook(fis);
} else if ("xlsx".equals(split[1])) {
wb = new XSSFWorkbook(excel);
} else {
System.out.println("文件類型錯誤!");
return null;
}
// 開始解析
Sheet sheet = wb.getSheetAt(0); // 讀取sheet 0
int firstRowIndex = sheet.getFirstRowNum() + 2; // 第一、二行是列名,所以不讀,從第三行開始讀
int lastRowIndex = sheet.getLastRowNum();
// System.out.println("firstRowIndex: "+firstRowIndex);
// System.out.println("lastRowIndex: "+lastRowIndex);
// 解析模板對象List
entities = new ArrayList<ColumnEntity>();
// 數據庫名
databaseName = sheet.getRow(0).getCell(1).getStringCellValue();
// 表物理名
physicalTableName = sheet.getRow(0).getCell(3).getStringCellValue();
// 表邏輯名
logicalTableName = sheet.getRow(0).getCell(5).getStringCellValue();
for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) { // 遍歷行
// System.out.println("rIndex: " + rIndex);
ColumnEntity entity = new ColumnEntity();
Row row = sheet.getRow(rIndex);
if (row != null) {
if (row.getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue() == null || row
.getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue().isEmpty()) {
continue;
}
/*
* int firstCellIndex = row.getFirstCellNum(); int lastCellIndex =
* row.getLastCellNum(); for (int cIndex = firstCellIndex; cIndex <
* lastCellIndex; cIndex++) { //遍歷列 Cell cell = row.getCell(cIndex); if (cell !=
* null) { System.out.println(cell.toString()); } }
*/
// 解析對象
entity.setPhysicalColumnName(
row.getCell(0, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 列物理名
entity.setLogicalColumnName(
row.getCell(1, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 列邏輯名
entity.setType(row.getCell(2, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 類型
entity.setLength(row.getCell(3, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 長度
entity.setDecimal(row.getCell(4, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue());// 精度
entity.setPrimaryKey("*"
.equals(row.getCell(5, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue()));// 是否主鍵
entity.setNotNull("*"
.equals(row.getCell(6, MissingCellPolicy.CREATE_NULL_AS_BLANK).getStringCellValue()));// 是否非空
// 存入list
entities.add(entity);
}
}
} else {
System.out.println("找不到指定的文件");
return null;
}
} catch (Exception e) {
e.printStackTrace();
}
TableEntity tableEntity = new TableEntity();
tableEntity.setEntities(entities);
tableEntity.setDatabaseName(databaseName);
tableEntity.setLogicalTableName(logicalTableName);
tableEntity.setPhysicalTableName(physicalTableName);
return tableEntity;
}
/**
* 將表實體轉換為sql並輸出為txt
*
* @param tableEntity
*/
public void convertSQL(TableEntity tableEntity) {
StringBuffer sql = new StringBuffer();
sql.append("CREATE TABLE `");
sql.append(tableEntity.getDatabaseName());
sql.append("`.`");
sql.append(tableEntity.getPhysicalTableName());
sql.append("` (");
// CREATE TABLE `databaseName`.`tablePhysicalName` (
List<ColumnEntity> cellEnties = tableEntity.getEntities();
// 主鍵
String primaryKey = null;
// 獲取主鍵
for (ColumnEntity item : cellEnties) {
// 將pk為true的設為主鍵
if (item.isPrimaryKey()) {
primaryKey = item.getPhysicalColumnName();
break;
}
}
// 循環列
for (ColumnEntity item : cellEnties) {
sql.append(" `");
sql.append(item.getPhysicalColumnName().trim());
sql.append("` ");
// `physicalColumnName`
// 根據NOT NULL 來拼接
if (item.isNotNull()) { // 如果不允許為空,則拼接NOT NULL
//類型
String type = item.getType().toLowerCase();
//類型轉換
if(type.indexOf("varchar")!=-1) {
type= TableTypeConstant.VARCHAR;
}else if (type.indexOf("number")!=-1) {
type=TableTypeConstant.INT;
//默認長度
if(item.getLength()==null||item.getLength().isEmpty()) {
item.setLength("11");
}
}else if(type.indexOf("char")!=-1) {
type=TableTypeConstant.CHAR;
}
// 根據類型選擇是否拼接長度
if (TableTypeConstant.CHAR.equals(type) || TableTypeConstant.VARCHAR.equals(type)) { // 文本需要拼接長度
sql.append(type);
sql.append("(");
sql.append(item.getLength());
sql.append(") CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '");
} else if (TableTypeConstant.TEXT.equals(type) || TableTypeConstant.LONG_TEXT.equals(type)) { // 文本不需要拼接長度
sql.append(type);
sql.append(" CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '");
} else if (TableTypeConstant.DATE.equals(type)) { // 時間不需要拼接長度
sql.append(type);
sql.append(" NOT NULL COMMENT '");
} else if (TableTypeConstant.DATE_TIME.equals(type)||TableTypeConstant.TIME_STAMP.equals(type)) { // 時間需要拼接長度 並且長度為0
sql.append(type);
sql.append("(0) NOT NULL COMMENT '");
} else if (TableTypeConstant.INT.equals(type)) { // 數字需要拼接長度
sql.append(type);
sql.append("(");
sql.append(item.getLength());
sql.append(") NOT NULL COMMENT '");
}
} else { // 如果允許為空,則拼接 NULL DEFAULT NULL
String type = item.getType().toLowerCase();
//類型轉換
if(type.indexOf("varchar")!=-1) {
type=TableTypeConstant.VARCHAR;
}else if (type.indexOf("number")!=-1) {
type=TableTypeConstant.INT;
//默認長度
if(item.getLength()==null||item.getLength().isEmpty()) {
item.setLength("11");
}
}else if(type.indexOf("char")!=-1) {
type=TableTypeConstant.CHAR;
}
// 根據類型選擇是否拼接長度
if (TableTypeConstant.CHAR.equals(type) || TableTypeConstant.VARCHAR.equals(type)) { // 文本需要拼接長度
sql.append(type);
sql.append("(");
sql.append(item.getLength());
sql.append(") CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '");
} else if (TableTypeConstant.TEXT.equals(type) || TableTypeConstant.LONG_TEXT.equals(type)) { // 文本不需要拼接長度
sql.append(type);
sql.append(" CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '");
} else if (TableTypeConstant.DATE.equals(type)) { // 時間不需要拼接長度
sql.append(type);
sql.append(" NULL DEFAULT NULL COMMENT '");
} else if (TableTypeConstant.DATE_TIME.equals(type)||TableTypeConstant.TIME_STAMP.equals(type)) { // 時間需要拼接長度 並且長度為0
sql.append(type);
sql.append("(0) NULL DEFAULT NULL COMMENT '");
} else if (TableTypeConstant.INT.equals(type) || TableTypeConstant.BIG_INT.equals(type) || TableTypeConstant.LONG.equals(type)) { // 數字需要拼接長度
sql.append(type);
sql.append("(");
sql.append(item.getLength());
sql.append(") NULL DEFAULT NULL COMMENT '");
}
}
// 拼接邏輯列名
sql.append(item.getLogicalColumnName());
sql.append("',");
}
// 拼接主鍵
sql.append(" PRIMARY KEY (`");
sql.append(primaryKey);
sql.append("`) USING BTREE ) ");
// 拼接引擎和邏輯表名
sql.append("ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '");
sql.append(tableEntity.getLogicalTableName());
sql.append("' ROW_FORMAT = Compact;");
System.err.println(sql);
try {
writeTXT("", sql.toString(), tableEntity.getPhysicalTableName() + tableEntity.getLogicalTableName());
System.out
.println("已導出:" + tableEntity.getPhysicalTableName() + tableEntity.getLogicalTableName() + ".txt!");
} catch (Exception e) {
e.printStackTrace();
System.err.println("導出文件失敗");
}
}
/**
* 將字符串寫入txt並導出
*
* @throws Exception
*/
public void writeTXT(String path, String value, String fileName) throws Exception {
File f = new File(path + fileName + ".txt");
FileOutputStream fos1 = new FileOutputStream(f);
OutputStreamWriter dos1 = new OutputStreamWriter(fos1);
dos1.write(value);
dos1.close();
}
}
主入口
通過控制台輸入Excel路徑,會在jar包同級目錄下生成包含建表SQL的TXT文件。
public class MainApplication {
public static void main(String[] args) {
while(true) {
Excel excel = new Excel();
Scanner scanner = new Scanner(System.in);
System.err.println("請輸入Excel的路徑:");
String excelPath = scanner.nextLine();
TableEntity tEntity = excel.readExcel(excelPath);
if(tEntity==null) {
continue;
}
excel.convertSQL(tEntity);
}
}
}
總結
基本上就是解析EXCEL,然后根據數據類型拼接SQL語句。
目前支持情況:
較原文沒啥改動,只是增加了部分字段,處理了部分默認值問題。