Java tutorial
/** * Copyright (c) 2011-2014, hubin (jobob@qq.com). * <p> * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.baomidou.mybatisplus.generator; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import com.baomidou.mybatisplus.annotations.IdType; import com.baomidou.mybatisplus.exceptions.MybatisPlusException; import com.baomidou.mybatisplus.toolkit.DBKeywordsProcessor; import com.baomidou.mybatisplus.toolkit.StringUtils; /** * <p> * ? * </p> * * @author hubin yanghu * @Date 2016-06-12 */ public class AutoGenerator { protected ConfigGenerator config; public ConfigGenerator getConfig() { return config; } public void setConfig(ConfigGenerator config) { this.config = config; } public AutoGenerator() { } public AutoGenerator(ConfigGenerator config) { this.config = config; } protected static String PATH_ENTITY = null; protected static String PATH_MAPPER = null; protected static String PATH_XML = null; protected static String PATH_SERVICE = null; protected static String PATH_SERVICE_IMPL = null; protected static boolean FILE_OVERRIDE = false; protected static final String JAVA_SUFFIX = ".java"; protected static final String XML_SUFFIX = ".xml"; /** * run */ public static void run(ConfigGenerator config) { if (config == null) { throw new MybatisPlusException(" ConfigGenerator is null. "); } else if (config.getIdType() == null) { throw new MybatisPlusException("ConfigGenerator IdType is null"); } /** * ? */ File gf = new File(config.getSaveDir()); if (!gf.exists()) { gf.mkdirs(); } /** * */ String saveDir = gf.getPath(); PATH_ENTITY = getFilePath(saveDir, getPathFromPackageName(config.getEntityPackage())); PATH_MAPPER = getFilePath(saveDir, getPathFromPackageName(config.getMapperPackage())); PATH_XML = getFilePath(saveDir, getPathFromPackageName(config.getXmlPackage())); PATH_SERVICE = getFilePath(saveDir, getPathFromPackageName(config.getServicePackage())); PATH_SERVICE_IMPL = getFilePath(saveDir, getPathFromPackageName(config.getServiceImplPackage())); /** * ?? */ FILE_OVERRIDE = config.isFileOverride(); /** * ?? */ new AutoGenerator(config).generate(); /** * ? * <p> * ? osName * </p> */ try { String osName = System.getProperty("os.name"); if (osName != null) { if (osName.contains("Mac")) { Runtime.getRuntime().exec("open " + config.getSaveDir()); } else if (osName.contains("Windows")) { Runtime.getRuntime().exec("cmd /c start " + config.getSaveDir()); } else { System.err.println("save dir:" + config.getSaveDir()); } } System.out.println(" generate success! "); } catch (IOException e) { e.printStackTrace(); } } /** * ????? * * @param packageName * @return */ protected static String getPathFromPackageName(String packageName) { if (StringUtils.isEmpty(packageName)) { return ""; } return packageName.replace(".", File.separator); } /** * ?? * * @param segment * ? * @return */ protected static String getFilePath(String savePath, String segment) { File folder = new File(savePath + File.separator + segment); if (!folder.exists()) { folder.mkdirs(); } return folder.getPath(); } /** * ? */ public void generate() { Connection conn = null; try { /** * */ Class.forName(config.getDbDriverName()); conn = DriverManager.getConnection(config.getDbUrl(), config.getDbUser(), config.getDbPassword()); /** * ??? */ boolean isOracle = false; if (config.getConfigDataSource() == ConfigDataSource.ORACLE) { isOracle = true; } /** * ????? */ List<String> tables = getTables(conn); if (null == tables) { return; } Map<String, String> tableComments = getTableComment(conn); for (String table : tables) { List<String> columns = new ArrayList<String>(); List<String> types = new ArrayList<String>(); List<String> comments = new ArrayList<String>(); /* ID ?,??? */ boolean idExist = false; Map<String, IdInfo> idMap = new HashMap<String, IdInfo>(); String tableFieldsSql = String.format(config.getConfigDataSource().getTableFieldsSql(), table); ResultSet results = conn.prepareStatement(tableFieldsSql).executeQuery(); while (results.next()) { String field = results.getString(config.getConfigDataSource().getFieldName()); /* ? baseEntity */ if (null != config.getConfigBaseEntity() && config.getConfigBaseEntity().includeColumns(field)) { continue; } columns.add(field); types.add(results.getString(config.getConfigDataSource().getFieldType())); comments.add(results.getString(config.getConfigDataSource().getFieldComment())); if (!isOracle && !idExist) { /* MYSQL ID ?? */ String key = results.getString(config.getConfigDataSource().getFieldKey()); if ("PRI".equals(key)) { boolean autoIncrement = false; if ("auto_increment".equals(results.getString("EXTRA"))) { autoIncrement = true; } idExist = true; idMap.put(field, new IdInfo(field, autoIncrement)); } } } if (isOracle) { /* ORACLE ID ?? */ String idSql = String.format( "SELECT A.COLUMN_NAME FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME AND B.CONSTRAINT_TYPE = 'P' AND A.TABLE_NAME = '%s'", table); ResultSet rs = conn.prepareStatement(idSql).executeQuery(); while (rs.next() && !idExist) { String field = rs.getString(config.getConfigDataSource().getFieldKey()); idExist = true; idMap.put(field, new IdInfo(field, false)); } } String beanName = getBeanName(table, config.isDbPrefix()); String mapperName = String.format(config.getMapperName(), beanName); String mapperXMLName = String.format(config.getMapperXMLName(), beanName); String serviceName = String.format(config.getServiceName(), beanName); String serviceImplName = String.format(config.getServiceImplName(), beanName); /** * ??? */ if (valideFile(PATH_ENTITY, beanName, JAVA_SUFFIX)) { buildEntityBean(columns, types, comments, tableComments.get(table), idMap, table, beanName); } if (valideFile(PATH_MAPPER, mapperName, JAVA_SUFFIX)) { buildMapper(beanName, mapperName); } if (valideFile(PATH_XML, mapperXMLName, XML_SUFFIX)) { buildMapperXml(columns, types, comments, idMap, mapperName, mapperXMLName); } if (valideFile(PATH_SERVICE, serviceName, JAVA_SUFFIX)) { buildService(beanName, serviceName); } if (valideFile(PATH_SERVICE_IMPL, serviceImplName, JAVA_SUFFIX)) { buildServiceImpl(beanName, serviceImplName, serviceName, mapperName); } } } catch (Exception e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } /** * ???? * * @param dirPath * @param beanName * @param suffix * @return */ protected boolean valideFile(String dirPath, String beanName, String suffix) { File file = new File(dirPath, beanName + suffix); return !file.exists() || FILE_OVERRIDE; } /** * ??dbTables. * <ul> * <li>?</li> * <li>custTables.</li> * <li>????null</li> * </ul> * * @return * @throws SQLException */ protected List<String> getTables(Connection conn) throws SQLException { List<String> tables = new ArrayList<String>(); PreparedStatement pstate = conn.prepareStatement(config.getConfigDataSource().getTablesSql()); ResultSet results = pstate.executeQuery(); while (results.next()) { tables.add(results.getString(1)); } String[] tableNames = config.getTableNames(); if (null == tableNames || tableNames.length == 0) { return tables; } // ??? List<String> custTables = Arrays.asList(tableNames); List<String> notExistTables = new ArrayList<String>(); for (String tb : custTables) { if (!tables.contains(tb)) { notExistTables.add(tb); } } if (notExistTables.size() == 0) { return custTables; } // ????null System.err.println("tablename " + notExistTables.toString() + " is not exist!! ==> stop generate!!"); return null; } /** * ? beanName * * @param table * ?? * @return beanName */ protected String getBeanName(String table, boolean includePrefix) { StringBuilder sb = new StringBuilder(); if (table.contains("_")) { String[] tables = table.split("_"); int l = tables.length; int s = 0; if (includePrefix) { s = 1; } for (int i = s; i < l; i++) { String temp = tables[i].trim(); sb.append(temp.substring(0, 1).toUpperCase()).append(temp.substring(1).toLowerCase()); } } else { sb.append(table.substring(0, 1).toUpperCase()).append(table.substring(1).toLowerCase()); } return sb.toString(); } protected String processType(String type) { if (config.getConfigDataSource() == ConfigDataSource.ORACLE) { return oracleProcessType(type); } return mysqlProcessType(type); } /** * MYSQL? * * @param type * * @return */ protected String mysqlProcessType(String type) { String t = type.toLowerCase(); if (t.contains("char")) { return "String"; } else if (t.contains("bigint")) { return "Long"; } else if (t.contains("int")) { return "Integer"; } else if (t.contains("date") || t.contains("timestamp")) { return "Date"; } else if (t.contains("text")) { return "String"; } else if (t.contains("bit")) { return "Boolean"; } else if (t.contains("decimal")) { return "BigDecimal"; } else if (t.contains("blob")) { return "byte[]"; } else if (t.contains("float")) { return "Float"; } else if (t.contains("double")) { return "Double"; } else if (t.contains("json") || t.contains("enum")) { return "String"; } return null; } /** * ORACLE? * * @param type * * @return */ protected String oracleProcessType(String type) { String t = type.toUpperCase(); if (t.contains("CHAR")) { return "String"; } else if (t.contains("DATE") || t.contains("TIMESTAMP")) { return "Date"; } else if (t.contains("NUMBER")) { if (t.matches("NUMBER\\(+\\d{1}+\\)")) { return "Integer"; } else if (t.matches("NUMBER\\(+\\d{2}+\\)")) { return "Long"; } return "Double"; } else if (t.contains("FLOAT")) { return "Float"; } else if (t.contains("BLOB")) { return "Object"; } else if (t.contains("RAW")) { return "byte[]"; } return null; } /** * ? * * @param types * * @return */ protected boolean isDate(List<String> types) { for (String type : types) { String t = type.toLowerCase(); if (t.contains("date") || t.contains("timestamp")) { return true; } } return false; } /** * ? * * @param types * * @return */ protected boolean isDecimal(List<String> types) { for (String type : types) { if (type.toLowerCase().contains("decimal")) { return true; } } return false; } /** * ? * * @param field * * @return */ protected String processField(String field) { /* * ?? */ if (!field.contains("_")) { if (StringUtils.isUpperCase(field)) { /* * ??? */ return field.toLowerCase(); } return field; } /* * ??? */ StringBuilder sb = new StringBuilder(); String[] fields = field.split("_"); sb.append(fields[0].toLowerCase()); for (int i = 1; i < fields.length; i++) { String temp = fields[i]; sb.append(temp.substring(0, 1).toUpperCase()); sb.append(temp.substring(1).toLowerCase()); } return sb.toString(); } /** * ? * * @param bw * @param text * @return * @throws IOException */ protected BufferedWriter buildClassComment(BufferedWriter bw, String text) throws IOException { bw.newLine(); bw.write("/**"); bw.newLine(); bw.write(" *"); bw.newLine(); bw.write(" * " + text); bw.newLine(); bw.write(" *"); bw.newLine(); bw.write(" */"); return bw; } /** * ? * * @param columns * @param types * @param comments * @throws IOException */ protected void buildEntityBean(List<String> columns, List<String> types, List<String> comments, String tableComment, Map<String, IdInfo> idMap, String table, String beanName) throws IOException { File beanFile = new File(PATH_ENTITY, beanName + ".java"); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(beanFile))); bw.write("package " + config.getEntityPackage() + ";"); bw.newLine(); bw.newLine(); bw.write("import java.io.Serializable;"); bw.newLine(); if (isDate(types)) { bw.write("import java.util.Date;"); bw.newLine(); } if (isDecimal(types)) { bw.write("import java.math.BigDecimal;"); bw.newLine(); } bw.newLine(); if (config.getIdType() != IdType.ID_WORKER) { bw.write("import com.baomidou.mybatisplus.annotations.IdType;"); bw.newLine(); } bw.newLine(); /* * ? BaseEntity */ if (null != config.getConfigBaseEntity() && null != config.getConfigBaseEntity().getPackageName() && !config.getEntityPackage().equals(config.getConfigBaseEntity().getPackageName())) { bw.write("import " + config.getConfigBaseEntity().getPackageName() + ";"); bw.newLine(); } bw.write("import com.baomidou.mybatisplus.annotations.TableField;"); bw.newLine(); if (null == config.getConfigBaseEntity()) { bw.write("import com.baomidou.mybatisplus.annotations.TableId;"); bw.newLine(); } if (table.contains("_")) { bw.write("import com.baomidou.mybatisplus.annotations.TableName;"); bw.newLine(); } bw = buildClassComment(bw, tableComment); bw.newLine(); /* ? */ if (table.contains("_")) { bw.write("@TableName(\"" + table + "\")"); bw.newLine(); } /** * ???? BaseEntity */ if (null != config.getConfigBaseEntity()) { bw.write("public class " + beanName + " extends " + config.getConfigBaseEntity().getClassName() + " {"); } else { bw.write("public class " + beanName + " implements Serializable {"); } bw.newLine(); bw.newLine(); bw.write("\t@TableField(exist = false)"); bw.newLine(); bw.write("\tprivate static final long serialVersionUID = 1L;"); bw.newLine(); int size = columns.size(); for (int i = 0; i < size; i++) { bw.newLine(); bw.write("\t/** " + comments.get(i) + " */"); bw.newLine(); /* * ID <br> isLine ?? */ String column = columns.get(i); String field = processField(column); boolean isLine = column.contains("_"); IdInfo idInfo = idMap.get(column); if (idInfo != null) { // @TableId(value = "test_id", type = IdType.AUTO) bw.write("\t@TableId"); String idType = toIdType(); if (isLine) { if (config.isDbColumnUnderline()) { // if (null != idType) { bw.write("("); bw.write(idType); bw.write(")"); } } else { bw.write("(value = \"" + column + "\""); if (null != idType) { bw.write(", "); bw.write(idType); } bw.write(")"); } } else if (null != idType) { bw.write("("); bw.write(idType); bw.write(")"); } bw.newLine(); } else if (isLine && !config.isDbColumnUnderline()) { // @TableField(value = "test_type", exist = false) bw.write("\t@TableField(value = \"" + column + "\")"); bw.newLine(); } bw.write("\tprivate " + processType(types.get(i)) + " " + field + ";"); bw.newLine(); } /* * ?? */ this.buildEntityBeanColumnConstant(columns, types, comments, bw, size); bw.newLine(); /* * ?get set */ for (int i = 0; i < size; i++) { String _tempType = processType(types.get(i)); String _tempField = processField(columns.get(i)); String _field = _tempField.substring(0, 1).toUpperCase() + _tempField.substring(1); bw.newLine(); bw.write("\tpublic " + _tempType + " get" + _field + "() {"); bw.newLine(); bw.write("\t\treturn this." + _tempField + ";"); bw.newLine(); bw.write("\t}"); bw.newLine(); bw.newLine(); /* ? */ if (config.isBuliderModel()) { bw.write("\tpublic " + beanName + " set" + _field + "(" + _tempType + " " + _tempField + ") {"); bw.newLine(); bw.write("\t\tthis." + _tempField + " = " + _tempField + ";"); bw.newLine(); bw.write("\t\treturn this;"); } else { bw.write("\tpublic void set" + _field + "(" + _tempType + " " + _tempField + ") {"); bw.newLine(); bw.write("\t\tthis." + _tempField + " = " + _tempField + ";"); } bw.newLine(); bw.write("\t}"); bw.newLine(); } bw.newLine(); bw.write("}"); bw.newLine(); bw.flush(); bw.close(); } protected void buildEntityBeanColumnConstant(List<String> columns, List<String> types, List<String> comments, BufferedWriter bw, int size) throws IOException { /* * ???? false */ if (config.isColumnConstant()) { for (int i = 0; i < size; i++) { String _tempType = processType(types.get(i)); String _column = columns.get(i); bw.newLine(); bw.write("\tpublic static final " + _tempType + " " + _column.toUpperCase() + " = \"" + _column + "\";"); } bw.newLine(); } } public String toIdType() { if (config.getIdType() == IdType.AUTO) { return "type = IdType.AUTO"; } else if (config.getIdType() == IdType.INPUT) { return "type = IdType.INPUT"; } else if (config.getIdType() == IdType.UUID) { return "type = IdType.UUID"; } return null; } /** * Mapper * * @param beanName * @param mapperName * @throws IOException */ protected void buildMapper(String beanName, String mapperName) throws IOException { File mapperFile = new File(PATH_MAPPER, mapperName + ".java"); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mapperFile), "utf-8")); bw.write("package " + config.getMapperPackage() + ";"); bw.newLine(); bw.newLine(); bw.write("import " + config.getEntityPackage() + "." + beanName + ";"); bw.newLine(); if (config.getConfigIdType() == ConfigIdType.STRING) { bw.write("import com.baomidou.mybatisplus.mapper.CommonMapper;"); } else { bw.write("import com.baomidou.mybatisplus.mapper.AutoMapper;"); } bw.newLine(); bw = buildClassComment(bw, beanName + " ??"); bw.newLine(); if (config.getConfigIdType() == ConfigIdType.STRING) { bw.write("public interface " + mapperName + " extends CommonMapper<" + beanName + "> {"); } else { bw.write("public interface " + mapperName + " extends AutoMapper<" + beanName + "> {"); } bw.newLine(); bw.newLine(); // ----------mapperEnd---------- bw.newLine(); bw.write("}"); bw.flush(); bw.close(); } /** * XML * * @param columns * @param types * @param comments * @throws IOException */ protected void buildMapperXml(List<String> columns, List<String> types, List<String> comments, Map<String, IdInfo> idMap, String mapperName, String mapperXMLName) throws IOException { File mapperXmlFile = new File(PATH_XML, mapperXMLName + ".xml"); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(mapperXmlFile))); bw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); bw.newLine(); bw.write( "<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">"); bw.newLine(); bw.write("<mapper namespace=\"" + config.getMapperPackage() + "." + mapperName + "\">"); bw.newLine(); bw.newLine(); /* * ?SqlMapper */ buildSQL(bw, idMap, columns); bw.write("</mapper>"); bw.flush(); bw.close(); } /** * service * * @param beanName * @param serviceName * @throws IOException */ protected void buildService(String beanName, String serviceName) throws IOException { File serviceFile = new File(PATH_SERVICE, serviceName + ".java"); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(serviceFile), "utf-8")); bw.write("package " + config.getServicePackage() + ";"); bw.newLine(); bw.newLine(); bw.write("import " + config.getEntityPackage() + "." + beanName + ";"); bw.newLine(); String superService = config.getSuperService(); bw.write("import " + superService + ";"); bw.newLine(); bw = buildClassComment(bw, beanName + " ???"); bw.newLine(); superService = superService.substring(superService.lastIndexOf(".") + 1); bw.write("public interface " + serviceName + " extends " + superService + "<" + beanName + "> {"); bw.newLine(); bw.newLine(); // ----------serviceEnd---------- bw.newLine(); bw.write("}"); bw.flush(); bw.close(); } /** * service * * @param beanName * @param serviceImplName * @param mapperName * @throws IOException */ protected void buildServiceImpl(String beanName, String serviceImplName, String serviceName, String mapperName) throws IOException { File serviceFile = new File(PATH_SERVICE_IMPL, serviceImplName + ".java"); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(serviceFile), "utf-8")); bw.write("package " + config.getServiceImplPackage() + ";"); bw.newLine(); bw.newLine(); bw.write("import org.springframework.stereotype.Service;"); bw.newLine(); bw.newLine(); bw.write("import " + config.getMapperPackage() + "." + mapperName + ";"); bw.newLine(); bw.write("import " + config.getEntityPackage() + "." + beanName + ";"); bw.newLine(); bw.write("import " + config.getServicePackage() + "." + serviceName + ";"); bw.newLine(); String superServiceImpl = config.getSuperServiceImpl(); bw.write("import " + superServiceImpl + ";"); bw.newLine(); bw = buildClassComment(bw, beanName + " ???"); bw.newLine(); bw.write("@Service"); bw.newLine(); superServiceImpl = superServiceImpl.substring(superServiceImpl.lastIndexOf(".") + 1); bw.write("public class " + serviceImplName + " extends " + superServiceImpl + "<" + mapperName + ", " + beanName + "> implements " + serviceName + " {"); bw.newLine(); bw.newLine(); // ----------serviceEnd---------- bw.newLine(); bw.write("}"); bw.flush(); bw.close(); } /** * ? * * @param bw * @param idMap * @param columns * @throws IOException */ protected void buildSQL(BufferedWriter bw, Map<String, IdInfo> idMap, List<String> columns) throws IOException { int size = columns.size(); bw.write("\t<!-- -->"); bw.newLine(); bw.write("\t<sql id=\"Base_Column_List\">"); bw.newLine(); bw.write("\t\t"); /* * */ if (null != config.getConfigBaseEntity()) { for (String column : config.getConfigBaseEntity().getColumns()) { bw.write(DBKeywordsProcessor.convert(column)); if (column.contains("_")) { bw.write(" AS " + processField(column)); } bw.write(", "); } } /** * */ for (int i = 0; i < size; i++) { String column = columns.get(i); IdInfo idInfo = idMap.get(column); if (idInfo != null) { bw.write(DBKeywordsProcessor.convert(idInfo.getValue())); if (idInfo.getValue().contains("_")) { bw.write(" AS " + processField(idInfo.getValue())); } } else { if (null == config.getConfigBaseEntity()) { bw.write(" "); } bw.write(DBKeywordsProcessor.convert(column)); if (column.contains("_")) { bw.write(" AS " + processField(column)); } } if (i != size - 1) { bw.write(","); } } bw.newLine(); bw.write("\t</sql>"); bw.newLine(); bw.newLine(); } /** * ?? * * @return * @throws SQLException */ protected Map<String, String> getTableComment(Connection conn) throws SQLException { Map<String, String> maps = new HashMap<String, String>(); PreparedStatement pstate = conn.prepareStatement(config.getConfigDataSource().getTableCommentsSql()); ResultSet results = pstate.executeQuery(); while (results.next()) { maps.put(results.getString(config.getConfigDataSource().getTableName()), results.getString(config.getConfigDataSource().getTableComment())); } return maps; } class IdInfo { private String value; private boolean autoIncrement; public IdInfo(String value, boolean autoIncrement) { this.value = value; this.autoIncrement = autoIncrement; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public boolean isAutoIncrement() { return autoIncrement; } public void setAutoIncrement(boolean autoIncrement) { this.autoIncrement = autoIncrement; } } }