• 使用Java根据约定格式生成Oracle建表语句


    记录:278

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

    版本:Spring Boot 2.6.3

    一、案例场景

    1.开发文档中以表格方式提供建表信息。

    2.手动转换为txt文件,文件名:SENSOR_DATA.txt,格式约定如下:

    第一行为,表名##表名称。

    第二行开始,每行:字段名称##字段类型##字段非空##字段注释##字段主键或者索引。

    1. SENSOR_DATA##传感器数据
    2. ID##NUMBER(16)##Y##实体唯一标识##primary
    3. REGION##VARCHAR2(8)##N##区域##index
    4. VALUE1##NUMBER(16,2)##N##取值1##N
    5. VALUE2##NUMBER(16,2)##N##取值2##N

     3.执行代码,自动生成sql文件,文件名:SENSOR_DATA.sql,生成结果。

    1. create table SENSOR_DATA (
    2. ID NUMBER(16) not null ,
    3. REGION VARCHAR2(8),
    4. VALUE1 NUMBER(16,2),
    5. VALUE2 NUMBER(16,2)
    6. );
    7. comment on table SENSOR_DATA is '传感器数据';
    8. comment on column SENSOR_DATA.ID is '实体唯一标识';
    9. comment on column SENSOR_DATA.REGION is '区域';
    10. comment on column SENSOR_DATA.VALUE1 is '取值1';
    11. comment on column SENSOR_DATA.VALUE2 is '取值2';
    12. alter table SENSOR_DATA add constraint PK_SENSOR_DATA_ID primary key (ID);
    13. 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>中。

    1. public static ArrayList<ArrayList<String>> readFromTxt(String fileName) {
    2. ArrayList<ArrayList<String>> listAll = new ArrayList<>();
    3. try {
    4. //1.读txt文件,一次读一行
    5. BufferedReader br = new BufferedReader(new FileReader(fileName));
    6. String oneLine = null;
    7. //2.使用readLine方法,一次读一行
    8. while ((oneLine = br.readLine()) != null) {
    9. ArrayList<String> oneLineList = getOneLine(oneLine, "##");
    10. listAll.add(oneLineList);
    11. }
    12. br.close();
    13. } catch (Exception e) {
    14. System.out.println("读异常.");
    15. e.printStackTrace();
    16. }
    17. return listAll;
    18. }
    19. public static ArrayList<String> getOneLine(String content, String split) {
    20. String[] strArr = content.split(split);
    21. ArrayList<String> oneLine = new ArrayList<>(strArr.length);
    22. Collections.addAll(oneLine, strArr);
    23. return oneLine;
    24. }

    2.写文件

    逐行写文件,以追加方式写入,不覆盖已经写入的内容。

    1. public static void writeFile(String fileName, String content) {
    2. try {
    3. // 设置为追加写入true
    4. BufferedWriter bw = new BufferedWriter(
    5. new FileWriter(fileName, true));
    6. bw.write(content);
    7. bw.close();
    8. } catch (IOException e) {
    9. System.out.println("读异常.");
    10. e.printStackTrace();
    11. }
    12. }

    3.生成建表语句

    根据从txt读取的表字段信息,生成建表语句。

    1. public static void createTable(String fileName, ArrayList<ArrayList<String>> content) {
    2. List<String> firstOne = content.get(0);
    3. String tableName = firstOne.get(0);
    4. String part1 = "create table ";
    5. String part2 = tableName;
    6. String part3 = " ( ";
    7. writeFile(fileName, part1 + part2 + part3 + "\n");
    8. String part5 = " );";
    9. int size = content.size();
    10. for (int i = 0; i < size; i++) {
    11. ArrayList<String> oneLine = content.get(i);
    12. if (StringUtils.equals(tableName, oneLine.get(0))) continue;
    13. String line = "";
    14. int last = content.size() - 1;
    15. if (StringUtils.equals("Y", oneLine.get(2))) {
    16. line = oneLine.get(0) + " " + oneLine.get(1) + " not null " + "," + "\n";
    17. } else if (i == last) {
    18. line = oneLine.get(0) + " " + oneLine.get(1) + "\n";
    19. } else {
    20. line = oneLine.get(0) + " " + oneLine.get(1) + "," + "\n";
    21. }
    22. writeFile(fileName, " " + line);
    23. }
    24. writeFile(fileName, part5 + "\n");
    25. }

    4.生成字段注释

    根据从txt读取的表字段信息,生成字段注释。

    1. public static void createComment(String fileName, ArrayList<ArrayList<String>> content) {
    2. List<String> firstOne = content.get(0);
    3. String tableName = firstOne.get(0);
    4. String tableComment = firstOne.get(1);
    5. String part1 = "comment on table ";
    6. String part2 = tableName;
    7. String part3 = " is '";
    8. String part4 = tableComment;
    9. String part5 = "';";
    10. String tableComments = part1 + part2 + part3 + part4 + part5;
    11. writeFile(fileName, tableComments + "\n");
    12. int size = content.size();
    13. for (int i = 0; i < size; i++) {
    14. ArrayList<String> oneLine = content.get(i);
    15. if (StringUtils.equals(tableName, oneLine.get(0))) continue;
    16. String part01 = "comment on column ";
    17. String part02 = tableName + ".";
    18. String part03 = oneLine.get(0);
    19. String part04 = " is '";
    20. String part05 = oneLine.get(3) + "';\n";
    21. String part = part01 + part02 + part03 + part04 + part05;
    22. writeFile(fileName, part);
    23. }
    24. }

    5.生成主键约束和索引

    根据从txt读取的表字段信息,生成主键约束和索引。

    1. // 生成主键和索引
    2. public static void createPrimaryAndIndex(String fileName, ArrayList<ArrayList<String>> content) {
    3. List<String> firstOne = content.get(0);
    4. String tableName = firstOne.get(0);
    5. int size = content.size();
    6. for (int i = 0; i < size; i++) {
    7. ArrayList<String> oneLine = content.get(i);
    8. if (StringUtils.equals(tableName, oneLine.get(0))) continue;
    9. if (StringUtils.equals("primary", oneLine.get(4).toLowerCase())) {
    10. String part1 = "alter table ";
    11. String part2 = tableName;
    12. String part3 = " add constraint ";
    13. String part4 = "PK_" + tableName + "_" + oneLine.get(0);
    14. String part5 = " primary key (" + oneLine.get(0) + ");";
    15. part4 = getLimitString(part4);
    16. String pk = part1 + part2 + part3 + part4 + part5;
    17. writeFile(fileName, pk + "\n");
    18. }
    19. if (StringUtils.equals("index", oneLine.get(4).toLowerCase())) {
    20. String part1 = "create index ";
    21. String part2 = "IDX_" + tableName + "_" + oneLine.get(0);
    22. String part3 = " on ";
    23. String part4 = tableName;
    24. String part5 = " (" + oneLine.get(0) + ");";
    25. part2 = getLimitString(part2);
    26. String index = part1 + part2 + part3 + part4 + part5;
    27. writeFile(fileName, index + "\n");
    28. }
    29. }
    30. }
    31. // 限定主键或索引名称字符串30个字符
    32. public static String getLimitString(String srcStr){
    33. int length = srcStr.length();
    34. if (length > 30) {
    35. srcStr = srcStr.substring(0, 30);
    36. String underline = srcStr.substring(29, 30);
    37. if (StringUtils.equals("_", underline)) {
    38. // 最后一个字符是字母而不是下划线
    39. srcStr = srcStr.substring(0, 29);
    40. }
    41. }
    42. return srcStr;
    43. }

    6.在main函数调用

    在main函数调用测试。

    1. public static void main(String[] args) {
    2. System.out.println("开始...");
    3. String baseDir = "D:\\example\\";
    4. String fileName = "SENSOR_DATA";
    5. String txtFileName = baseDir + fileName + ".txt";
    6. String sqlFileName = baseDir + fileName + ".sql";
    7. ArrayList<ArrayList<String>> read = readFromTxt(txtFileName);
    8. // 表结构
    9. createTable(sqlFileName, read);
    10. // 注释
    11. createComment(sqlFileName, read);
    12. // 主键和索引(单个字段)
    13. createPrimaryAndIndex(sqlFileName, read);
    14. System.out.println("结束...");
    15. }

    以上,感谢。

    2022年7月1日

  • 相关阅读:
    NLP新手入门指南|北大-TANGENT
    深究防火墙
    基于inotify实现落盘文件的跨进程实时读写交互
    小波去噪算法的简易实现及其扩展(小波锐化、高斯拉普拉斯金字塔去噪及锐化)之一。
    关于dubbo快速开发和服务提供者无法注册上注意点
    MongoDB聚合运算符:$denseRank
    多表操作-外键级联操作
    数据结构-二叉树
    文本文件的读取+操作
    域名竞价要注意什么?
  • 原文地址:https://blog.csdn.net/zhangbeizhen18/article/details/125567405