Reputation: 6012
In the JDBC docs of setObject
I found this sentence:
The JDBC specification specifies a standard mapping from Java Object types to SQL types.
However, I cannot find where this mapping is defined. All I found is this. But that only specifies the mapping between SQL types and JDBC types. But I don't see, how I get from JDBC type to Java types.
More specifically, I'm wondering if e.g. this code is guaranteed to never throw an InvalidCastException
:
int type = resultSet.getMetadata().getColumnType(1);
if (type == Types.LONGNVARCHAR || type == Types.CHAR) {
String abc = (String)resultSet.getObject(1);
}
In this case it's quite intuitive that one would expect String
, but there are many other SQL types for which I don't have such an intuition.
I just cannot find a table telling me which casts can be safely performed based on the knowledge of the java.sql.Types
constant.
Upvotes: 5
Views: 5775
Reputation: 3
Here is the Mybatis Generator source code URL:
Here is the copy of source code(Prevent URL to be invalid)
/*
* Copyright 2006-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mybatis.generator.internal.types;
import java.math.BigDecimal;
import java.sql.Types;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.JavaTypeResolver;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.config.PropertyRegistry;
import org.mybatis.generator.internal.util.StringUtility;
public class JavaTypeResolverDefaultImpl implements JavaTypeResolver {
protected List<String> warnings;
protected final Properties properties;
protected Context context;
protected boolean forceBigDecimals;
protected boolean useJSR310Types;
protected final Map<Integer, JdbcTypeInformation> typeMap;
public JavaTypeResolverDefaultImpl() {
super();
properties = new Properties();
typeMap = new HashMap<>();
typeMap.put(Types.ARRAY, new JdbcTypeInformation("ARRAY", //$NON-NLS-1$
new FullyQualifiedJavaType(Object.class.getName())));
typeMap.put(Types.BIGINT, new JdbcTypeInformation("BIGINT", //$NON-NLS-1$
new FullyQualifiedJavaType(Long.class.getName())));
typeMap.put(Types.BINARY, new JdbcTypeInformation("BINARY", //$NON-NLS-1$
new FullyQualifiedJavaType("byte[]"))); //$NON-NLS-1$
typeMap.put(Types.BIT, new JdbcTypeInformation("BIT", //$NON-NLS-1$
new FullyQualifiedJavaType(Boolean.class.getName())));
typeMap.put(Types.BLOB, new JdbcTypeInformation("BLOB", //$NON-NLS-1$
new FullyQualifiedJavaType("byte[]"))); //$NON-NLS-1$
typeMap.put(Types.BOOLEAN, new JdbcTypeInformation("BOOLEAN", //$NON-NLS-1$
new FullyQualifiedJavaType(Boolean.class.getName())));
typeMap.put(Types.CHAR, new JdbcTypeInformation("CHAR", //$NON-NLS-1$
new FullyQualifiedJavaType(String.class.getName())));
typeMap.put(Types.CLOB, new JdbcTypeInformation("CLOB", //$NON-NLS-1$
new FullyQualifiedJavaType(String.class.getName())));
typeMap.put(Types.DATALINK, new JdbcTypeInformation("DATALINK", //$NON-NLS-1$
new FullyQualifiedJavaType(Object.class.getName())));
typeMap.put(Types.DATE, new JdbcTypeInformation("DATE", //$NON-NLS-1$
new FullyQualifiedJavaType(Date.class.getName())));
typeMap.put(Types.DECIMAL, new JdbcTypeInformation("DECIMAL", //$NON-NLS-1$
new FullyQualifiedJavaType(BigDecimal.class.getName())));
typeMap.put(Types.DISTINCT, new JdbcTypeInformation("DISTINCT", //$NON-NLS-1$
new FullyQualifiedJavaType(Object.class.getName())));
typeMap.put(Types.DOUBLE, new JdbcTypeInformation("DOUBLE", //$NON-NLS-1$
new FullyQualifiedJavaType(Double.class.getName())));
typeMap.put(Types.FLOAT, new JdbcTypeInformation("FLOAT", //$NON-NLS-1$
new FullyQualifiedJavaType(Double.class.getName())));
typeMap.put(Types.INTEGER, new JdbcTypeInformation("INTEGER", //$NON-NLS-1$
new FullyQualifiedJavaType(Integer.class.getName())));
typeMap.put(Types.JAVA_OBJECT, new JdbcTypeInformation("JAVA_OBJECT", //$NON-NLS-1$
new FullyQualifiedJavaType(Object.class.getName())));
typeMap.put(Types.LONGNVARCHAR, new JdbcTypeInformation("LONGNVARCHAR", //$NON-NLS-1$
new FullyQualifiedJavaType(String.class.getName())));
typeMap.put(Types.LONGVARBINARY, new JdbcTypeInformation(
"LONGVARBINARY", //$NON-NLS-1$
new FullyQualifiedJavaType("byte[]"))); //$NON-NLS-1$
typeMap.put(Types.LONGVARCHAR, new JdbcTypeInformation("LONGVARCHAR", //$NON-NLS-1$
new FullyQualifiedJavaType(String.class.getName())));
typeMap.put(Types.NCHAR, new JdbcTypeInformation("NCHAR", //$NON-NLS-1$
new FullyQualifiedJavaType(String.class.getName())));
typeMap.put(Types.NCLOB, new JdbcTypeInformation("NCLOB", //$NON-NLS-1$
new FullyQualifiedJavaType(String.class.getName())));
typeMap.put(Types.NVARCHAR, new JdbcTypeInformation("NVARCHAR", //$NON-NLS-1$
new FullyQualifiedJavaType(String.class.getName())));
typeMap.put(Types.NULL, new JdbcTypeInformation("NULL", //$NON-NLS-1$
new FullyQualifiedJavaType(Object.class.getName())));
typeMap.put(Types.NUMERIC, new JdbcTypeInformation("NUMERIC", //$NON-NLS-1$
new FullyQualifiedJavaType(BigDecimal.class.getName())));
typeMap.put(Types.OTHER, new JdbcTypeInformation("OTHER", //$NON-NLS-1$
new FullyQualifiedJavaType(Object.class.getName())));
typeMap.put(Types.REAL, new JdbcTypeInformation("REAL", //$NON-NLS-1$
new FullyQualifiedJavaType(Float.class.getName())));
typeMap.put(Types.REF, new JdbcTypeInformation("REF", //$NON-NLS-1$
new FullyQualifiedJavaType(Object.class.getName())));
typeMap.put(Types.SMALLINT, new JdbcTypeInformation("SMALLINT", //$NON-NLS-1$
new FullyQualifiedJavaType(Short.class.getName())));
typeMap.put(Types.STRUCT, new JdbcTypeInformation("STRUCT", //$NON-NLS-1$
new FullyQualifiedJavaType(Object.class.getName())));
typeMap.put(Types.TIME, new JdbcTypeInformation("TIME", //$NON-NLS-1$
new FullyQualifiedJavaType(Date.class.getName())));
typeMap.put(Types.TIMESTAMP, new JdbcTypeInformation("TIMESTAMP", //$NON-NLS-1$
new FullyQualifiedJavaType(Date.class.getName())));
typeMap.put(Types.TINYINT, new JdbcTypeInformation("TINYINT", //$NON-NLS-1$
new FullyQualifiedJavaType(Byte.class.getName())));
typeMap.put(Types.VARBINARY, new JdbcTypeInformation("VARBINARY", //$NON-NLS-1$
new FullyQualifiedJavaType("byte[]"))); //$NON-NLS-1$
typeMap.put(Types.VARCHAR, new JdbcTypeInformation("VARCHAR", //$NON-NLS-1$
new FullyQualifiedJavaType(String.class.getName())));
// JDK 1.8 types
typeMap.put(Types.TIME_WITH_TIMEZONE, new JdbcTypeInformation("TIME_WITH_TIMEZONE", //$NON-NLS-1$
new FullyQualifiedJavaType("java.time.OffsetTime"))); //$NON-NLS-1$
typeMap.put(Types.TIMESTAMP_WITH_TIMEZONE, new JdbcTypeInformation("TIMESTAMP_WITH_TIMEZONE", //$NON-NLS-1$
new FullyQualifiedJavaType("java.time.OffsetDateTime"))); //$NON-NLS-1$
}
@Override
public void addConfigurationProperties(Properties properties) {
this.properties.putAll(properties);
forceBigDecimals = StringUtility
.isTrue(properties
.getProperty(PropertyRegistry.TYPE_RESOLVER_FORCE_BIG_DECIMALS));
useJSR310Types = StringUtility
.isTrue(properties
.getProperty(PropertyRegistry.TYPE_RESOLVER_USE_JSR310_TYPES));
}
@Override
public FullyQualifiedJavaType calculateJavaType(
IntrospectedColumn introspectedColumn) {
FullyQualifiedJavaType answer = null;
JdbcTypeInformation jdbcTypeInformation = typeMap
.get(introspectedColumn.getJdbcType());
if (jdbcTypeInformation != null) {
answer = jdbcTypeInformation.getFullyQualifiedJavaType();
answer = overrideDefaultType(introspectedColumn, answer);
}
return answer;
}
protected FullyQualifiedJavaType overrideDefaultType(IntrospectedColumn column,
FullyQualifiedJavaType defaultType) {
FullyQualifiedJavaType answer = defaultType;
switch (column.getJdbcType()) {
case Types.BIT:
answer = calculateBitReplacement(column, defaultType);
break;
case Types.DATE:
answer = calculateDateType(column, defaultType);
break;
case Types.DECIMAL:
case Types.NUMERIC:
answer = calculateBigDecimalReplacement(column, defaultType);
break;
case Types.TIME:
answer = calculateTimeType(column, defaultType);
break;
case Types.TIMESTAMP:
answer = calculateTimestampType(column, defaultType);
break;
default:
break;
}
return answer;
}
protected FullyQualifiedJavaType calculateDateType(IntrospectedColumn column, FullyQualifiedJavaType defaultType) {
FullyQualifiedJavaType answer;
if (useJSR310Types) {
answer = new FullyQualifiedJavaType("java.time.LocalDate"); //$NON-NLS-1$
} else {
answer = defaultType;
}
return answer;
}
protected FullyQualifiedJavaType calculateTimeType(IntrospectedColumn column, FullyQualifiedJavaType defaultType) {
FullyQualifiedJavaType answer;
if (useJSR310Types) {
answer = new FullyQualifiedJavaType("java.time.LocalTime"); //$NON-NLS-1$
} else {
answer = defaultType;
}
return answer;
}
protected FullyQualifiedJavaType calculateTimestampType(IntrospectedColumn column,
FullyQualifiedJavaType defaultType) {
FullyQualifiedJavaType answer;
if (useJSR310Types) {
answer = new FullyQualifiedJavaType("java.time.LocalDateTime"); //$NON-NLS-1$
} else {
answer = defaultType;
}
return answer;
}
protected FullyQualifiedJavaType calculateBitReplacement(IntrospectedColumn column,
FullyQualifiedJavaType defaultType) {
FullyQualifiedJavaType answer;
if (column.getLength() > 1) {
answer = new FullyQualifiedJavaType("byte[]"); //$NON-NLS-1$
} else {
answer = defaultType;
}
return answer;
}
protected FullyQualifiedJavaType calculateBigDecimalReplacement(IntrospectedColumn column,
FullyQualifiedJavaType defaultType) {
FullyQualifiedJavaType answer;
if (column.getScale() > 0 || column.getLength() > 18 || forceBigDecimals) {
answer = defaultType;
} else if (column.getLength() > 9) {
answer = new FullyQualifiedJavaType(Long.class.getName());
} else if (column.getLength() > 4) {
answer = new FullyQualifiedJavaType(Integer.class.getName());
} else {
answer = new FullyQualifiedJavaType(Short.class.getName());
}
return answer;
}
@Override
public String calculateJdbcTypeName(IntrospectedColumn introspectedColumn) {
String answer = null;
JdbcTypeInformation jdbcTypeInformation = typeMap
.get(introspectedColumn.getJdbcType());
if (jdbcTypeInformation != null) {
answer = jdbcTypeInformation.getJdbcTypeName();
}
return answer;
}
@Override
public void setWarnings(List<String> warnings) {
this.warnings = warnings;
}
@Override
public void setContext(Context context) {
this.context = context;
}
public static class JdbcTypeInformation {
private final String jdbcTypeName;
private final FullyQualifiedJavaType fullyQualifiedJavaType;
public JdbcTypeInformation(String jdbcTypeName,
FullyQualifiedJavaType fullyQualifiedJavaType) {
this.jdbcTypeName = jdbcTypeName;
this.fullyQualifiedJavaType = fullyQualifiedJavaType;
}
public String getJdbcTypeName() {
return jdbcTypeName;
}
public FullyQualifiedJavaType getFullyQualifiedJavaType() {
return fullyQualifiedJavaType;
}
}
}
Hope this can help you :)
Upvotes: 0
Reputation: 72884
You can download the official spec for JDBC here (since you link to Java 8 documentation, the spec would be for JDBC version 4.2). Specifically it is in table B-3 in the appendices.
For the JDBC types CHAR
and LONGNVARCHAR
, the Java type is indeed String
so your cast is safe.
Upvotes: 5
Reputation: 159215
You can find the type mappings here:
Mapping SQL and Java Types (Java 1.5)
The part you're looking for is in table 8.9.3 JDBC Types Mapped to Java Object Types:
JDBC Type Java Object Type ============= ============================== CHAR String VARCHAR String LONGVARCHAR String NUMERIC java.math.BigDecimal DECIMAL java.math.BigDecimal BIT Boolean TINYINT Integer SMALLINT Integer INTEGER Integer BIGINT Long REAL Float FLOAT Double DOUBLE Double BINARY byte[] VARBINARY byte[] LONGVARBINARY byte[] DATE java.sql.Date TIME java.sql.Time TIMESTAMP java.sql.Timestamp DISTINCT Object type of underlying type CLOB Clob BLOB Blob ARRAY Array STRUCT Struct or SQLData REF Ref JAVA_OBJECT underlying Java class
Upvotes: 4