Excel生成Oracle数据库表sql工具类
1.解决问题: 开发文档中字段比较多的时候,建表sql(Oracle下划线命名规范)比较麻烦,容易出错~~ (主要是懒)
特意手写一个工具,根据excel字段,生成建表的sql语句.
~~~末尾附GitHub传送门~~~
2.Java代码
Excel头:
public class ExcelHead {
private String excelName; //Excel名
private String entityName; //实体类属性名
private boolean required=false; //值必填
get()/set()
}
Excel实体:
public class Excel {
private String item; //属性列
private String type; //类型
private String isNeed; //是否必填
private String annotation; //注释
private Integer maxLength; //最大长度 get()/set()
}
ExcelUtils工具类 :
(借鉴而来)
package com.utils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List; public class ExcelUtils {
private static final String FULL_DATA_FORMAT = "yyyy/MM/dd HH:mm:ss";
private static final String SHORT_DATA_FORMAT = "yyyy/MM/dd"; /**
* Excel表头对应Entity属性 解析封装javabean
*
* @param classzz 类
* @param in excel流
* @param fileName 文件名
* @param excelHeads excel表头与entity属性对应关系
* @param <T>
* @return
* @throws Exception
*/
public static <T> List<T> readExcelToEntity(Class<T> classzz, InputStream in, String fileName, List<ExcelHead> excelHeads) throws Exception {
checkFile(fileName); //是否EXCEL文件
Workbook workbook = getWorkBoot(in, fileName); //兼容新老版本
List<T> excelForBeans = readExcel(classzz, workbook, excelHeads); //解析Excel
return excelForBeans;
} /**
* 解析Excel转换为Entity
*
* @param classzz 类
* @param in excel流
* @param fileName 文件名
* @param <T>
* @return
* @throws Exception
*/
public static <T> List<T> readExcelToEntity(Class<T> classzz, InputStream in, String fileName) throws Exception {
return readExcelToEntity(classzz, in, fileName,null);
} /**
* 校验是否是Excel文件
*
* @param fileName
* @throws Exception
*/
public static void checkFile(String fileName) throws Exception {
if (!StringUtils.isEmpty(fileName) && !(fileName.endsWith(".xlsx") || fileName.endsWith(".xls"))) {
throw new Exception("不是Excel文件!");
}
} /**
* 兼容新老版Excel
*
* @param in
* @param fileName
* @return
* @throws IOException
*/
private static Workbook getWorkBoot(InputStream in, String fileName) throws IOException {
if (fileName.endsWith(".xlsx")) {
return new XSSFWorkbook(in);
} else {
return new HSSFWorkbook(in);
}
} /**
* 解析Excel
*
* @param classzz 类
* @param workbook 工作簿对象
* @param excelHeads excel与entity对应关系实体
* @param <T>
* @return
* @throws Exception
*/
private static <T> List<T> readExcel(Class<T> classzz, Workbook workbook, List<ExcelHead> excelHeads) throws Exception {
List<T> beans = new ArrayList<T>();
int sheetNum = workbook.getNumberOfSheets();
for (int sheetIndex = 0; sheetIndex < sheetNum; sheetIndex++) {
Sheet sheet = workbook.getSheetAt(sheetIndex);
String sheetName=sheet.getSheetName();
int firstRowNum = sheet.getFirstRowNum();
int lastRowNum = sheet.getLastRowNum();
Row head = sheet.getRow(firstRowNum);
if (head == null)
continue;
short firstCellNum = head.getFirstCellNum();
short lastCellNum = head.getLastCellNum();
Field[] fields = classzz.getDeclaredFields();
for (int rowIndex = firstRowNum + 1; rowIndex <= lastRowNum; rowIndex++) {
Row dataRow = sheet.getRow(rowIndex);
if (dataRow == null)
continue;
T instance = classzz.newInstance();
if(CollectionUtils.isEmpty(excelHeads)){ //非头部映射方式,默认不校验是否为空,提高效率
firstCellNum=dataRow.getFirstCellNum();
lastCellNum=dataRow.getLastCellNum();
}
for (int cellIndex = firstCellNum; cellIndex < lastCellNum; cellIndex++) {
Cell headCell = head.getCell(cellIndex);
if (headCell == null)
continue;
Cell cell = dataRow.getCell(cellIndex);
headCell.setCellType(Cell.CELL_TYPE_STRING);
String headName = headCell.getStringCellValue().trim();
if (StringUtils.isEmpty(headName)) {
continue;
}
ExcelHead eHead = null;
if (!CollectionUtils.isEmpty(excelHeads)) {
for (ExcelHead excelHead : excelHeads) {
if (headName.equals(excelHead.getExcelName())) {
eHead = excelHead;
headName = eHead.getEntityName();
break;
}
}
}
for (Field field : fields) {
if (headName.equalsIgnoreCase(field.getName())) {
String methodName = MethodUtils.setMethodName(field.getName());
Method method = classzz.getMethod(methodName, field.getType());
if (isDateFied(field)) {
Date date=null;
if(cell!=null){
date=cell.getDateCellValue();
}
if (date == null) {
volidateValueRequired(eHead,sheetName,rowIndex);
break;
}
method.invoke(instance, cell.getDateCellValue());
} else {
String value = null;
if(cell!=null){
cell.setCellType(Cell.CELL_TYPE_STRING);
value=cell.getStringCellValue();
}
if (StringUtils.isEmpty(value)) {
volidateValueRequired(eHead,sheetName,rowIndex);
break;
}
method.invoke(instance, convertType(field.getType(), value.trim()));
}
break;
}
}
}
beans.add(instance);
}
}
return beans;
}
/**
* 是否日期字段
*
* @param field
* @return
*/
private static boolean isDateFied(Field field) {
return (Date.class == field.getType());
}
/**
* 空值校验
*
* @param excelHead
* @throws Exception
*/
private static void volidateValueRequired(ExcelHead excelHead,String sheetName,int rowIndex) throws Exception {
if (excelHead != null && excelHead.isRequired()) {
throw new Exception("《"+sheetName+"》第"+(rowIndex+1)+"行:\""+excelHead.getExcelName() + "\"不能为空!");
}
}
/**
* 类型转换
*
* @param classzz
* @param value
* @return
*/
private static Object convertType(Class classzz, String value) {
if (Integer.class == classzz || int.class == classzz) {
return Integer.valueOf(value);
}
if (Short.class == classzz || short.class == classzz) {
return Short.valueOf(value);
}
if (Byte.class == classzz || byte.class == classzz) {
return Byte.valueOf(value);
}
if (Character.class == classzz || char.class == classzz) {
return value.charAt(0);
}
if (Long.class == classzz || long.class == classzz) {
return Long.valueOf(value);
}
if (Float.class == classzz || float.class == classzz) {
return Float.valueOf(value);
}
if (Double.class == classzz || double.class == classzz) {
return Double.valueOf(value);
}
if (Boolean.class == classzz || boolean.class == classzz) {
return Boolean.valueOf(value.toLowerCase());
}
if (BigDecimal.class == classzz) {
return new BigDecimal(value);
}
/* if (Date.class == classzz) {
SimpleDateFormat formatter = new SimpleDateFormat(FULL_DATA_FORMAT);
ParsePosition pos = new ParsePosition(0);
Date date = formatter.parse(value, pos);
return date;
}*/
return value;
}
/**
* 获取properties的set和get方法
*/
static class MethodUtils {
private static final String SET_PREFIX = "set";
private static final String GET_PREFIX = "get";
private static String capitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
public static String setMethodName(String propertyName) {
return SET_PREFIX + capitalize(propertyName);
}
public static String getMethodName(String propertyName) {
return GET_PREFIX + capitalize(propertyName);
}
}
}
Constant常量 :
package com.utils; public interface Constant { String pre = " create table <<tableName>> \n" +
"(\n" +
"<<itemContent>> \n" +
")\n" +
"/\n" +
"comment on table <<tableName>> is '<<tableNameDesc>>'" +
"\n" +
"/\n" +
"<<annotationContent>>"; //oracle数据类型相关
String NUMBER = "NUMBER";
String VARCHAR2 = "VARCHAR2";
String DATE = "DATE";
String NOT_NULL = "not null";
String STRING_MAX_LENGTH = "256";//默认字符串最大位数
String ROW_PRE = " ";//行开头缩进 }
ChangeChar工具类 (驼峰转下划线大写) :
我的另一篇博客有 : https://www.cnblogs.com/coloz/p/10911174.html
ExcelToSql:( 处理Excel中数据,各种拼接替换模板和常量)
package com.utils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import java.io.*; import java.util.List; public class ExcelToSql { /**
* @param tableName
* @param tableNameDesc
* @param excelPath
* @throws Exception
*/
public static String createSql(String tableName, String tableNameDesc, String excelPath) throws Exception {
//String tableName = "MY_USER"; //表名
// String tableNameDesc = "我的用户表"; //表名描述
// String excelPath = "D:\\code\\excelToSql\\src\\main\\resources\\Excel.xlsx";
File file = new File(excelPath); //文件位置
FileInputStream fileInputStream = new FileInputStream(file);
String name = file.getName();
List<Excel> list = ExcelUtils.readExcelToEntity(Excel.class, fileInputStream, name);
// System.out.println("list :" + list);
String sqlStr = Constant.pre; //总的部分,先添加前置部分
String itemContent = ""; //具体表字段信息
String annotationContent = ""; //后面注释内容 String rowModelEnd = ",\n"; //最后一行不加 if (CollectionUtils.isNotEmpty(list)) {
for (int i = 0; i < list.size(); i++) {
//oracle
Excel vo = list.get(i);
if (vo != null) { String item = vo.getItem();
String annotation = vo.getAnnotation();
String type = vo.getType(); //数据类型
String isNeed = vo.getIsNeed(); //是否必填
Integer maxLength = vo.getMaxLength(); //最大长度
if (StringUtils.isBlank(item)) {
continue; //列不存在直接跳过
} String ITEM_LINE = ChangeChar.camelToUnderline(item, 2); //对应oracle数据库列名转大写下划线 //用于替换sql语句中的占位 字符串<< >>
String itemNew = ITEM_LINE; //oracle大写
String annotationNew = annotation;
String typeNew = Constant.VARCHAR2; //默认字符串类型
String isNeedNew = ""; //默认不必填
String maxLengthNew = ""; //最大长度 if (type.contains("int") || type.contains("Num") || type.contains("Int")
|| type.contains("数") || type.contains("num")) {
typeNew = Constant.NUMBER;
} else if (type.contains("date") || type.contains("Date") || type.contains("日期")) {
typeNew = Constant.DATE;
} if (isNeed.contains("是") || isNeed.contains("true") || isNeed.contains("True")) {
isNeedNew = Constant.NOT_NULL;
}
if (isNeed.contains("是") || isNeed.contains("true") || isNeed.contains("True")) {
isNeedNew = Constant.NOT_NULL;
} //如果是字符串类型没有指定长度,默认256
if (maxLength == null || maxLength < 0) {
if (typeNew.equals(Constant.VARCHAR2)) {
maxLengthNew = "(" + Constant.STRING_MAX_LENGTH + ")";
}
} else {
maxLengthNew = "(" + maxLength + ")"; //有值直接赋值
}
//默认值问题??? //列字段相关,行左端保持必要空格,方便格式对齐
String rowModel = Constant.ROW_PRE + "<<rowItem>> <<dataType>><<(maxLength)>> <<isNeed>>"; //maxlength有括号
if (i != (list.size() - 1)) {
rowModel += rowModelEnd; //最后一行不加
} rowModel = rowModel.replaceAll("<<rowItem>>", itemNew).
replaceAll("<<dataType>>", typeNew).
replace("<<(maxLength)>>", maxLengthNew).
replaceAll("<<isNeed>>", isNeedNew); itemContent += rowModel; //列拼接 //注释相关
String rowAnnotation = "\n" +
"comment on column <<tableName>>.<<ITEM_LINE>> is '<<annotation>>'\n" +
"/"; rowAnnotation = rowAnnotation.replaceAll("<<tableName>>", tableName).
replaceAll("<<ITEM_LINE>>", ITEM_LINE).
replaceAll("<<annotation>>", annotationNew)
; annotationContent += rowAnnotation; //注释拼接
}
}
} //替换一下表字段名和注释部分
sqlStr = sqlStr.replaceAll("<<itemContent>>", itemContent)
.replaceAll("<<tableNameDesc>>", tableNameDesc)
.replaceAll("<<annotationContent>>", annotationContent)
; sqlStr = sqlStr.replaceAll("<<tableName>>", tableName);
System.out.println("-----------下面是生成表的sql--------------------------------------------------------");
System.out.println(sqlStr); System.out.println("-----------sql结束----------------------------------------------------------------");
return sqlStr;
} }
测试类:
package com; import com.utils.ExcelToSql; public class MainRun {
public static void main(String[] args) throws Exception {
/**
* 本工具主要为EXCEL生成ORACLE数据库建表sql
* 第一步:修改resource文件夹下面Excel.xlsx内容(第一行不要修改),
* item:列字段, annotation:注释,type:数据类型(Number/String/Date 默认String),maxLength:最大长度(字符串默认256),isNeed:是否必须(是/否)
* 第二步:设置 下面的tableName, tableNameDesc,excelPath
* 第三步:运行MainRun.java类下的main方法,控制台输出sqls
* 注意格式:只测试过excel里面(驼峰字段)--->生成表列都是(下划线大写)
*
*/ String tableName = "MY_USER"; //表名,必填
String tableNameDesc = "我的用户表"; //表名,可以为空
String excelPath = "D:\\code\\excelToSql\\src\\main\\resources\\Excel.xlsx"; //excel硬盘上路径
String sql = ExcelToSql.createSql(tableName, tableNameDesc, excelPath); }
}
总结 : 1. Oracle的SQL规范,对开发者来说也是一种比较好的约束和开发工作中需要考虑到的方面.
2.使用一些比较方便的工具对开发者省时省力,避免重复的"CV"工作.
3.本篇中使用的无非是使用sql模板,结合POI工具,对表字段内容进行替换和逻辑判断,十分简单.
4.如果有实现Mysql版本对应的工具,欢迎留言交流分享~~~
GitHub传送门: https://github.com/ColoZhu/excelToSql
Excel生成Oracle数据库表sql工具类的更多相关文章
- 利用ADO让普通人用excel读取oracle数据库表的通用办法
Ref:http://blog.csdn.net/iamlaosong/article/details/8465177 Excel通过ADO方式连接到Oracle并操作Oracle给那些编程能力不强的 ...
- 用T4模版生成对应数据库表的实体类
<#@ template debug="false" hostspecific="false" language="C#" #> ...
- 在线数据库表(sql语句)生成java实体类工具
相信每个做java开发的读者,都接触过SQL建表语句,尤其是在项目开发初期,因为数据库是项目的基石. 在现代项目开发中,出现了许多ORM框架,通过简单的实体映射,即可实现与数据库的交互,然而我们最初设 ...
- JAVA 自动生成对应数据库表的JPA代码工具
http://blog.csdn.net/zheng2008hua/article/details/6274659 关键词:JPA 数据库表代码自动生成,JPA代码生成 自动生成对应数据库表的 ...
- Oracle数据库中调用Java类开发存储过程、函数的方法
Oracle数据库中调用Java类开发存储过程.函数的方法 时间:2014年12月24日 浏览:5538次 oracle数据库的开发非常灵活,不仅支持最基本的SQL,而且还提供了独有的PL/SQL, ...
- Java创建Oracle数据库表
我们通常只用java执行DML(即:insert, update, delete, select)操作,很少用来执行DDL(create, drop, alert)操作.今天试了下如何用java来创建 ...
- Oracle数据库表分区
一.Oracle数据库表分区概念和理解 1.1.已经存在的表没有方法可以直接转化为分区表. 1.2.不在分区字段上建立分区索引,在别的字段上建立索引相当于全局索引.效率 ...
- 搜索表字段包含某字符串的SQL和监控Oracle数据库的SQL。
1.第一个SQL 背景:需要找到SQL Server数据库中,包含某个字符串的表,输出表和包含该字符串的列. )='=' --这里填要搜索的字符串 DECLARE @sql NVARCHAR(MAX) ...
- 数据库连接池与SQL工具类
数据库连接池与SQL工具类 1.数据库连接池 依赖包 pymysql dbutils # -*- coding: utf-8 -*- ''' @Time : 2021/11/19 16:45 @Aut ...
随机推荐
- Openstack Nova 源码分析 — Create instances (nova-conductor阶段)
目录 目录 前言 Instance Flavor Instance Status Virt Driver Resource Tracker nova-conductor Create Instance ...
- 20140421 常量指针与指针常量; const指针; reinterpret_cast ;const_cast作用
1.reinterpret_cast<type_id>(表达式)的作用: type-id 必须是一个指针.引用.算术类型.函数指针或者成员指针.它可以把一个指针转换成一个整数,也可以把一个 ...
- 图像直方图均衡化(C#)
关于图像直方图均衡化的原理和步骤先不作讨论,我就看看代码吧. private Bitmap picequalization(Bitmap basemap, int width, int height) ...
- CSS3新属性之---flex box布局实例
flex box布局实例 flex的强大之处在于不管什么布局,几行命令即可实现 /*本节模板div元素(代表骰子的一个面)是Flex容器,span元素(代表一个点)是Flex项目.如果有多个项目,就要 ...
- JSON Web Token (JWT)生成Token及解密实战。
昨天讲解了JWT的介绍.应用场景.优点及注意事项等,今天来个JWT具体的使用实践吧. 从JWT官网支持的类库来看,jjwt是Java支持的算法中最全的,推荐使用,网址如下. https://githu ...
- unittest(2)
测试用例执行顺序 1.setUp和tearDown相关 setUp:表示前置条件,它在每一个用例执行之前必须会执行一次 setUp可以理解为我们需要自动化测试时,需要打开网页窗口,输入对 ...
- linux mysql主从复制配置
1.设置主库master的servie-id值并且开启bin-log功能参数vi /etc/my.cnf修改my.cnf的参数:[mysqld]server-id=1 //每一个库的server-id ...
- vue项目使用history模式打包应该注意的地方
1.在config/index.js中将assetsPublicPath原来的’/‘修改为‘./’. build: { env: require('./prod.env'), index: path. ...
- 常见PID里面的像素大小
因为tensorflow/models里faster R-cnn目前识别的好像是按照像素比上图片大小来识别的,所以在这里统计一下各个元件的像素大小的范围 DCS:70~200
- mysql 09章_存储过程和函数
一. 函数和存储过程的相同点: 函数和存储过程都是事先预编译并保存在数据库中的特殊的数据库对象, 需要执行相应功能时就可以直接通过“函数名”.“存储过程”调用其中的代码,以提高执行效率和代码的复用性. ...