Java逆向工程(數據庫表生成java類)


說起來倒是挺簡單的,就是聽着名字感覺挺高大上。逆向工程方式有很多,比如mybatis就提供了一個這樣的工具mybatis-genderator,這個我反正是沒用過只是聽說過,以前在公司都是用公司寫好的的工具,最近也是閑的無聊自己動手寫了一個。

我的這個工程師基於spring和mybatis寫的,有興趣的加上spring-mvc,加個頁面也是不錯的。

其實呢使用mybatis做逆向工程很簡單就是兩個select查詢就好了,數據庫底子好的童鞋們應該記得一下這兩個查詢語句的(不記得也沒關系,可以學嘛):

  1. 查詢庫中的所有表: select * from information_schema.TABLES where TABLE_SCHEMA=(select database())

  2.查詢表中的所有字段信息: select * from information_schema.COLUMNS where TABLE_SCHEMA = (select database()) and TABLE_NAME=#{tableName}

對於第一條sql來說查詢那個庫就連接哪個就行了,不需要傳參數。但是第二條sql需要將表名傳進去的(這也是無可厚非的)

必不可少的我們是需要數據庫的4大連接參數,凡是和數據庫掛鈎應該都需要這幾個玩意(這聲明一下我這里是用的MySQL)。其他的配置文件上的事情我就不多說了。今天重點不在這里

接下來簡單的將dao、service層貼出來了,和平時的web結構一樣很簡單。

service層

service實現類

接下來就是今天的重點了。其實也很簡單,可能很多人都已經想到了,我們都已經獲取到了表字段信息了,那么我們只需要一個文件流不就可以了?(嗯,沒錯,大兄弟,反正我就是這么寫的)

其實我的這個很簡單,主要圍繞一個stringbuffer進行,先拼接到字符串中,然后用流寫到文件中。下邊我粘一下我的代碼吧。

package com.ml.code.one.codegenerator.util;

import com.ml.code.one.codegenerator.myservice.MyCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Component
public class CodeGenerator {
    @Autowired
    private  MyCodeService service;

    public void codeGenerator(String tableName,String path){
        List<Map> columns = service.listColumn(tableName);//查詢所有的表字段信息
        String className = getClassName(tableName);
        StringBuffer sb = new StringBuffer();
        sb.append("package "+getPackageName(path)+";\n");
        sb.append("import java.io.Serializable;"+"\n");
        sb.append("import java.util.*;\n");
        sb.append("import java.lang.*;\n");
        sb.append("import lombok.Data;\n");
        sb.append("import lombok.ToString;\n\n");
        sb.append("@Data\n@ToString\n");
        sb.append("public class "+className+" implements Serializable {\n");
        sb.append("\tprivate static final long serialVersionUID = 1L;\n\n");
        //獲取字段信息
        Iterator<Map> iterator = columns.iterator();
        while (iterator.hasNext()){
            Map next = iterator.next();
            Object dataType = next.get("DATA_TYPE");//獲取數據類型
            String type = classCast(dataType);//數據類型
            Object property = next.get("COLUMN_NAME");//獲取字段名稱
            String propertity = getPropertity(property);//屬性名稱
            Object annotation = next.get("COLUMN_COMMENT");//注解
            sb.append("\tprivate "+type+" "+propertity+";"+"//"+(String)annotation+"\n");
        }
        sb.append("}");
        //拼接結束

        //生成文件
        try {
            //生成java文件
            getFile(className,sb.toString(),path);
            //生成mapper.xml
//            getMapperFile(className,path);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成類名
     * @param tableName 表名
     * @return
     */
    private String getClassName(String tableName){
        String newClassName="";
        int i = tableName.indexOf("_");
        if (i<0){//沒有下划線
            newClassName = tableName.substring(0, 1).toUpperCase() + tableName.substring(1)+"Po";
        }else{//有下划線
            String[] strs = tableName.split("_");
            StringBuffer sb = new StringBuffer();
            for (int m = 0; m<strs.length; m++){
                sb.append(strs[m].substring(0, 1).toUpperCase() + strs[m].substring(1));
            }
            newClassName=sb.toString()+"Po";
        }
        return newClassName;
    }
    //生成屬性java類型
    private String classCast(Object obj){
        String type="";
        String str=(String)obj;
        if (str.equals("varchar")||str.equals("char")||str.equals("text")){
            type="String";
        }else if (str.equals("int")){
            type="Integer";
        }else if (str.equals("bigint")){
            type="Long";
        }else if (str.equals("double")||str.equals("float")){
            type="Double";
        }else if (str.equals("date")||str.equals("datetime")||str.equals("timestamp")){
            type="Date";
        }else {
            type="String";
        }
        return type;
    }
    //數據庫字段名字轉java屬性名字
    private  String getPropertity(Object obj){
        String pro="";
        String colum=(String)obj;
        int index = colum.indexOf("_");//判斷是否存在下划線
        if (index<0){//沒有下划線
            pro=colum.substring(0,1).toLowerCase()+colum.substring(1);//首字母小寫
        }else {//有下划線
            StringBuilder sb = new StringBuilder();
            String[] colums = colum.split("_");
            for (int i = 0; i<colums.length; i++){
                if (i==0){
                    sb.append(colums[i].substring(0,1).toLowerCase()+colums[i].substring(1));//拼接第一個,並將首字母小寫
                }else{
                    sb.append(colums[i].substring(0,1).toUpperCase()+colums[i].substring(1));//除了第一個都將首字母大寫
                }
            }
            pro=sb.toString();
        }

        return pro;
    }

    /**
     * 生成包名
     */
    private  String getPackageName(String path){
        int index = path.indexOf("java\\");
        String newPackage="";
        if (index>0){
            String substring = path.substring(index+5);
            newPackage = substring.replace("\\", ".");
        }
        return newPackage;
    }

    /**
     * 生成文件
     * @param fileName 文件名
     * @param info 要寫入的內容
     * @throws IOException
     */
    private  void getFile(String fileName,String info,String path) throws IOException {
        //生成文件
        File file = new File(path+"\\"+fileName+".java");
        if (!file.exists()){
            file.createNewFile();
        }
        FileWriter writer = new FileWriter(file);
        writer.write(info);
        writer.flush();
        writer.close();
    }

    /**
     * 生成Mapper.xml
     * @param poName
     */
    private void getMapperFile(String poName,String path) throws IOException {
        //獲取文件名
        StringBuilder fileName = new StringBuilder();
        int index = poName.indexOf("Po");
        if (index<0){//沒有Po后綴時
            fileName.append(poName+"Mapper");
        }else{//存在Po后綴
            String sub = poName.substring(0, index);//截取到需要的部分
            fileName.append(sub+"Mapper");
        }
        //獲取路徑
        StringBuilder newPath = new StringBuilder();
        int main = path.indexOf("main\\");
        if (main>0){
            String substring = path.substring(0, main+5);
            newPath.append(substring).append("\\resources\\mapper\\");
        }

        File file = new File(newPath+fileName.toString()+".xml");
        StringBuilder xmlInfo = new StringBuilder();
        xmlInfo.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        xmlInfo.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\"  \n" +
                "     \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n");
        xmlInfo.append("<mapper namespace=\"\">\n");
        xmlInfo.append("\n\n");
        xmlInfo.append("</mapper>");
        FileWriter fw = new FileWriter(file);
        fw.write(xmlInfo.toString());
        fw.flush();
        fw.close();
    }
}

這里我用的是boot工程寫的,運行的時候我選擇用boot自帶的test工具運行就ok了(別忘了在啟動類上加上dao層的包掃描呦)

到這里呢這個簡單的逆向工程就結束了,這個可以直接生成到你指定文件下,順帶連Mapper.xml也生成了的。大佬勿噴。

有需要源碼的可以到以下網盤獲取,(網盤中的也只是一部分,只是逆向工程部分,其他的需要你們自行補充,應該是不難的) 

 

補充一下,如果有用idea的我建議用idea的代碼生成工具哈  下載一個插件就可以了  EasyCode,至於使用方法很簡單,把你的idea連上數據庫就好了,而且還可以手動配置呢

鏈接:https://pan.baidu.com/s/1KW7h9vro2U199hsL85Q38w
提取碼:obpf

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM