通过java实体类逆向生成创建数据表的sql

小灰灰 2023-10-09 23:11 155阅读 0赞

以下代码略有瑕疵,需要根据自己的实际情况进行少许更改即可

  1. import lombok.extern.slf4j.Slf4j;
  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.lang.reflect.Field;
  6. import java.util.ArrayList;
  7. import java.util.HashMap;
  8. import java.util.List;
  9. import java.util.Map;
  10. @Slf4j
  11. public class SqlGenerator {
  12. //-1小写,1大写
  13. public static final int format = -1;
  14. /**
  15. * 用来存储Java等属性类型与sql中属性类型的对照
  16. * </br>
  17. * 例如:java.lang.Integer 对应 integer
  18. */
  19. public static Map<String, String> map = new HashMap<>();
  20. public static void main(String[] args) {
  21. map.put("boolean", "tinyint(1)");
  22. map.put("int", "int");
  23. map.put("short", "int");
  24. map.put("long", "bigint");
  25. map.put("float", "float");
  26. map.put("double", "double");
  27. map.put("char", "varchar(255)");
  28. map.put("java.lang.Object", "text");
  29. map.put("java.lang.String", "varchar(255)");
  30. map.put("java.lang.Integer", "int");
  31. map.put("java.lang.byte[]", "blob");
  32. map.put("java.lang.Boolean", "bit");
  33. map.put("java.lang.Long", "integer unsigned");
  34. map.put("java.math.BigInteger", "bigint unsigned");
  35. map.put("java.lang.Float", "float");
  36. map.put("java.lang.Double", "float");
  37. map.put("java.sql.Date", "datetime");
  38. map.put("java.sql.Time", "time");
  39. map.put("java.sql.Timestamp", "datetime");
  40. map.put("java.util.Date", "datetime");
  41. map.put("java.lang.Byte", "tinyint");
  42. sqlConstruction();
  43. }
  44. /**
  45. * 生成sql建库语句
  46. */
  47. private static void sqlConstruction() {
  48. //实体类所在的package在磁盘上的绝对路径
  49. String packageName = "C:\\Users\\Administrator\\Desktop\\dletc-qpt\\etc-em-api\\src\\main\\java\\com\\etc\\major\\domain";
  50. //生成sql的文件夹
  51. String filePath = "D:\\tmp4";
  52. //项目中实体类的路径
  53. String prefix = "com.etc.major.domain.";
  54. String className = "";
  55. StringBuffer sqls = new StringBuffer();
  56. //获取包下的所有类名称
  57. List<String> list = getAllClasses(packageName);
  58. for (String str : list) {
  59. className = prefix + str.substring(0, str.lastIndexOf("."));
  60. String sql = generateSql(className, filePath);
  61. sqls.append(sql);
  62. }
  63. StringToSql(sqls.toString(), filePath + ".sql");
  64. }
  65. /**
  66. * 根据实体类生成建表语句
  67. *
  68. * @param className 全类名
  69. * @param filePath 磁盘路径
  70. * @return
  71. */
  72. public static String generateSql(String className, String filePath) {
  73. try {
  74. Class<?> clz = Class.forName(className);
  75. className = clz.getSimpleName();
  76. // 表表名adminUser → tb_admin_user
  77. className = getStandardFields(className).toLowerCase();
  78. Field[] fields = clz.getDeclaredFields();
  79. StringBuffer column = new StringBuffer();
  80. String varchar = " CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,";
  81. for (Field f : fields) {
  82. System.out.println(f.getType().getName());
  83. String typeName = f.getType().getName();
  84. if (f.getName().equals("serialVersionUID")) {
  85. continue;
  86. }
  87. if ("java.lang.String".equals(typeName)) {
  88. column.append(" \n `" + getStandardFields(f.getName()) + "`" + " " + map.get(typeName)).append(varchar);
  89. } else {
  90. if(f.getName().equalsIgnoreCase("id")){
  91. column.append(" \n `id` int(11) NOT NULL AUTO_INCREMENT,");
  92. }else {
  93. column.append(" \n `" + getStandardFields(f.getName()) + "`" + " " + map.get(typeName)).append(",");
  94. }
  95. }
  96. }
  97. StringBuffer sql = new StringBuffer();
  98. sql.append("\n DROP TABLE IF EXISTS `" + className + "`; ")
  99. .append(" \n CREATE TABLE `" + className + "` (")
  100. // .append(" \n `id` int(11) NOT NULL AUTO_INCREMENT,")
  101. .append(column)
  102. .append(" \n PRIMARY KEY (`id`) USING BTREE,")
  103. .append("\n INDEX `id`(`id`) USING BTREE")
  104. .append(" \n ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci;\n");
  105. return sql.toString();
  106. } catch (ClassNotFoundException e) {
  107. log.info("该类未找到!");
  108. return null;
  109. }
  110. }
  111. /**
  112. * 转换为标准等sql字段 例如 adminUser → admin_user
  113. *
  114. * @param str 转换为字符串的字段名
  115. * @return
  116. */
  117. public static String getStandardFields(String str) {
  118. StringBuffer sb = new StringBuffer();
  119. for (int i = 0; i < str.length(); i++) {
  120. char c = str.charAt(i);
  121. if (i != 0 && (c > 'A' && c < 'Z')) {
  122. sb.append("_");
  123. }
  124. sb.append(c);
  125. }
  126. return sb.toString();
  127. }
  128. /**
  129. * 获取包下面等所有实体类名称,类似于获取 XXX.java
  130. *
  131. * @param packageName 全类名
  132. * @return
  133. */
  134. public static List<String> getAllClasses(String packageName) {
  135. List<String> classList = new ArrayList();
  136. String className = "";
  137. File f = new File(packageName);
  138. if (f.exists() && f.isDirectory()) {
  139. File[] files = f.listFiles();
  140. // 遍历实体类下面等所有.java文件 获取其类名
  141. for (File file : files) {
  142. className = file.getName();
  143. classList.add(className);
  144. }
  145. return classList;
  146. } else {
  147. log.info("包路径未找到!");
  148. return null;
  149. }
  150. }
  151. /**
  152. * 将生成等String字符串 写进sql文件
  153. *
  154. * @param str String字符串
  155. * @param path sql文件路径路径
  156. */
  157. public static void StringToSql(String str, String path) {
  158. if (format < 0) {
  159. str = str.toLowerCase();
  160. } else {
  161. str = str.toUpperCase();
  162. }
  163. System.out.println(str);
  164. byte[] sourceByte = str.getBytes();
  165. FileOutputStream os = null;
  166. if (null != sourceByte) {
  167. try {
  168. //文件路径(路径+文件名)
  169. File file = new File(path);
  170. //文件不存在则创建文件,先创建目录
  171. if (!file.exists()) {
  172. File dir = new File(file.getParent());
  173. dir.mkdirs();
  174. file.createNewFile();
  175. }
  176. //文件输出流用于将数据写入文件
  177. os = new FileOutputStream(file);
  178. os.write(sourceByte);
  179. os.flush();
  180. System.out.println("生成成功!!");
  181. } catch (Exception e) {
  182. e.printStackTrace();
  183. } finally {
  184. // 关闭文件输出流
  185. try {
  186. if (os != null) {
  187. os.close();
  188. }
  189. } catch (IOException e) {
  190. e.printStackTrace();
  191. }
  192. }
  193. }
  194. }
  195. }

使用方法:

第一步:新建一个类将代码放进去

第二步:更改代码中的 packageName prefix className 等,自己看情况改

第三步:直接运行main方法

这个亲测可用

发表评论

表情:
评论列表 (有 0 条评论,155人围观)

还没有评论,来说两句吧...

相关阅读