记录:278
场景:在实际开发中,开发文档中的建表信息以表格的方式提供,包括字段名称、字段类型、字段注释、是否为空等。本例就是先把表格信息转换为约定格式的txt文件,在使用Java代码生成完整的建表语句。
版本:Spring Boot 2.6.3
一、案例场景
1.开发文档中以表格方式提供建表信息。

2.手动转换为txt文件,文件名:SENSOR_DATA.txt,格式约定如下:
第一行为,表名##表名称。
第二行开始,每行:字段名称##字段类型##字段非空##字段注释##字段主键或者索引。
- SENSOR_DATA##传感器数据
- ID##NUMBER(16)##Y##实体唯一标识##primary
- REGION##VARCHAR2(8)##N##区域##index
- VALUE1##NUMBER(16,2)##N##取值1##N
- VALUE2##NUMBER(16,2)##N##取值2##N
3.执行代码,自动生成sql文件,文件名:SENSOR_DATA.sql,生成结果。
- create table SENSOR_DATA (
- ID NUMBER(16) not null ,
- REGION VARCHAR2(8),
- VALUE1 NUMBER(16,2),
- VALUE2 NUMBER(16,2)
- );
- comment on table SENSOR_DATA is '传感器数据';
- comment on column SENSOR_DATA.ID is '实体唯一标识';
- comment on column SENSOR_DATA.REGION is '区域';
- comment on column SENSOR_DATA.VALUE1 is '取值1';
- comment on column SENSOR_DATA.VALUE2 is '取值2';
- alter table SENSOR_DATA add constraint PK_SENSOR_DATA_ID primary key (ID);
- create index IDX_SENSOR_DATA_REGION on SENSOR_DATA (REGION);
二、使用类
1.读文件操作
java.lang.AutoCloseable,接口。
java.io.Closeable,接口,继承AutoCloseable。
java.lang.Readable,接口。
java.io.Reader,抽象类,实现Readable接口和Closeable。
java.io.BufferedReader,实现类,实现Reader抽象类。
java.io.InputStreamReader,实现类,读输入流,Reader抽象类。
java.io.FileReader,实现类,读文件,继承InputStreamReader。
new BufferedReader(new FileReader(fileName))。
2.写文件操作
java.lang.AutoCloseable,接口。
java.io.Closeable,接口,继承AutoCloseable。
java.io.Flushable,接口。
java.lang.Appendable,接口。
java.io.Writer,抽象类,实现Appendable, Closeable, Flushable。
java.io.BufferedWriter,实现类,实现Writer抽象类。
java.io.OutputStreamWriter,实现类,写输出流,Writer抽象类。
java.io.FileWriter,实现类,写文件,继承OutputStreamWriter。
new BufferedWriter(new FileWriter(fileName, true));
3.操作ArrayList
java.lang.Iterable,接口。
java.util.Collection,接口,继承Iterable。
java.util.List,接口,继承Collection。
java.util.AbstractCollection,抽象类,实现Collection。
java.util.AbstractList,抽象类,继承AbstractCollection,实现List。
java.util.ArrayList,一个Resizable-array。
4.Collections
java.util.Collections,对集合相关操作。
三、代码
1.读文件
读取文件,逐行读取,每读取一行,立即解析,根据分隔符##,分割成多个String字符串,存放在一个List<String>中。解析完成的一行数据List<String>,再放入List<List>中。
- public static ArrayList<ArrayList<String>> readFromTxt(String fileName) {
- ArrayList<ArrayList<String>> listAll = new ArrayList<>();
- try {
- //1.读txt文件,一次读一行
- BufferedReader br = new BufferedReader(new FileReader(fileName));
- String oneLine = null;
- //2.使用readLine方法,一次读一行
- while ((oneLine = br.readLine()) != null) {
- ArrayList<String> oneLineList = getOneLine(oneLine, "##");
- listAll.add(oneLineList);
- }
- br.close();
- } catch (Exception e) {
- System.out.println("读异常.");
- e.printStackTrace();
- }
- return listAll;
- }
- public static ArrayList<String> getOneLine(String content, String split) {
- String[] strArr = content.split(split);
- ArrayList<String> oneLine = new ArrayList<>(strArr.length);
- Collections.addAll(oneLine, strArr);
- return oneLine;
- }
2.写文件
逐行写文件,以追加方式写入,不覆盖已经写入的内容。
- public static void writeFile(String fileName, String content) {
- try {
- // 设置为追加写入true
- BufferedWriter bw = new BufferedWriter(
- new FileWriter(fileName, true));
- bw.write(content);
- bw.close();
- } catch (IOException e) {
- System.out.println("读异常.");
- e.printStackTrace();
- }
- }
3.生成建表语句
根据从txt读取的表字段信息,生成建表语句。
- public static void createTable(String fileName, ArrayList<ArrayList<String>> content) {
- List<String> firstOne = content.get(0);
- String tableName = firstOne.get(0);
- String part1 = "create table ";
- String part2 = tableName;
- String part3 = " ( ";
- writeFile(fileName, part1 + part2 + part3 + "\n");
- String part5 = " );";
- int size = content.size();
- for (int i = 0; i < size; i++) {
- ArrayList<String> oneLine = content.get(i);
- if (StringUtils.equals(tableName, oneLine.get(0))) continue;
- String line = "";
- int last = content.size() - 1;
- if (StringUtils.equals("Y", oneLine.get(2))) {
- line = oneLine.get(0) + " " + oneLine.get(1) + " not null " + "," + "\n";
- } else if (i == last) {
- line = oneLine.get(0) + " " + oneLine.get(1) + "\n";
- } else {
- line = oneLine.get(0) + " " + oneLine.get(1) + "," + "\n";
- }
- writeFile(fileName, " " + line);
- }
- writeFile(fileName, part5 + "\n");
- }
4.生成字段注释
根据从txt读取的表字段信息,生成字段注释。
- public static void createComment(String fileName, ArrayList<ArrayList<String>> content) {
- List<String> firstOne = content.get(0);
- String tableName = firstOne.get(0);
- String tableComment = firstOne.get(1);
- String part1 = "comment on table ";
- String part2 = tableName;
- String part3 = " is '";
- String part4 = tableComment;
- String part5 = "';";
- String tableComments = part1 + part2 + part3 + part4 + part5;
- writeFile(fileName, tableComments + "\n");
- int size = content.size();
- for (int i = 0; i < size; i++) {
- ArrayList<String> oneLine = content.get(i);
- if (StringUtils.equals(tableName, oneLine.get(0))) continue;
- String part01 = "comment on column ";
- String part02 = tableName + ".";
- String part03 = oneLine.get(0);
- String part04 = " is '";
- String part05 = oneLine.get(3) + "';\n";
- String part = part01 + part02 + part03 + part04 + part05;
- writeFile(fileName, part);
- }
- }
5.生成主键约束和索引
根据从txt读取的表字段信息,生成主键约束和索引。
- // 生成主键和索引
- public static void createPrimaryAndIndex(String fileName, ArrayList<ArrayList<String>> content) {
- List<String> firstOne = content.get(0);
- String tableName = firstOne.get(0);
- int size = content.size();
- for (int i = 0; i < size; i++) {
- ArrayList<String> oneLine = content.get(i);
- if (StringUtils.equals(tableName, oneLine.get(0))) continue;
- if (StringUtils.equals("primary", oneLine.get(4).toLowerCase())) {
- String part1 = "alter table ";
- String part2 = tableName;
- String part3 = " add constraint ";
- String part4 = "PK_" + tableName + "_" + oneLine.get(0);
- String part5 = " primary key (" + oneLine.get(0) + ");";
- part4 = getLimitString(part4);
- String pk = part1 + part2 + part3 + part4 + part5;
- writeFile(fileName, pk + "\n");
- }
- if (StringUtils.equals("index", oneLine.get(4).toLowerCase())) {
- String part1 = "create index ";
- String part2 = "IDX_" + tableName + "_" + oneLine.get(0);
- String part3 = " on ";
- String part4 = tableName;
- String part5 = " (" + oneLine.get(0) + ");";
- part2 = getLimitString(part2);
- String index = part1 + part2 + part3 + part4 + part5;
- writeFile(fileName, index + "\n");
- }
- }
- }
- // 限定主键或索引名称字符串30个字符
- public static String getLimitString(String srcStr){
- int length = srcStr.length();
- if (length > 30) {
- srcStr = srcStr.substring(0, 30);
- String underline = srcStr.substring(29, 30);
- if (StringUtils.equals("_", underline)) {
- // 最后一个字符是字母而不是下划线
- srcStr = srcStr.substring(0, 29);
- }
- }
- return srcStr;
- }
6.在main函数调用
在main函数调用测试。
- public static void main(String[] args) {
- System.out.println("开始...");
- String baseDir = "D:\\example\\";
- String fileName = "SENSOR_DATA";
- String txtFileName = baseDir + fileName + ".txt";
- String sqlFileName = baseDir + fileName + ".sql";
- ArrayList<ArrayList<String>> read = readFromTxt(txtFileName);
- // 表结构
- createTable(sqlFileName, read);
- // 注释
- createComment(sqlFileName, read);
- // 主键和索引(单个字段)
- createPrimaryAndIndex(sqlFileName, read);
- System.out.println("结束...");
- }
以上,感谢。
2022年7月1日