根据数据库表名生成java实体类、根据实体生成创建表语句

45 篇文章 0 订阅

公司用的jpa,没有用mybatis。所以也没有用mybatis自动生成。但有些数据库表字段太多,就想着一劳永逸了,连数据库注释都搞上去

第一种

这里使用的是jdbcTemplate+Junit测试生成,方式可变。

SpringBoot版本是2.4.4,只需要加上@SpringBootTest就可以了。不用@RunWith

pom:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

代码

package com.shinedata.bims.web;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName TestController
 * @Author yupanpan
 * @Date 2021/4/12 14:24
 */
@SpringBootTest
public class TestController {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Test
    public void database(){
        createEntity("1ceping", "t_evaluation_template_info_copy","com.shinedata.bims.entity",false);
    }

    /**
     *
     * @param dataBaseName 数据库名
     * @param tableName 表名
     * @param packageName 包名
     * @param isAddEntitySuffix 类名是否添加Entity后缀 true-添加 false-不添加
     */
    public void createEntity(String dataBaseName,String tableName,String packageName,boolean isAddEntitySuffix){
        String className=tableName;
        if(tableName.substring(0,2).equals("t_")){
            StringBuilder stringBuilder = new StringBuilder(tableName);
            stringBuilder.replace(0, 2, "");
            String initialsUpperCase = stringBuilder.substring(0, 1).toUpperCase();
            className=initialsUpperCase+stringBuilder.substring(1);
        }
        className=removeUnderline(className)+(isAddEntitySuffix?"Entity":"");

        StringBuffer classBuffer=new StringBuffer();
        classBuffer.append("import java.util.Date;\r\n");
        classBuffer.append("import java.time.LocalDateTime;\r\n");
        classBuffer.append("import com.alibaba.fastjson.JSONObject;\r\n");
        classBuffer.append("import java.lang.*;\r\n");
        classBuffer.append("import java.math.*;\r\n");
        classBuffer.append("import java.sql.*;\r\n");
        classBuffer.append("import lombok.Data;\r\n\r\n\r\n");
        classBuffer.append("@Data\r\n");
        classBuffer.append("public class " + className + " {\r\n\r\n");
        List<Map> filedMaps = getFiledMaps(dataBaseName, tableName);
        processAllAttrs(classBuffer,filedMaps);
        classBuffer.append("}\r\n");
        markerBean(className,classBuffer.toString(),packageName);
    }

    /**
     * 创建实体类文件
     * @param className 类名(不包含.java文件名后缀) 根据表名首字母大写并去掉开头t_和所有下划线-驼峰命名
     * @param content 添加的内容(字段注释等)
     * @param packageName 包名(com.xxx.xxx.xxx)
     */
    public void markerBean(String className, String content, String packageName) {
        String folder = System.getProperty("user.dir") + "/src/main/java/" + packageName.replace(".","/") + "/";
        File file = new File(folder);
        if (!file.exists()) {
            file.mkdirs();
        }
        String fileName = folder + className + ".java";
        try {
            File newjava = new File(fileName);
            FileWriter fw = new FileWriter(newjava);
            fw.write("package\t" + packageName + ";\r\n");
            fw.write(content);
            fw.flush();
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解析输出属性
     *
     * @return
     */
    private void processAllAttrs(StringBuffer sb,List<Map> filedMaps) {
        for (int i = 0; i < filedMaps.size(); i++) {
            Map map = filedMaps.get(i);
            String fieldType = MapUtils.getString(map, "fieldType");
            String fieldName = MapUtils.getString(map, "fieldName");
            String fieldComment = MapUtils.getString(map, "fieldComment");
            if(StringUtils.isNotBlank(fieldComment)){
                sb.append("\t/**\r\n").append("\t* ").append(fieldComment).append("\n").append("\t*/\r\n");
            }
            sb.append("\tprivate " + fieldType + " " + fieldName + ";\r\n\r\n");
        }
    }

    /**
     * 获取表字段信息(列名、类型、注释等)
     * @param dataBaseName
     * @param tableName
     * @return
     */
    private List<Map> getFiledMaps(String dataBaseName,String tableName) {
        String sql="SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA ='"+dataBaseName+"' AND TABLE_NAME = '"+tableName+"'";
        List<Map> tableFieldList = jdbcTemplate.query(sql, new RowMapper<Map>() {
            @Override
            public Map<String,String> mapRow(ResultSet resultSet, int rowNum) throws SQLException {
                Map<String,String> fieldMap = new HashMap();
                String column_name = resultSet.getString("COLUMN_NAME");
                setFieldName(column_name.toLowerCase(),fieldMap);
                String data_type = resultSet.getString("DATA_TYPE");
                setFieldType(data_type.toUpperCase(),fieldMap);
                fieldMap.put("fieldComment",resultSet.getString("COLUMN_COMMENT"));
                return fieldMap;
            }
        });
        return tableFieldList;
    }


    private void setFieldName(String columnName, Map fieldMap) {
        fieldMap.put("fieldName",removeUnderline(columnName));
    }

    /**
     * 去下划线
     * @param string
     * @return
     */
    public String removeUnderline(String string){
        StringBuilder columnNameBuilder=new StringBuilder(string);
        if(!string.contains("_")){
            return string;
        }else {
            int i = columnNameBuilder.indexOf("_");
            columnNameBuilder.replace(i,i+1, "").replace(i,i+1,columnNameBuilder.substring(i,i+1).toUpperCase());
            return removeUnderline(columnNameBuilder.toString());
        }
    }

    private void setFieldType(String columnType,Map fieldMap){
        String fieldType="String";
        if(columnType.equals("INT")||columnType.equals("INTEGER")){
            fieldType="Integer";
        }else if(columnType.equals("BIGINT")){
            fieldType="Long";
        }else if(columnType.equals("DATETIME")){
            fieldType="Date";
        }else if(columnType.equals("TEXT")||columnType.equals("VARCHAR")||columnType.equals("TINYTEXT")||columnType.equals("LONGTEXT")){
            fieldType="String";
        }else if(columnType.equals("DOUBLE")){
            fieldType="Double";
        }else if(columnType.equals("BIT")){
            fieldType="Boolean";
        }else if(columnType.equals("FLOAT")){
            fieldType="Float";
        }else if(columnType.equals("DECIMAL")){
            fieldType="BigDecimal";
        }else if(columnType.equals("DATE")){
            fieldType="Date";
        }else if(columnType.equals("TIMESTAMP")){
            fieldType="LocalDateTime";
        }else if(columnType.equals("CHAR")){
            fieldType="Char";
        }else if(columnType.equals("JSON")){//mysql5.7版本才开始有的
            fieldType="JSONObject";
        }
        fieldMap.put("fieldType",fieldType);
    }

}

生成的类

用的lombok,就懒得去搞getset了

第二种

搞的是直接main方法运行下就生成,大同小异。不用Junit,方便一些,就是个工具。和第一种结果一样的

package com.shinedata.bims.web;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.*;
import java.util.*;

/**
 * @ClassName TableToEntityUtils
 * @Author yupanpan
 * @Date 2021/6/8 17:25
 */
public class TableToEntityUtils {


    static final String USER = "root";
    static final String PASS = "xxxxxxxxxxx";
//    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    // MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://xxxxxxxxxxxxxxxxxxxxxxx:3306/1ceping?useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&allowMultiQueries=true&rewriteBatchedStatements=true";

    public static void main(String[] args) throws Exception {
        createEntity("1ceping", "t_evaluation_template_info_copy","com.shinedata.bims.entity",false);
    }

    /**
     *
     * @param dataBaseName 数据库名
     * @param tableName 表名
     * @param packageName 包名
     * @param isAddEntitySuffix 类名是否添加Entity后缀 true-添加 false-不添加
     */
    public static void createEntity(String dataBaseName, String tableName, String packageName, boolean isAddEntitySuffix) throws Exception{
        String className=tableName;
        if(tableName.substring(0,2).equals("t_")){
            StringBuilder stringBuilder = new StringBuilder(tableName);
            stringBuilder.replace(0, 2, "");
            String initialsUpperCase = stringBuilder.substring(0, 1).toUpperCase();
            className=initialsUpperCase+stringBuilder.substring(1);
        }
        className=removeUnderline(className)+(isAddEntitySuffix?"Entity":"");

        StringBuffer classBuffer=new StringBuffer();
        classBuffer.append("import java.util.Date;\r\n");
        classBuffer.append("import java.time.LocalDateTime;\r\n");
        classBuffer.append("import com.alibaba.fastjson.JSONObject;\r\n");
        classBuffer.append("import java.lang.*;\r\n");
        classBuffer.append("import java.math.*;\r\n");
        classBuffer.append("import java.sql.*;\r\n");
        classBuffer.append("import lombok.Data;\r\n\r\n\r\n");
        classBuffer.append("@Data\r\n");
        classBuffer.append("public class " + className + " {\r\n\r\n");
        List<Map> filedMaps = getFiledMaps(dataBaseName, tableName);
        processAllAttrs(classBuffer,filedMaps);
        classBuffer.append("}\r\n");
        markerBean(className,classBuffer.toString(),packageName);
    }

    /**
     * 创建实体类文件
     * @param className 类名(不包含.java文件名后缀) 根据表名首字母大写并去掉开头t_和所有下划线-驼峰命名
     * @param content 添加的内容(字段注释等)
     * @param packageName 包名(com.xxx.xxx.xxx)
     */
    public static void markerBean(String className, String content, String packageName) throws Exception {
//      这里不使用System.getProperty("user.dir")了。user.dir是根据运行时环境来的
        File f2 = new File(TableToEntityUtils.class.getResource("/").getPath());
        String homePath=f2.getCanonicalPath().replace("\\target\\classes", "");
        String folder = homePath + "/src/main/java/" + packageName.replace(".","/") + "/";
        File file = new File(folder);
        if (!file.exists()) {
            file.mkdirs();
        }
        String fileName = folder + className + ".java";
        try {
            File newjava = new File(fileName);
            FileWriter fw = new FileWriter(newjava);
            fw.write("package\t" + packageName + ";\r\n");
            fw.write(content);
            fw.flush();
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 去下划线
     * @param string
     * @return
     */
    public static String removeUnderline(String string){
        StringBuilder columnNameBuilder=new StringBuilder(string);
        if(!string.contains("_")){
            return string;
        }else {
            int i = columnNameBuilder.indexOf("_");
            columnNameBuilder.replace(i,i+1, "").replace(i,i+1,columnNameBuilder.substring(i,i+1).toUpperCase());
            return removeUnderline(columnNameBuilder.toString());
        }
    }

    /**
     * 获取表字段信息(列名、类型、注释等)
     * @param dataBaseName
     * @param tableName
     * @return
     */
    private static List<Map> getFiledMaps(String dataBaseName, String tableName) {
        Connection conn = null;
        Statement stmt = null;
        List<Map> tableFieldList=new ArrayList<>();
        try{
            // 注册 JDBC 驱动
            Class.forName(JDBC_DRIVER);
            conn = DriverManager.getConnection(DB_URL,USER,PASS);
            // 执行查询
            stmt = conn.createStatement();
            String sql= "SELECT * FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA ='"+dataBaseName+"' AND TABLE_NAME= '"+tableName+"'";
            ResultSet rs = stmt.executeQuery(sql);
            while (rs.next()) {
                Map<String,String> fieldMap = new HashMap();
                String column_name = rs.getString("COLUMN_NAME");
                setFieldName(column_name.toLowerCase(),fieldMap);
                String data_type = rs.getString("DATA_TYPE");
                setFieldType(data_type.toUpperCase(),fieldMap);
                fieldMap.put("fieldComment",rs.getString("COLUMN_COMMENT"));
                tableFieldList.add(fieldMap);
            }
            rs.close();
            stmt.close();
            conn.close();
        }catch(SQLException se){
            // 处理 JDBC 错误
            se.printStackTrace();
        }catch(Exception e){
            // 处理 Class.forName 错误
            e.printStackTrace();
        }finally{
            // 关闭资源
            try{
                if(stmt!=null){
                    stmt.close();
                }
            }catch(SQLException se2){
            }// 什么都不做
            try{
                if(conn!=null) conn.close();
            }catch(SQLException se){
                se.printStackTrace();
            }
        }
        return tableFieldList;
    }

    /**
     * 解析输出属性
     *
     * @return
     */
    private static void processAllAttrs(StringBuffer sb, List<Map> filedMaps) {
        for (int i = 0; i < filedMaps.size(); i++) {
            Map map = filedMaps.get(i);
            String fieldType = MapUtils.getString(map, "fieldType");
            String fieldName = MapUtils.getString(map, "fieldName");
            String fieldComment = MapUtils.getString(map, "fieldComment");
            if(StringUtils.isNotBlank(fieldComment)){
                sb.append("\t/**\r\n").append("\t* ").append(fieldComment).append("\n").append("\t*/\r\n");
            }
            sb.append("\tprivate " + fieldType + " " + fieldName + ";\r\n\r\n");
        }
    }

    private static void setFieldName(String columnName, Map fieldMap) {
        fieldMap.put("fieldName",removeUnderline(columnName));
    }

    private static void setFieldType(String columnType, Map fieldMap){
        String fieldType="String";
        if(columnType.equals("INT")||columnType.equals("INTEGER")){
            fieldType="Integer";
        }else if(columnType.equals("BIGINT")){
            fieldType="Long";
        }else if(columnType.equals("DATETIME")){
            fieldType="Date";
        }else if(columnType.equals("TEXT")||columnType.equals("VARCHAR")||columnType.equals("TINYTEXT")||columnType.equals("LONGTEXT")){
            fieldType="String";
        }else if(columnType.equals("DOUBLE")){
            fieldType="Double";
        }else if(columnType.equals("BIT")){
            fieldType="Boolean";
        }else if(columnType.equals("FLOAT")){
            fieldType="Float";
        }else if(columnType.equals("DECIMAL")){
            fieldType="BigDecimal";
        }else if(columnType.equals("DATE")){
            fieldType="Date";
        }else if(columnType.equals("TIMESTAMP")){
            fieldType="LocalDateTime";
        }else if(columnType.equals("CHAR")){
            fieldType="Char";
        }else if(columnType.equals("JSON")){//mysql5.7版本才开始有的
            fieldType="JSONObject";
        }
        fieldMap.put("fieldType",fieldType);
    }
}

根据实体类生成创建表语句

package com.fruit.system.utils;

import org.apache.commons.lang3.StringUtils;

import javax.persistence.Table;
import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.URL;
import java.util.*;

/**
 * @ClassName EntityToTableUtils
 * @Author yupanpan
 * @Date 2021/11/16 15:23
 */
public class EntityToTableUtils {

    /**
     * 用来存储Java等属性类型与sql中属性类型的对照
     * </br>
     * 例如:java.lang.Integer 对应 integer
     */
    public static Map<String, String> map = new HashMap<>();

    static {
        map.put("class java.lang.String", "varchar(255)");
        map.put("class java.lang.Integer", "int(11)");
        map.put("class java.lang.Long", "bigint(20)");
        map.put("class java.lang.byte[]", "blob");
        map.put("class java.lang.Boolean", "bit");
        map.put("class java.math.BigInteger", "bigint unsigned");
        map.put("class java.lang.Float", "float(10,1)");
        map.put("class java.lang.Double", "double(10,2)");
        map.put("class java.sql.Date", "datetime");
        map.put("class java.sql.Time", "time");
        map.put("class java.sql.Timestamp", "datetime");
        map.put("class java.util.Date", "datetime");
        map.put("class java.lang.Byte", "tinyint");
        map.put("class java.math.BigDecimal", "decimal(10,2)");
    }

    public static void main(String[] args) throws Exception{
        createTableSql("com.fruit.system.entity");
    }

    public static void createTableSql(String packageName) throws Exception {
        List<String> classNames = getClassName(packageName);
        for (String reference : classNames) {
            Class<?> aClass = Class.forName(reference);
            Table table = aClass.getAnnotation(Table.class);
            if(table!=null){
                StringBuilder sb=new StringBuilder();
                String primaryKey="id";
                String name = table.name();
                if(StringUtils.isNotBlank(name)){
                    sb.append("CREATE TABLE `"+name+"` (");
                    sb.append("\n");
                }
                List<Field> allFields=getAllFields(aClass);
                for (Field field : allFields) {
                    String fieldName = field.getName();
                    String columnName = getStandardFields(fieldName);
                    Class<?> type = field.getType();
                    String typeName = type.toString();
                    String columnType = map.get(typeName);
                    if(StringUtils.isNotBlank(columnType)){
                        StringBuilder columnDDL=new StringBuilder();
                        columnDDL.append("\t").append("`").append(columnName).append("` ").append(columnType);
                        if(primaryKey.equals(columnName)){
                            columnDDL.append(" NOT NULL,");
                        }else {
                            columnDDL.append(" DEFAULT NULL,");
                        }
                        columnDDL.append("\n");
                        //将id主键放在最前面一列
                        if(primaryKey.equals(columnName)){
                            int i = sb.indexOf("(");
                            //i+2,有个换行符
                            sb=new StringBuilder(sb.substring(0,i+2)+columnDDL.toString()+sb.substring(i+2));
                        }else {
                            sb.append(columnDDL);
                        }
                    }
                }
                sb.append("\t");
                sb.append("PRIMARY KEY (`"+primaryKey+"`)");
                sb.append("\n");
                sb.append(") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
                sb.append("\n");
                System.out.println(sb.toString());
            }
        }
    }

    /**
     * 获取所有字段(包括父类的,排除Object)
     * @return
     */
    public static List<Field> getAllFields(Class<?> aClass) {
        List<Field> fields=new ArrayList<>();
        Field[] declaredFields = aClass.getDeclaredFields();
        fields.addAll(Arrays.asList(declaredFields));
        Class<?> superclass = aClass.getSuperclass();
        while(superclass!=null){
//            System.out.println(superclass.getName());
            if("java.lang.Object".equals(superclass.getName())){
                break;
            }
            fields.addAll(Arrays.asList(superclass.getDeclaredFields()));
            superclass=superclass.getSuperclass();
        }
        return fields;
    }

    /**
     * 转换为标准等sql字段 例如 adminUser → admin_user
     *
     * @param str 转换为字符串的字段名
     * @return
     */
    public static String getStandardFields(String str) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (i != 0 && (c >= 'A' && c <= 'Z')) {
                sb.append("_");
            }
            sb.append(c);
        }
        return sb.toString().toLowerCase();
    }

    /**
     * 获得对应包下的类名称(自动遍历子包)
     * <功能详细描述>
     * @param packageName
     * @return
     */
    public static List<String> getClassName(String packageName)
    {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        String packagePath = packageName.replace(".", "/");
        //加载包下的所有资源
        URL url = loader.getResource(packagePath);
        List<String> fileNames = null;
        if (url != null)
        {
            String type = url.getProtocol();
            if (type.equals("file"))
            {
                fileNames = getClassName(url.getPath(), null);
            }
        }

        return fileNames;
    }

    /**
     * 根据资源路径返回 class 路径
     * <功能详细描述>
     * @param filePath
     * @param className
     * @return
     */
    private static List<String> getClassName(String filePath, List<String> className)
    {
        List<String> myClassName = new ArrayList<String>();
        File file = new File(filePath);
        File[] childFiles = file.listFiles();
        for (File childFile : childFiles)
        {
            if (childFile.isDirectory())
            {
                myClassName.addAll(getClassName(childFile.getPath(), myClassName));
            }
            else
            {
                String childFilePath = childFile.getPath();
                childFilePath =
                        childFilePath.substring(childFilePath.indexOf("\\classes") + 9, childFilePath.lastIndexOf("."));
                childFilePath = childFilePath.replace("\\", ".");
                myClassName.add(childFilePath);
            }
        }

        return myClassName;
    }
}

实体类用了@Table(name="t_member")注解定义表名

结果:

CREATE TABLE `t_member` (
	`id` bigint(20) NOT NULL,
	`bind_member_id` bigint(20) DEFAULT NULL,
	`user_name` varchar(255) DEFAULT NULL,
	`tel` varchar(255) DEFAULT NULL,
	`employee_id` bigint(20) DEFAULT NULL,
	`open_id` varchar(255) DEFAULT NULL,
	`type` int(11) DEFAULT NULL,
	`create_time` datetime DEFAULT NULL,
	`update_time` datetime DEFAULT NULL,
	`delete_status` int(11) DEFAULT NULL,
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `t_member_coupon` (
	`id` bigint(20) NOT NULL,
	`member_id` bigint(20) DEFAULT NULL,
	`type` int(11) DEFAULT NULL,
	`source_id` bigint(20) DEFAULT NULL,
	`use_channel` int(11) DEFAULT NULL,
	`use_product_id` bigint(20) DEFAULT NULL,
	`amount` decimal(10,2) DEFAULT NULL,
	`satisfy_amount` decimal(10,2) DEFAULT NULL,
	`expire_time` datetime DEFAULT NULL,
	`create_time` datetime DEFAULT NULL,
	`update_time` datetime DEFAULT NULL,
	`delete_status` int(11) DEFAULT NULL,
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `t_member_coupon_setting` (
	`id` bigint(20) NOT NULL,
	`type` int(11) DEFAULT NULL,
	`amount` decimal(10,2) DEFAULT NULL,
	`satisfy_amount` decimal(10,2) DEFAULT NULL,
	`expire_type` int(11) DEFAULT NULL,
	`expire_value` int(11) DEFAULT NULL,
	`create_time` datetime DEFAULT NULL,
	`update_time` datetime DEFAULT NULL,
	`delete_status` int(11) DEFAULT NULL,
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值