jdbc 2.0 将 oracle 的数值类型(number)统一识别为 BigDecimal 类型,导致在 model 中类型与实际类型不匹配。经波总指点,通过识别 oracle 数值类型精度与 java 数值类型对应,解决上述问题。
具体方案思路:
创建类 OracleMeteBuilder 继承 MetaBuilder
重写 buildColumnMetas(TableMeta tableMeta) 方法,核心代码是 64 行 - 79 行
增加数值类型对应代码
在 _Generator 类中引用 OracleMeteBuilder
具体代码
import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import javax.sql.DataSource; import com.jfinal.plugin.activerecord.generator.ColumnMeta; import com.jfinal.plugin.activerecord.generator.MetaBuilder; import com.jfinal.plugin.activerecord.generator.TableMeta; /** * MetaBuilder */ public class OracleMetaBuilder extends MetaBuilder{ public OracleMetaBuilder(DataSource dataSource) { super(dataSource); } /** * 文档参考: * http://dev.mysql.com/doc/connector-j/en/connector-j-reference-type-conversions.html * * JDBC 与时间有关类型转换规则,mysql 类型到 java 类型如下对应关系: * DATE java.sql.Date * DATETIME java.sql.Timestamp * TIMESTAMP[(M)] java.sql.Timestamp * TIME java.sql.Time * * 对数据库的 DATE、DATETIME、TIMESTAMP、TIME 四种类型注入 new java.util.Date()对象保存到库以后可以达到“秒精度” * 为了便捷性,getter、setter 方法中对上述四种字段类型采用 java.util.Date,可通过定制 TypeMapping 改变此映射规则 */ @Override protected void buildColumnMetas(TableMeta tableMeta) throws SQLException { String sql = dialect.forTableBuilderDoBuild(tableMeta.name); Statement stm = conn.createStatement(); ResultSet rs = stm.executeQuery(sql); ResultSetMetaData rsmd = rs.getMetaData(); for (int i=1; i<=rsmd.getColumnCount(); i++) { ColumnMeta cm = new ColumnMeta(); cm.name = rsmd.getColumnName(i); String typeStr = null; if (dialect.isKeepByteAndShort()) { int type = rsmd.getColumnType(i); if (type == Types.TINYINT) { typeStr = "java.lang.Byte"; } else if (type == Types.SMALLINT) { typeStr = "java.lang.Short"; } } if (typeStr == null) { String colClassName = rsmd.getColumnClassName(i); typeStr = typeMapping.getType(colClassName); } // 参考资料: // https://blog.csdn.net/ludongshun2016/article/details/71453125 // http://lysongfei.iteye.com/blog/602546 if("java.math.BigDecimal".equals(typeStr)) { int precision = rsmd.getPrecision(i); int scale = rsmd.getScale(i); if(scale == 0){ // 整数 if(precision <= 9){ typeStr = "java.lang.Integer"; } else if (precision <= 18){ typeStr = "java.lang.Long"; } else { //if (precision <= 38){ typeStr = "java.math.BigDecimal"; } } else { // 非整数都采用 BigDecimal 类型,如果需要转换成 double,在 model 写一个转换满足需求 } } if (typeStr == null) { int type = rsmd.getColumnType(i); if (type == Types.BINARY || type == Types.VARBINARY || type == Types.LONGVARBINARY || type == Types.BLOB) { typeStr = "byte[]"; } else if (type == Types.CLOB || type == Types.NCLOB) { typeStr = "java.lang.String"; } // 支持 oracle 的 TIMESTAMP、DATE 字段类型,其中 Types.DATE 值并不会出现 // 保留对 Types.DATE 的判断,一是为了逻辑上的正确性、完备性,二是其它类型的数据库可能用得着 else if (type == Types.TIMESTAMP || type == Types.DATE) { typeStr = "java.util.Date"; } // 支持 PostgreSql 的 jsonb json else if (type == Types.OTHER) { typeStr = "java.lang.Object"; } else { typeStr = "java.lang.String"; } } cm.javaType = typeStr; // 构造字段对应的属性名 attrName cm.attrName = buildAttrName(cm.name); tableMeta.columnMetas.add(cm); } rs.close(); stm.close(); } }
在 _Generator 类中引用 OracleMeteBuilder。
gen.setMetaBuilder(new OracleMetaBuilder(getDataSource()));
执行 _Generator,打完收工。
必须点赞加收藏,下次有人问我这个问题,直接给链接