なんじゃくにっき

プログラミングの話題中心。

エンティティを動的に生成してみる

バイトコード変換ライブラリJavassistを使って、ResultSetのMetadataからエンティティを動的に生成してみるテスト。


import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;

import javassist.*;

public class Main {
public static void main(String[] args) throws Exception{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:test",
"test",
"test");

String filename = "Hoge";
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass(filename);

Statement statement = con.createStatement();
String sql = "SELECT * from EMP";
ResultSet rs = statement.executeQuery(sql);

ResultSetMetaData rsMetaData= rs.getMetaData();
int columnCount = rsMetaData.getColumnCount();
String fieldtype;
String fieldname;
for(int i=0; i<columnCount; i++){
fieldname = rsMetaData.getColumnName(i+1).toLowerCase();
switch (rsMetaData.getColumnType(i+1)) {
case java.sql.Types.CHAR:
case java.sql.Types.VARCHAR:
fieldtype = "java.lang.String";
break;
case java.sql.Types.DATE:
fieldtype = "java.sql.Date";
break;
case java.sql.Types.NUMERIC:
fieldtype = "java.math.BigDecimal";
break;
default:
throw new RuntimeException("????");
}

CtClass ftypeclass = pool.get(fieldtype);
CtField field = new CtField(ftypeclass, fieldname, cc);
field.setModifiers(Modifier.PUBLIC);

try {
cc.getDeclaredField(fieldname);
} catch (NotFoundException e) {
cc.addField(field);
}
}

Class c = cc.toClass();
Object o = c.newInstance();

Field[] fields = o.getClass().getFields();
for(Field f: fields){
System.out.println(f.toString());
}

rs.close();
statement.close();
con.close();
}
}

JavaでもRubyのActive Recordみたいなものを作るっていうのは既に何年も前に
こことかで言及されている。
でも実際今流行っていないってことは何かしら問題があるのかな?
Javaの静的言語としてのメリットが失われる部分が多いからだろうか、と勝手に想像。