将数据库类型映射到具体的Java类

背景

将列数据类型映射到其对应的Java类。

问题

查询从数据库返回元信息:

SELECT rb.object_schema, rb.object_name, rb.column_name FROM dictionary.resource_bundle rb 

例如,此查询返回(自引用):

 dictionary, resource_bundle, column_name 

其中’dictionary’是模式名称,’resource_bundle’是object_name,’column_name’是column_name。

做一些像这样的事情会很棒:

 SELECT rb.object_schema, rb.object_name, rb.column_name, rb.column_type FROM dictionary.resource_bundle rb 

并让此查询返回:

 dictionary, resource_bundle, column_name, varchar 

然后使用JDBC发现varchar 映射到java.lang.String

问题

  1. 在PostgreSQL中,在给定模式名称,对象名称(保证是表或视图)和列名称的情况下,如何确定用于存储数据的类型?
  2. 以数据库中立的方式(利用JDBC),如何确定数据库对给定数据类型使用的映射?

谢谢!

答案比使用getMetaData方法更复杂,因为getMetaData方法返回的整数类型和完整的类名没有直接映射。 此解决方案需要两段代码:

  • 实现一个方法来获取java.sql.Types常量整数值。
  • 创建将该值转换为类名的方法。

Java类型方法

以下方法检索元信息:

  public String getJavaType( String schema, String object, String column ) throws Exception { String fullName = schema + '.' + object + '.' + column; DatabaseMetaData metaData = getConnection().getMetaData(); ResultSet columnMeta = metaData.getColumns( null, schema, object, column ); String javaType = null; if( columnMeta.first() ) { int dataType = columnMeta.getInt( "DATA_TYPE" ); javaType = SQLTypeMap.convert( dataType ); } else { throw new Exception( "Unknown database column " + fullName + '.' ); } return javaType; } 

静态转换方法

必须将常量整数值转换为类名。 这可以通过以下方式完成:

 import java.sql.Types; /** * Converts database types to Java class types. */ public class SQLTypeMap { /** * Translates a data type from an integer (java.sql.Types value) to a string * that represents the corresponding class. * * @param type * The java.sql.Types value to convert to its corresponding class. * @return The class that corresponds to the given java.sql.Types * value, or Object.class if the type has no known mapping. */ public static Class toClass(int type) { Class result = Object.class; switch (type) { case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: result = String.class; break; case Types.NUMERIC: case Types.DECIMAL: result = java.math.BigDecimal.class; break; case Types.BIT: result = Boolean.class; break; case Types.TINYINT: result = Byte.class; break; case Types.SMALLINT: result = Short.class; break; case Types.INTEGER: result = Integer.class; break; case Types.BIGINT: result = Long.class; break; case Types.REAL: case Types.FLOAT: result = Float.class; break; case Types.DOUBLE: result = Double.class; break; case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: result = Byte[].class; break; case Types.DATE: result = java.sql.Date.class; break; case Types.TIME: result = java.sql.Time.class; break; case Types.TIMESTAMP: result = java.sql.Timestamp.class; break; } return result; } } 

请注意,不同的数据库可以在映射上具有不同的变体。

JDBC提供了内省数据库元信息的方法。

在JDBC Connection中,从那里调用getMetaData和getColumns以获取模式,表和列的信息。