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

发布于 2024-10-21 06:04:43 字数 951 浏览 1 评论 0原文

背景

将列数据类型映射到其相应的 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),如何确定数据库用于给定数据类型的映射?

Background

Map a column data type to its corresponding Java class.

Problem

A query returns meta information from a database:

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

For example, this query returns (the self-referential):

dictionary, resource_bundle, column_name

Where 'dictionary' is the schema name, 'resource_bundle' is the object_name, and 'column_name' is the column_name.

It would be great to do something like:

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

And have this query return:

dictionary, resource_bundle, column_name, varchar

Then use JDBC to discover that varchar is mapped to java.lang.String.

Questions

  1. In PostgreSQL, how do you determine what type is used to store the data, given a schema name, object name (guaranteed to be table or view), and column name?
  2. In a database-neutral fashion (leveraging JDBC), how do you determine the mapping a database uses for a given data type?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

︶葆Ⅱㄣ 2024-10-28 06:04:43

解决方案

答案比使用 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;
    }
}

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

Solution

The answer is more complicated than using the getMetaData method because there is no direct mapping from the integer types returned by the getMetaData method and the full class name. This solution requires two pieces of code:

  • Implementing a method to obtain the java.sql.Types constant integer value.
  • Creating a method to translate that value to a class name.

Java Type Method

The following method retrieves the meta information:

  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;
  }

Static Conversion Method

The constant integer values must be translated to a class name. This can be accomplished as follows:

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;
    }
}

Note that different databases can have different variations on the mapping.

酒与心事 2024-10-28 06:04:43

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

从 JDBC 连接,调用 getMetaDatagetColumns 从那里向下钻取以获取模式信息,表和列。

JDBC provides the means to introspect database meta information.

From a JDBC Connection, call getMetaData and getColumns drill down from there to get information for schemas, tables and, columns.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文