org.hibernate.type.descriptor.sql.SqlTypeDescriptorRegistry Maven / Gradle / Ivy
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type.descriptor.sql;
import java.io.Serializable;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.type.descriptor.JdbcTypeNameMapper;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.jboss.logging.Logger;
/**
* Basically a map from JDBC type code (int) -> {@link SqlTypeDescriptor}
*
* @author Steve Ebersole
*/
public class SqlTypeDescriptorRegistry {
public static final SqlTypeDescriptorRegistry INSTANCE = new SqlTypeDescriptorRegistry();
private static final Logger log = Logger.getLogger( SqlTypeDescriptorRegistry.class );
private ConcurrentHashMap descriptorMap = new ConcurrentHashMap();
public void addDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
descriptorMap.put( sqlTypeDescriptor.getSqlType(), sqlTypeDescriptor );
}
public SqlTypeDescriptor getDescriptor(int jdbcTypeCode) {
SqlTypeDescriptor descriptor = descriptorMap.get( Integer.valueOf( jdbcTypeCode ) );
if ( descriptor != null ) {
return descriptor;
}
if ( JdbcTypeNameMapper.isStandardTypeCode( jdbcTypeCode ) ) {
log.debugf(
"A standard JDBC type code [%s] was not defined in SqlTypeDescriptorRegistry",
jdbcTypeCode
);
}
// see if the typecode is part of a known type family...
JdbcTypeFamilyInformation.Family family = JdbcTypeFamilyInformation.INSTANCE.locateJdbcTypeFamilyByTypeCode( jdbcTypeCode );
if ( family != null ) {
for ( int potentialAlternateTypeCode : family.getTypeCodes() ) {
if ( potentialAlternateTypeCode != jdbcTypeCode ) {
final SqlTypeDescriptor potentialAlternateDescriptor = descriptorMap.get( Integer.valueOf( potentialAlternateTypeCode ) );
if ( potentialAlternateDescriptor != null ) {
// todo : add a SqlTypeDescriptor.canBeAssignedFrom method...
return potentialAlternateDescriptor;
}
if ( JdbcTypeNameMapper.isStandardTypeCode( potentialAlternateTypeCode ) ) {
log.debugf(
"A standard JDBC type code [%s] was not defined in SqlTypeDescriptorRegistry",
potentialAlternateTypeCode
);
}
}
}
}
// finally, create a new descriptor mapping to getObject/setObject for this type code...
final ObjectSqlTypeDescriptor fallBackDescriptor = new ObjectSqlTypeDescriptor( jdbcTypeCode );
addDescriptor( fallBackDescriptor );
return fallBackDescriptor;
}
public static class ObjectSqlTypeDescriptor implements SqlTypeDescriptor {
private final int jdbcTypeCode;
public ObjectSqlTypeDescriptor(int jdbcTypeCode) {
this.jdbcTypeCode = jdbcTypeCode;
}
@Override
public int getSqlType() {
return jdbcTypeCode;
}
@Override
public boolean canBeRemapped() {
return true;
}
@Override
public ValueBinder getBinder(JavaTypeDescriptor javaTypeDescriptor) {
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
return VarbinaryTypeDescriptor.INSTANCE.getBinder( javaTypeDescriptor );
}
return new BasicBinder( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
st.setObject( index, value, jdbcTypeCode );
}
};
}
@Override
@SuppressWarnings("unchecked")
public ValueExtractor getExtractor(JavaTypeDescriptor javaTypeDescriptor) {
if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
return VarbinaryTypeDescriptor.INSTANCE.getExtractor( javaTypeDescriptor );
}
return new BasicExtractor( javaTypeDescriptor, this ) {
@Override
protected Object doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
return rs.getObject( name );
}
@Override
protected Object doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
return statement.getObject( index );
}
@Override
protected Object doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
return statement.getObject( name );
}
};
}
}
}