package org.hibernate.cfg.reveng;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.MappingException;
/**
* Utility class for mapping between sqltypes and hibernate type names.
*
* @author max (based on parts from Sql2Java from Middlegen)
*
*/
public final class JDBCToHibernateTypeHelper {
private JDBCToHibernateTypeHelper() {
}
/** The Map containing the preferred conversion type values. */
private static final Map<Integer, String[]> PREFERRED_HIBERNATETYPE_FOR_SQLTYPE = new HashMap<Integer, String[]>();
static {
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.TINYINT), new String[] { "byte", Byte.class.getName()} );
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.SMALLINT), new String[] { "short", Short.class.getName()} );
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.INTEGER), new String[] { "int", Integer.class.getName()} );
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.BIGINT), new String[] { "long", Long.class.getName()} );
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.REAL), new String[] { "float", Float.class.getName()} );
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.FLOAT), new String[] { "double", Double.class.getName()} );
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.DOUBLE), new String[] { "double", Double.class.getName()});
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.DECIMAL), new String[] { "big_decimal", "big_decimal" });
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.NUMERIC), new String[] { "big_decimal", "big_decimal" });
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.BIT), new String[] { "boolean", Boolean.class.getName()});
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.BOOLEAN), new String[] { "boolean", Boolean.class.getName()});
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.CHAR), new String[] { "char", Character.class.getName()});
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.VARCHAR), new String[] { "string", "string" });
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.LONGVARCHAR), new String[] { "string", "string" });
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.BINARY), new String[] { "binary", "binary" });
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.VARBINARY), new String[] { "binary", "binary" });
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.LONGVARBINARY), new String[] { "binary", "binary" });
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.DATE), new String[] { "date", "date" });
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.TIME), new String[] { "time", "time" });
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.TIMESTAMP), new String[] { "timestamp", "timestamp" });
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.CLOB), new String[] { "clob", "clob" });
PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.put(new Integer(Types.BLOB), new String[] { "blob", "blob" });
//Hibernate does not have any built-in Type for these:
//preferredJavaTypeForSqlType.put(new Integer(Types.ARRAY), "java.sql.Array");
//preferredJavaTypeForSqlType.put(new Integer(Types.REF), "java.sql.Ref");
//preferredJavaTypeForSqlType.put(new Integer(Types.STRUCT), "java.lang.Object");
//preferredJavaTypeForSqlType.put(new Integer(Types.JAVA_OBJECT), "java.lang.Object");
}
/* (non-Javadoc)
* @see org.hibernate.cfg.JDBCTypeToHibernateTypesStrategy#getPreferredHibernateType(int, int, int, int)
*/
public static String getPreferredHibernateType(int sqlType, int size, int precision, int scale, boolean nullable, boolean generatedIdentifier) {
boolean returnNullable = nullable || generatedIdentifier;
if ( (sqlType == Types.DECIMAL || sqlType == Types.NUMERIC) && scale <= 0) { // <=
if (precision == 1) {
// NUMERIC(1) is a often used idiom for storing boolean thus providing it out of the box.
return returnNullable?Boolean.class.getName():"boolean";
}
else if (precision < 3) {
return returnNullable?Byte.class.getName():"byte";
}
else if (precision < 5) {
return returnNullable?Short.class.getName():"short";
}
else if (precision < 10) {
return returnNullable?Integer.class.getName():"int";
}
else if (precision < 19) {
return returnNullable?Long.class.getName():"long";
}
else {
return "big_decimal";
}
}
if ( sqlType == Types.CHAR && size>1 ) {
return "string";
}
String[] result = (String[]) PREFERRED_HIBERNATETYPE_FOR_SQLTYPE.get(new Integer(sqlType) );
if(result==null) {
return null;
} else if(returnNullable) {
return result[1];
} else {
return result[0];
}
}
static Map<String, Integer> jdbcTypes; // Name to value
static Map<Integer, String> jdbcTypeValues; // value to Name
public static String[] getJDBCTypes() {
checkTypes();
return (String[]) jdbcTypes.keySet().toArray(new String[jdbcTypes.size()]);
}
public static int getJDBCType(String value) {
checkTypes();
Integer number = (Integer) jdbcTypes.get(value);
if(number==null) {
try {
return Integer.parseInt(value);
}
catch (NumberFormatException nfe) {
throw new MappingException("jdbc-type: " + value + " is not a known JDBC Type nor a valid number");
}
}
else {
return number.intValue();
}
}
private static void checkTypes() {
if(jdbcTypes==null) {
jdbcTypes = new HashMap<String, Integer>();
Field[] fields = Types.class.getFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if(Modifier.isStatic(field.getModifiers() ) ) {
try {
jdbcTypes.put(field.getName(), (Integer)field.get(Types.class) );
}
catch (IllegalArgumentException e) {
// ignore
}
catch (IllegalAccessException e) {
// ignore
}
}
}
}
}
public static String getJDBCTypeName(int value) {
if(jdbcTypeValues==null) {
jdbcTypeValues = new HashMap<Integer, String>();
Field[] fields = Types.class.getFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if(Modifier.isStatic(field.getModifiers() ) ) {
try {
jdbcTypeValues.put((Integer)field.get(Types.class), field.getName() );
}
catch (IllegalArgumentException e) {
// ignore
}
catch (IllegalAccessException e) {
// ignore
}
}
}
}
String name = (String) jdbcTypeValues.get(new Integer(value) );
if(name!=null) {
return name;
}
else {
return ""+value;
}
}
/**
* @param table
* @param schema
* @param catalog
* @throws SQLException
*/
// scale and precision have numeric column
public static boolean typeHasScaleAndPrecision(int sqlType) {
return (sqlType == Types.DECIMAL || sqlType == Types.NUMERIC
|| sqlType == Types.REAL || sqlType == Types.FLOAT || sqlType == Types.DOUBLE);
}
// length is for string column
public static boolean typeHasLength(int sqlType) {
return (sqlType == Types.CHAR || sqlType == Types.DATE
|| sqlType == Types.LONGVARCHAR || sqlType == Types.TIME || sqlType == Types.TIMESTAMP
|| sqlType == Types.VARCHAR );
}
}