美文网首页Spring Boot
基于Velocity的golang xorm生成器

基于Velocity的golang xorm生成器

作者: EasyNetCN | 来源:发表于2020-08-14 15:42 被阅读0次

    本示例可以生产xorm的struct和repository,也可以生成用于返回json的struct。

    CodeGenerator接口

    import java.util.List;
    
    import javax.sql.DataSource;
    
    public interface CodeGenerator {
        boolean generate(DataSource datasource, String db, List<String> tables, String outputPath, String tpl);
    }
    
    

    数据列封装

    import org.apache.commons.lang3.StringUtils;
    
    public class DataColumn {
        private String name;
    
        private long ordinalPosition;
    
        private String defaultValue;
    
        private boolean nullable;
    
        private Long characterMaxLength;
    
        private Long characterOctetLength;
    
        private Long numericPrecision;
    
        private Long numericScale;
    
        private String dataType;
    
        private String columnType;
    
        private String comment;
    
        private boolean identity;
    
        private boolean primary;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public long getOrdinalPosition() {
            return ordinalPosition;
        }
    
        public void setOrdinalPosition(long ordinalPosition) {
            this.ordinalPosition = ordinalPosition;
        }
    
        public String getDefaultValue() {
            return defaultValue;
        }
    
        public void setDefaultValue(String defaultValue) {
            this.defaultValue = defaultValue;
        }
    
        public boolean getNullable() {
            return nullable;
        }
    
        public void setNullable(boolean nullable) {
            this.nullable = nullable;
        }
    
        public Long getCharacterMaxLength() {
            return characterMaxLength;
        }
    
        public void setCharacterMaxLength(Long characterMaxLength) {
            this.characterMaxLength = characterMaxLength;
        }
    
        public Long getCharacterOctetLength() {
            return characterOctetLength;
        }
    
        public void setCharacterOctetLength(Long characterOctetLength) {
            this.characterOctetLength = characterOctetLength;
        }
    
        public Long getNumericPrecision() {
            return numericPrecision;
        }
    
        public void setNumericPrecision(Long numericPrecision) {
            this.numericPrecision = numericPrecision;
        }
    
        public Long getNumericScale() {
            return numericScale;
        }
    
        public void setNumericScale(Long numericScale) {
            this.numericScale = numericScale;
        }
    
        public String getDataType() {
            return dataType;
        }
    
        public void setDataType(String dataType) {
            this.dataType = dataType;
        }
    
        public String getColumnType() {
            return columnType;
        }
    
        public void setColumnType(String columnType) {
            this.columnType = columnType;
        }
    
        public String getComment() {
            return comment;
        }
    
        public void setComment(String comment) {
            this.comment = comment;
        }
    
        public boolean getIdentity() {
            return identity;
        }
    
        public void setIdentity(boolean identity) {
            this.identity = identity;
        }
    
        public boolean getPrimary() {
            return primary;
        }
    
        public void setPrimary(boolean primary) {
            this.primary = primary;
        }
    
        public String getPropertyName() {
            StringBuilder sb = new StringBuilder();
    
            String[] strs = name.split("_");
    
            for (String str : strs) {
                sb.append(StringUtils.capitalize(str));
            }
    
            return sb.toString();
        }
    
        public String getVariableName() {
            StringBuilder sb = new StringBuilder();
    
            String[] strs = name.split("_");
    
            for (int i = 0; i < strs.length; i++) {
                String str = strs[i];
    
                sb.append(i == 0 ? str : StringUtils.capitalize(str));
            }
    
            return sb.toString();
    
        }
    
        public String getGolangType() {
            if (dataType.equalsIgnoreCase("int")) {
                return "int";
            } else if (dataType.equalsIgnoreCase("varchar") || dataType.equalsIgnoreCase("text")
                    || dataType.equalsIgnoreCase("longtext")) {
                return nullable ? "*string" : "string";
            } else if (dataType.equalsIgnoreCase("long") || dataType.equalsIgnoreCase("bigint")) {
                return nullable ? "*int64" : "int64";
            } else if (dataType.equalsIgnoreCase("decimal")) {
                return nullable ? "*float64" : "float64";
            } else if (dataType.equalsIgnoreCase("datetime")) {
                return nullable ? "*time.Time" : "time.Time";
            } else {
                return dataType;
            }
        }
    
        public Boolean isDateType() {
            return dataType.equalsIgnoreCase("datetime");
        }
    
        public Boolean isDecimalType() {
            return dataType.equalsIgnoreCase("decimal");
        }
    
        public String getXormTag() {
            var sb = new StringBuilder("`xorm:\"");
    
            sb.append(dataType);
    
            sb.append(" '");
            sb.append(name);
            sb.append("'");
    
            if (identity) {
                sb.append(" autoincr");
            }
    
            if (primary) {
                sb.append(" pk");
            }
    
            if (nullable) {
                sb.append(" null");
            } else {
                sb.append(" notnull");
            }
    
            sb.append(" default(");
    
            if (dataType.equalsIgnoreCase("varchar") || dataType.equalsIgnoreCase("text")
                    || dataType.equalsIgnoreCase("longtext")) {
                sb.append("'");
            }
    
            sb.append(defaultValue);
    
            if (dataType.equalsIgnoreCase("varchar") || dataType.equalsIgnoreCase("text")
                    || dataType.equalsIgnoreCase("longtext")) {
                sb.append("'");
            }
    
            sb.append(")");
    
            sb.append(" comment('");
            sb.append(comment);
            sb.append("')");
    
            sb.append("\"`");
    
            return sb.toString();
        }
    }
    

    数据表信息封装

    import java.util.List;
    import java.util.stream.Collectors;
    
    import org.apache.commons.lang3.StringUtils;
    
    public class DataEntityDescriptor {
        private String packageName;
    
        private String tableName;
    
        private List<DataColumn> columns;
    
        public String getPackageName() {
            return packageName;
        }
    
        public void setPackageName(String packageName) {
            this.packageName = packageName;
        }
    
        public String getTableName() {
            return tableName;
        }
    
        public void setTableName(String tableName) {
            this.tableName = tableName;
        }
    
        public List<DataColumn> getColumns() {
            return columns;
        }
    
        public void setColumns(List<DataColumn> columns) {
            this.columns = columns;
        }
    
        public String getEntityClassName() {
            StringBuilder sb = new StringBuilder();
            String[] strs = getTableName().split("_");
    
            for (String str : strs) {
                sb.append(StringUtils.capitalize(str));
            }
    
            return sb.toString();
        }
    
        public Boolean hasDateType() {
            return columns.stream().anyMatch(DataColumn::isDateType);
        }
    
        public Boolean hasDecimalType() {
            return columns.stream().anyMatch(DataColumn::isDecimalType);
        }
    
        public String getRepositoryClassName() {
            StringBuilder sb = new StringBuilder();
    
            String[] strs = tableName.split("_");
    
            for (String str : strs) {
                sb.append(StringUtils.capitalize(str));
            }
    
            sb.append("Repository");
    
            return sb.toString();
        }
    
        public String getPrivateRepositoryClassName() {
            StringBuilder sb = new StringBuilder();
    
            String[] strs = tableName.split("_");
    
            for (int i = 0; i < strs.length; i++) {
                String str = strs[i];
    
                sb.append(i == 0 ? str : StringUtils.capitalize(str));
            }
    
            sb.append("Repository");
    
            return sb.toString();
        }
    
        public String getPrimaryColumnDataType() {
            return columns.stream().filter(DataColumn::getPrimary).findFirst().get().getGolangType();
        }
    
        public List<DataColumn> getCommonColumns() {
            return columns.stream().filter(DataColumn::getPrimary).collect(Collectors.toList());
        }
    }
    

    golang代码生成实现

    import java.io.FileWriter;
    import java.io.IOException;
    import java.nio.file.FileVisitResult;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.SimpleFileVisitor;
    import java.nio.file.attribute.BasicFileAttributes;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.sql.DataSource;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.velocity.VelocityContext;
    import org.apache.velocity.app.VelocityEngine;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.RowCallbackHandler;
    import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
    import org.springframework.stereotype.Service;
    
    import generator.model.DataColumn;
    import generator.model.DataEntityDescriptor;
    
    @Service
    public class GolangCodeGenerator implements CodeGenerator {
        private String getAllColumnInfoSql = "SELECT * FROM information_schema.columns WHERE table_schema = :db ORDER BY table_schema ASC,ordinal_position ASC";
        private String getColumnInfoSql = "SELECT * FROM information_schema.columns WHERE table_schema = :db AND table_name IN (:tables) ORDER BY table_schema ASC,ordinal_position ASC";
    
        @Autowired
        VelocityEngine velocityEngine;
    
        @Override
        public boolean generate(DataSource datasource, String db, List<String> tables, String outputPath, String tpl) {
            try {
                Files.walkFileTree(Paths.get(outputPath), new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                        Files.deleteIfExists(file);
    
                        return FileVisitResult.CONTINUE;
                    }
                });
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
    
            var namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(datasource);
    
            Map<String, Object> paramMap = new HashMap<>();
    
            paramMap.put("db", db);
    
            if (null != tables && !tables.isEmpty()) {
                paramMap.put("tables", tables);
            }
    
            Map<String, DataEntityDescriptor> dataEntityDescriptorMap = new LinkedHashMap<>();
    
            namedParameterJdbcTemplate.query(null == tables || tables.isEmpty() ? getAllColumnInfoSql : getColumnInfoSql,
                    paramMap, new RowCallbackHandler() {
                        @Override
                        public void processRow(ResultSet rs) throws SQLException {
                            var table = rs.getString(3);
                            var columnKey = rs.getString(17);
                            var extra = rs.getString(18);
    
                            if (!dataEntityDescriptorMap.containsKey(table)) {
                                var dataEntityDescriptor = new DataEntityDescriptor();
    
                                dataEntityDescriptor.setTableName(table);
                                dataEntityDescriptor.setColumns(new ArrayList<>());
    
                                dataEntityDescriptorMap.put(table, dataEntityDescriptor);
                            }
    
                            var dataEntityDescriptor = dataEntityDescriptorMap.get(table);
    
                            var dataColumn = new DataColumn();
    
                            dataColumn.setName(rs.getString(4));
                            dataColumn.setOrdinalPosition(rs.getLong(5));
                            dataColumn.setDefaultValue(rs.getString(6));
                            dataColumn.setNullable(rs.getString(7).equalsIgnoreCase("YES"));
                            dataColumn.setCharacterMaxLength(rs.getLong(9));
                            dataColumn.setCharacterOctetLength(rs.getLong(10));
                            dataColumn.setNumericPrecision(rs.getLong(11));
                            dataColumn.setNumericScale(rs.getLong(12));
                            dataColumn.setDataType(rs.getString(8));
                            dataColumn.setColumnType(rs.getString(16));
                            dataColumn.setComment(rs.getString(20));
    
                            if (StringUtils.isNotBlank(columnKey) && columnKey.equalsIgnoreCase("PRI")) {
                                dataColumn.setPrimary(true);
                            }
    
                            if (StringUtils.isNotBlank(extra) && extra.equalsIgnoreCase("auto_increment")) {
                                dataColumn.setIdentity(true);
                            }
    
                            dataEntityDescriptor.getColumns().add(dataColumn);
                        }
    
                    });
    
            dataEntityDescriptorMap.values().forEach(dataEntityDescriptor -> {
                var entityClassName = dataEntityDescriptor.getEntityClassName();
    
                var context = new VelocityContext();
    
                context.put("dataEntityDescriptor", dataEntityDescriptor);
                context.put("entityClassName", entityClassName);
                context.put("repositoryClassName", dataEntityDescriptor.getRepositoryClassName());
                context.put("privateRepositoryClassName", dataEntityDescriptor.getPrivateRepositoryClassName());
    
                var sb = new StringBuilder(dataEntityDescriptor.getTableName());
    
                if (tpl.equalsIgnoreCase("repository")) {
                    sb.append("_").append(tpl.toLowerCase());
                }
    
                sb.append(".go");
    
                try (var fileWriter = new FileWriter(Paths.get(outputPath, sb.toString()).toAbsolutePath().toString())) {
    
                    velocityEngine.mergeTemplate("vm/" + tpl + ".vm", "UTF-8", context, fileWriter);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    
            });
    
            return true;
        }
    }
    

    golang repository模板文件

    package repository
    
    import (
        "time"
    
        "xorm.io/xorm"
    )
    
    type $entityClassName struct {
        #foreach($column in $dataEntityDescriptor.columns)
        $column.propertyName             $column.golangType     $column.xormTag
        #end
    }
    
    var (
        ${dataEntityDescriptor.tableName.toUpperCase()}_COLUMNS=[]string{
            #foreach($column in $dataEntityDescriptor.columns)
            "$column.name",
            #end
        }
        
        ${dataEntityDescriptor.tableName.toUpperCase()}_COLUMNS_MAP=map[string]string{
            #foreach($column in $dataEntityDescriptor.columns)
            "$column.name":"$column.name",
            #end
        }
    )
    
    type $repositoryClassName interface {
    
    }
    
    type $privateRepositoryClassName struct {
        engine *xorm.Engine
    }
    
    func New$repositoryClassName(engine *xorm.Engine) $repositoryClassName {
        return &$privateRepositoryClassName{
            engine: engine,
        }
    }
    

    golang json struct模板文件

    package model
    
    
    type $entityClassName struct {
        #foreach($column in $dataEntityDescriptor.columns)
        $column.propertyName           #if($column.golangType == '*time.Time') *string #elseif($column.golangType == 'time.Time') string #else $column.golangType  #end   `json:"${column.variableName}"`
        #end
    }
    

    相关文章

      网友评论

        本文标题:基于Velocity的golang xorm生成器

        本文链接:https://www.haomeiwen.com/subject/nqggdktx.html