@JFinal 你好,想跟你请教个问题:
现在有个小项目 ,用的是Jfinal + SQLite3,发现一个问题。SQLITE3的表中字段映射到Java类型全是String类型,我跟踪到TableBuilder.java中的private static void doBuild(Table table, Connection conn, Config config)方法,有如下片断
String sql = config.dialect.forTableBuilderDoBuild(table.getName()); Statement stm = conn.createStatement(); ResultSet rs = stm.executeQuery(sql); ResultSetMetaData rsmd = rs.getMetaData(); for (int i=1; i<=rsmd.getColumnCount(); i++) { String colName = rsmd.getColumnName(i); String colClassName = rsmd.getColumnClassName(i); if ("java.lang.String".equals(colClassName)) { // varchar, char, enum, set, text, tinytext, mediumtext, longtext table.setColumnType(colName, java.lang.String.class); } else if..... }
其中无论SQLITE表中设置INTEGER 类型的,rsmd.getColumnClassName()返回的统统是java.lang.String。
我表单中的主键是自增的INTEGER,现在JFinal得到的表结构是Object,最后我看代码是都转成了String类型。这该怎么解决?是驱动的问题吗?用的是org.sqlite.JDBC就是sqlite-jdbc-3.7.2.jar。
奇怪通过getModel(XXX.class)获得的对象填充进去的就是String类型,是因为columnTypeMap里放的根据doBuild方法获得的Object,因为没有相符的就按String处理了。
而通过findById(1)这样的形式得到的对象中字段的类型就是正确。奇怪。最根源的问题就是用的sqlite3的JDBC驱动中getColumnClassName()这个行为太诡异了。
目前解决的办法是这样
引用来自“JFinal”的评论
换一下驱动程序试试, http://www.jfinal.com 下载 jfinal-1.8-lib.zip,里面有 sqlite 驱动可以试试@JFinal
那个包里的驱动就是sqlite-jdbc-3.7.2.jar,我用的就是那个。希望以后能加入一个功能,在Model中使用注解或其他方式显式地指明某些字段对应的Java类型。
总结一下,Table类中的doBuild方法,使用select * from 表名 where 1=2;
得到ResultSet和ResultSetMetaData,通过这个获得表中字段的类型, 但这个完全依赖于具体JDBC驱动的实现。这个SQLITE驱动返回所有字段类型都是java.lang.Object,根据doBuild方法的实现,没有匹配的,就按String处理了。如果能指定类型就好了。
可我想不明白的是,为什么我使用
XXX model = XXX.dao.findById(id);
得到的对象model中类型就正确,id是INTEGER->int就对了。
model.getInt("id") 能使用
而XXX model = getModel(XXX.class);
得到的对象model中id就是String类型,使用
model.getInt("id')就报不能将字符串转换为int的错误。