在开发中,一般是表结构设计好了之后,然后生成实体类,所以如果手写,你会哭,因为这些代码基本是类是的,而且手写还容易出错,所以一般通过自动生成的工具来生成,这个是控制台打印出来的效果,具体是咋生成类文件啥的,我就没有做了,主要是这玩意具体是生成到哪个包啊,类叫啥名称啊,不同的项目业务也不一样,所以没有必要接着写了,接着的看你自己的了。

生成效果

Oracle之Entity生成工具-yellowcong_List

实现原理代码

这个里面,通过java的工具类,将oracle的表字段信息都获取了,然后打印出来,这个里面需要注意其中的原理,就是查询oracle表USER_COL_COMMENTSUSER_TAB_COLUMNS ,通过他们来获取表字段信息。

修改版本:2017/11/15 对于Number判断进行了修改

package com.yellowcong.utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CreateEntity {

    private static final String DB_URL = "jdbc:oracle:thin:@10.0.7.170:1522:ORCL5";

    private static final String DB_USER = "SOFINAM_HENSEI";
    //venas2017   SOFINAM_HENSEI
    private static final String DB_PASSWORD = "SOFINAM_HENSEI";

    private static Connection conn = null;

    //设定set方法的模版
    private static final StringBuffer GET_METHOD_TEMPLATE = new StringBuffer();

    //设定get方法的模版
    private static final StringBuffer SET_METHOD_TEMPLATE = new StringBuffer();

    //类的名称
    private static final StringBuffer CLASS_TEMPLATE = new StringBuffer();

    //测试类
    public static void main(String[] args) throws Exception {
        String tableName = "TEST_DEMO";

        String result = createClass(tableName);
        System.out.println(result);
    }

    static {
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");

            conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);

            //创建Get方法的模版
            GET_METHOD_TEMPLATE.append("@Column(\"%s\")\r\n");
            GET_METHOD_TEMPLATE.append("public %s get%s() {\r\n");
            GET_METHOD_TEMPLATE.append("\treturn %s;\r\n");
            GET_METHOD_TEMPLATE.append("}");

            //设定set方法的模版
            SET_METHOD_TEMPLATE.append("public void set%s(%s %s) {\r\n");
            SET_METHOD_TEMPLATE.append("\tthis.%s=%s;\r\n");
            SET_METHOD_TEMPLATE.append("}");

            //方法体的生成
            CLASS_TEMPLATE.append("@Bean(table=\"%s\")\r\n");
            CLASS_TEMPLATE.append("public class %s implements Serializable{\r\n");
            CLASS_TEMPLATE.append("private static final long serialVersionUID = 1L;\r\n");
            CLASS_TEMPLATE.append("%s");
            CLASS_TEMPLATE.append("\r\n}");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String createClass(String tableName) throws Exception{

        StringBuffer sbBody = new StringBuffer();
        List<String> classBody =  CreateEntity.createClassBody(tableName);
        for(String classInfo :classBody){
            sbBody.append(classInfo);
            sbBody.append("\r\n");
        }

        return String.format(CLASS_TEMPLATE.toString(), tableName,underline2Camel(tableName,false),sbBody.toString());
    }
    /**
     * 生成class的内容
     * @param tableName
     * @return
     * @throws Exception
     */
    public static List<String> createClassBody(String tableName) throws Exception{
        List<EntityInfo> infos = getEntityInfo(tableName);
        //类的方法体
        List<String> classBody = new ArrayList<String>();

        for(EntityInfo info:infos){
            String comments = info.getComment();
            String dataType = info.getType();

            String filed = underline2Camel(info.getField());

            //当是String类型的
            String fieldResult = String.format("/** %s*/\r\nprivate %s %s;\r\n",comments,dataType,filed);
            classBody.add(fieldResult);
        }

        //setter和getter方法
        for(EntityInfo info:infos){
            //生成get方法
            String strGetMethod = createGetterMethod(info);
            classBody.add(strGetMethod);

            //生成set方法
            String strSetMethod = createSetterMethod(info);
            classBody.add(strSetMethod);
        }
        return classBody;
    }

    /**
     * 生成get方法
     * @param info
     * @return
     */
    private static String createGetterMethod(EntityInfo info){
        String strGetMethod = String.format(
                GET_METHOD_TEMPLATE.toString(),
                info.getField(),//注解数据
                info.getType(),//返回的数据类型格式
                underline2Camel(info.getField(),false), //getUserName
                underline2Camel(info.getField()));//userName
        return strGetMethod;
    }

    /**
     * 生成set的方法
     * @param info
     * @return
     */
    private static String createSetterMethod(EntityInfo info){

        String strSetMethod = String.format(
                SET_METHOD_TEMPLATE.toString(), //模版
                underline2Camel(info.getField(),false), //大驼峰 setUserName
                info.getType(),//数据类型
                underline2Camel(info.getField()), //小驼峰 userName
                underline2Camel(info.getField()), //小驼峰 userName
                underline2Camel(info.getField()) //小驼峰 userName
                );
        return strSetMethod.toString();
    }

    /**
     * 根据传入的数据类型来字符的类型
     * 如果你是其他的数据库,可以根据自己的需求来更改这一块
     * @param dataType oracle字段的类型
     * @param len 字符的长度
     * @return
     */
    private static String getFieldType(String dataType,int len){
        String fieldType = "";
        //当是String类型的
        switch(dataType){
        case "CHAR" :
            fieldType =  "String";
            break;
        case  "VARCHAR2":
            fieldType = "String";
            break;
        case "BLOB":
            fieldType = "BLOB";
            break;
        case "DATE":
            fieldType = "Date";
            break;
        case "NUMBER":
            if(len == 0){
                fieldType = "Long";
            }else{
                fieldType = len <12?"Integer":"Long";
            }
            break;
        case "FLOAT":
            fieldType = len <12?"Float":"Double";
            break;
        }
        return fieldType;
    }

    /**
     * 获取连接
     * @return
     */
    public static Connection getConnection() {

        try {
            if (conn == null) {
                Class.forName("oracle.jdbc.driver.OracleDriver");

                conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
            }
            return conn;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 获取实体类的字段信息
     * @param tableName
     * @return
     * @throws Exception
     */
    public static List<EntityInfo> getEntityInfo(String tableName) throws Exception {
        Connection con = CreateEntity.getConnection();
        //查询USER_COL_COMMENTS 和USER_TAB_COLUMNS 两个表,查询出字段信息
        String sql = "SELECT COL.COLUMN_NAME, COL.COMMENTS, " +
                " case TAB.DATA_TYPE when 'NUMBER' then decode(sign(NVL(TAB.DATA_SCALE,0)),0,'NUMBER','FLOAT') else TAB.DATA_TYPE end as DATA_TYPE," +
                " DECODE(TAB.DATA_TYPE, 'NUMBER', TAB.DATA_PRECISION + TAB.DATA_SCALE , TAB.DATA_LENGTH) AS DATA_LENGTH "
                + "FROM USER_COL_COMMENTS COL, USER_TAB_COLUMNS TAB WHERE COL.TABLE_NAME = ? "
                + "AND TAB.TABLE_NAME = COL.TABLE_NAME AND TAB.COLUMN_NAME = COL.COLUMN_NAME ";
        PreparedStatement ps = con.prepareStatement(sql);

        System.out.println(sql);
        ps.setString(1, tableName);

        ResultSet rs = ps.executeQuery();

        //将查询的信息都放到集合里面,然后回
        List<EntityInfo> infos = new ArrayList<EntityInfo>();
        while (rs.next()) {
            //字段名次
            String colNm = rs.getString(1);
            //备注
            String comments = rs.getString(2);
            //oracle 数据类型
            String dataType = rs.getString(3);
            //oralce 数据长度
            Integer len = rs.getInt(4);
            //获取对应的java苏汇聚类型
            String fieldType = getFieldType(dataType,len);

            infos.add(new CreateEntity.EntityInfo(colNm,comments,fieldType,len));
        }

        ps.close();
        con.close();

        return infos;
    }

    /**
     * 下划线转驼峰法(默认小驼峰)
     *
     * @param line
     *            源字符串
     * @param smallCamel
     *            大小驼峰,是否为小驼峰(驼峰,第一个字符是大写还是小写)
     * @return 转换后的字符串
     */
    public static String underline2Camel(String line, boolean ... smallCamel) {
        if (line == null || "".equals(line)) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        Pattern pattern = Pattern.compile("([A-Za-z\\d]+)(_)?");
        Matcher matcher = pattern.matcher(line);
        //匹配正则表达式
        while (matcher.find()) {
            String word = matcher.group();
            //当是true 或则是空的情况
            if((smallCamel.length ==0 || smallCamel[0] ) && matcher.start()==0){
                sb.append(Character.toLowerCase(word.charAt(0)));
            }else{
                sb.append(Character.toUpperCase(word.charAt(0)));
            }

            int index = word.lastIndexOf('_');
            if (index > 0) {
                sb.append(word.substring(1, index).toLowerCase());
            } else {
                sb.append(word.substring(1).toLowerCase());
            }
        }
        return sb.toString();
    }

    /**
     * 驼峰法转下划线
     *
     * @param line
     *            源字符串
     * @return 转换后的字符串
     */
    public static String camel2Underline(String line) {
        if (line == null || "".equals(line)) {
            return "";
        }
        line = String.valueOf(line.charAt(0)).toUpperCase()
                .concat(line.substring(1));
        StringBuffer sb = new StringBuffer();
        Pattern pattern = Pattern.compile("[A-Z]([a-z\\d]+)?");
        Matcher matcher = pattern.matcher(line);
        while (matcher.find()) {
            String word = matcher.group();
            sb.append(word.toUpperCase());
            sb.append(matcher.end() == line.length() ? "" : "_");
        }
        return sb.toString();
    }

    /**
     * 用于存储实体类字段信息
     * @author zhangrw
     *
     */
    static class EntityInfo {
        private String field;
        private String comment;
        private String type;
        private Integer length;

        /**
         *
         */
        public EntityInfo() {
            super();
        }

        /**
         * @param field
         * @param comment
         * @param type
         * @param length
         */
        public EntityInfo(String field, String comment, String type,
                Integer length) {
            super();
            this.field = field;
            this.comment = comment;
            this.type = type;
            this.length = length;
        }


        public String getField() {
            return field;
        }

        public void setField(String field) {
            this.field = field;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public Integer getLength() {
            return length;
        }

        public void setLength(Integer length) {
            this.length = length;
        }

        public String getComment() {
            return comment;
        }

        public void setComment(String comment) {
            this.comment = comment;
        }
    }
}

生成效果

这个是控制台打印出来的效果,具体是咋生成类文件啥的,我就没有做了,主要是这玩意具体是生成到哪个包啊,类叫啥名称啊,不同的项目业务也不一样,所以没有必要接着写了,接着的看你自己的了。

Oracle之Entity生成工具-yellowcong_List

类的头信息

Oracle之Entity生成工具-yellowcong_sql_03

注意细节

number类型的数据在oracle中的长度是 22,但是我们并不需要这个长度,而是后面的DATA_PRECISIONDATA_SCALE两个字段了,所以要么在SQL上下文章,要么在java处理做文章,这种情况,我们希望在oracle上做文章,这样效率跟高一点

Oracle之Entity生成工具-yellowcong_java_04

优化SQL语句

SELECT COL.COLUMN_NAME,
       COL.COMMENTS,
       case TAB.DATA_TYPE when 'NUMBER' then
             --当是number的情况,判断 DATA_SCALE 是否为0 如果是0 就是number类型
             --如果非0 就是FLOAT类型,这个地方,我就这么简单做判断了
             decode(sign(TAB.DATA_SCALE),0,'NUMBER','FLOAT')
       else
           TAB.DATA_TYPE
       end as DATA_TYPE,
       DECODE(TAB.DATA_TYPE,
              'NUMBER',
              TAB.DATA_PRECISION + TAB.DATA_SCALE ,
              TAB.DATA_LENGTH) AS DATA_LENGTH
  FROM USER_COL_COMMENTS COL, USER_TAB_COLUMNS TAB
 WHERE COL.TABLE_NAME = 'K_TRN_OUTLINE'
   AND TAB.TABLE_NAME = COL.TABLE_NAME
   AND TAB.COLUMN_NAME = COL.COLUMN_NAME

对于number类型进行特殊的处理,这样字段的长度就正确了,同时将数据类型为number的,如果是浮点,就反回float

Oracle之Entity生成工具-yellowcong_oracle_05