1. 程式人生 > >快速生成JavaBean: .sql轉JavaBean一步到位

快速生成JavaBean: .sql轉JavaBean一步到位

簡介

  • 我一般資料表結構是用PowerDesigner來建, 建完就需要建Model也即一堆javaBean, 如果沒有輔助工具挨個建要累死, 於是用python寫了這樣一個輔助小工具, 僅需複製下PowerDesigner中Preview中的sql語句, 然後雙擊下工具就直接生成出所有資料表的javaBean了

  • 效果如下
    sql2bean_pdm.gif

分析

  • 原理很簡單, 解析SQL語句用了正則表示式, 將關鍵資訊封裝起來, 解析完返回後即可以進行拼湊成JavaBean了

  • SQL的解析如下, 其中get_tables即解析函式, 解析完最終返回一個Table物件的列表, 每張表對應一個Table物件, Table物件中有個Field列表, Field其實就是表裡面的列

class Field:
    def __init__(self, name='', type='', comment=''):
        self.name = name
        self.type = type
        self.comment = comment
        self.is_not_null = False
        self.is_key = False
        self.is_auto_increase = False

    def __repr__(self):
        return "Field(name=%s, type=%s, comment=%s)"
% (self.name, self.type, self.comment) class Table: def __init__(self): self.name = '' self.comment = '' self.fields = [] def __repr__(self): return "Table(name=%s, comment=%s, field=%s)" % (self.name, self.comment, repr(self.fields)) def get_tables(sql_text)
:
""" sql文字轉Table物件列表 :param sql_text: sql文字 :return: list of Table """ tables = [] ret = re.findall(r'(create\stable\s(.+)[^(]+\(([^;]+)\);)', sql_text) for per_table_ret in ret: table_name = per_table_ret[1].replace('\r', '').replace('\n', '') table_body = per_table_ret[2] table_body_lines = list(map(lambda x: x.strip(), table_body.strip().splitlines())) new_table = Table() # 遍歷( ... )裡面的每一行 key_names = [] for line in table_body_lines: if 'primary key' in line: key_names.append(line[line.find('(') + 1:line.find(')')]) if 'key ' not in line: ret_line = re.search(r'([\w_]+)\s+([^\s,]+)\s?(.*)', line) field_name = ret_line.group(1) field_type = ret_line.group(2) field_tail = ret_line.group(3) field_comment = '--' if 'comment ' in field_tail: field_comment = re.search(r'[\w\s]+\'(.+)\'', line).group(1) new_field = Field(field_name, field_type, field_comment) if 'not null' in line: new_field.is_not_null = True if 'auto_increment' in line: new_field.is_auto_increase = True new_table.fields.append(new_field) # 處理primary key for per_field in new_table.fields: if per_field.name in key_names: per_field.is_key = True table_comment = 'null' ret_comment = re.search( r'alter\stable\s%s.+\'(.+)\'' % table_name.strip(), sql_text) if ret_comment is not None: table_comment = ret_comment.group(1) new_table.comment = table_comment new_table.name = table_name tables.append(new_table) return tables
  • 解析完得到Table的列表後, 剩下的就非常簡單了, toString也好getter setter也好最終也僅僅是字串的拼拼湊湊而已; 比較麻煩也就toString, 參照IDEA的toString格式的話, String型別在toString裡面兩邊還掛著對單引號, 加上各種縮排轉義啥的折騰起來有點亂. 程式碼如下
TO_STRING_TEMPLATE = """
    @Override
    public String toString() {{
        return {}
    }}

"""

def gen_tostring(class_name, typefield_list):
    """
    生成並返回tostring
    :param class_name
    :param typefield_list: 欄位型別+名的元組列表 eg:[(int,id), (String,name), (Date,createTime)]
    :return: str
    """
    tostring = '\"' + class_name + '{\" +\n'
    tostring += '\t\t\"' + \
                typefield_list[0][1] + '=\" + ' + typefield_list[0][1] + ' +\n'
    typefield_list_ext_first = typefield_list[1:]
    for type_field in typefield_list_ext_first:
        single_quote_left = r"'" if type_field[0] == 'String' else ""
        single_quote_right = r" + '\''" if type_field[0] == 'String' else ""
        tostring += '\t\t\", ' + type_field[1] + '=' + single_quote_left + '\" + ' + type_field[
            1] + single_quote_right + ' + \n'
    tostring += "\t\t\'}\';"
    return TO_STRING_TEMPLATE.format(tostring)
  • 最終生成的toString效果如下:
    @Override
    public String toString() {
        return "Job{" +
        "id=" + id +
        ", name='" + name + '\'' + 
        ", description='" + description + '\'' + 
        ", cronExpression='" + cronExpression + '\'' + 
        ", startTime='" + startTime + '\'' + 
        ", endTime='" + endTime + '\'' + 
        ", exeCount=" + exeCount + 
        ", maxExeCount=" + maxExeCount + 
        ", status='" + status + '\'' + 
        ", className='" + className + '\'' + 
        ", methodName='" + methodName + '\'' + 
        ", delayTime=" + delayTime + 
        ", intervalTime=" + intervalTime + 
        '}';
    }
  • 至於複製完直接雙擊就可以生成JavaBean, 這個則直接去拿剪貼簿的資料然後判斷是否是屬於sql語句, 如果是則直接生成JavaBean

Ps

  • Sql2Bean本來給自己用的, 所以夾了點私貨, 如多了@DescAnnotation註解等, 只要把Sql2Bean裡面額IS_SIMBA變數置為False即可生成不帶私貨的JavaBean :)