MyBatis の定義がクソ面倒なので、生成を狙う
A5:SQL Mk-2 - フリーの汎用SQL開発ツール/ER図ツール .. 松原正和 使って作ったテーブルのマッピングを書くのがだるくなったので、自動生成を狙った。
まずはこんな感じの ER を書いて、CSV でエクスポートする。
一応設定は UTF-8 で吐く。
そうすると、a5m2_COLUMNS.csv
なるファイルが出来上がる。
TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME,LOGICAL_NAME,ORDINAL_POSITION,COLUMN_DEFAULT,IS_NULLABLE,DATA_TYPE,KEY_POSITION,DESCRIPTION Example,,example_entity,id,ID,1,,NO,BIGINT IDENTITY,1, Example,,example_entity,name,名前,2,,NO,NVARCHAR(64),, Example,,example_entity,price,価格,3,,NO,@INT,, Example,,example_entity,example_field,その他適当,4,,NO,"@DECIMAL(10, 3)",,"これが 複数行" Example,,seller,id,ID,1,,NO,BIGINT IDENTITY,1, Example,,seller,example_entry_id,商品ID,2,,NO,BIGINT,, Example,,seller,name,店名,3,,NO,NVARCHAR(64),, Example,,seller,created_at,作成ビ,4,CURRENT_TIMESTAMP,NO,@DATETIME,, Example,,seller,updated_at,更新日,5,,YES,@DATETIME,,
あとはこれを自動生成できりゃいい。
ちなみに SQL Server 用に設定したけど、他のものを使いたければちょっと改変すればいい。
Python3 で読み込んで、マッピング java bean (Lombok) と mapping 用 XML を吐き出した。
import csv def to_camel_name(name): components = name.split('_') return components[0] + "".join(x.title() for x in components[1:]) def to_upper_camel_name(name): components = name.split('_') return "".join(x.title() for x in components[:]) def starts_with(string_value, arr): for v in arr: if string_value.startswith(v): return True return False class Field: def __init__(self, name, id, dataType, description): self.name = name self.id = id self.dataType = dataType self.description = description def db_type(self): stn = self.dataType.lower() convert = { 'INTEGER' : ['@int', 'int'], 'BIGINT' : ['bigint', '@bigint'], 'DECIMAL' : ['@decimal', 'decimal'], 'VARCHAR' : ['@char', 'char', 'varchar'], 'NVARCHAR' : ['nchar', 'nvarchar'], 'BOOLEAN' : ['bit'], 'TIMESTAMP': ['date', 'datetime', 'timestamp', '@datetime'] } for key in convert.keys(): if starts_with(stn, convert[key]): return key return None def type_name(self): stn = self.dataType.lower() convert = { 'Integer' : ['@int', 'int'], 'Long' : ['bigint', '@bigint'], 'BigDecimal': ['@decimal', 'decimal'], 'String' : ['@char', 'char', 'varchar', 'nchar', 'nvarchar'], 'Boolean' : ['bit'], 'Date' : ['date', 'datetime', 'timestamp', '@datetime'] } for key in convert.keys(): if starts_with(stn, convert[key]): return key return 'Object' def get_field_definition(self): changed_type = self.type_name() field_name = to_camel_name(self.id) str = '' str = str + f' /**\n' str = str + f' * {self.name}.\n' str = str + f' *\n' str = str + f' * {self.description}.\n' str = str + f' */\n' str = str + f' private {changed_type} {field_name};\n\n' return str class_field = {} # クラス辞書 try: with open('a5m2_COLUMNS.csv', 'r') as csvfile: spamreader = csv.reader(csvfile, delimiter=',', quotechar='"') for row in spamreader: if len(row) == 0: continue class_name = to_upper_camel_name(row[2]) field = Field(row[4], row[3], row[8], row[10]) if class_name in class_field: class_field[class_name].append(field) else: class_field[class_name] = [field] # 起こりそうな例外をキャッチ except FileNotFoundError as e: print(e) except csv.Error as e: print(e) for class_name in class_field.keys(): file = open(f'{class_name}.java', 'w', encoding='UTF-8') file.write('\nimport lombok.*;') file.write('\nimport java.util.Date;\n') file.write('\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n') file.write('public class ' + class_name + ' {\n') for field in class_field[class_name]: file.write(field.get_field_definition()) file.write('}\n') file.close() file = open(f'{class_name}.mapping.xml', 'w', encoding='UTF-8') file.write(f'<resultMap id="{class_name}Map" type="{class_name}">\n') for field in class_field[class_name]: cur_db_type = field.db_type() db_str = ('jdbcType="' + cur_db_type + '"') if cur_db_type != None else '' file.write(f' <result property="{to_camel_name(field.id)}" column="{field.id}" {db_str} />\n') file.write('</resultMap>\n') file.close()
このスクリプトは好きに使って。
CSV の1行目呼んで変なの出るけどご愛嬌で!