HHH-5957 : Provide a way for dialects to override a SqlTypeDescriptor
This commit is contained in:
parent
39d2d53968
commit
89eabb920d
|
@ -67,6 +67,9 @@ import org.hibernate.sql.CaseFragment;
|
|||
import org.hibernate.sql.ForUpdateFragment;
|
||||
import org.hibernate.sql.JoinFragment;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
import org.hibernate.util.StringHelper;
|
||||
|
||||
|
@ -293,6 +296,67 @@ public abstract class Dialect {
|
|||
typeNames.put( code, name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the dialect to override a {@link SqlTypeDescriptor}.
|
||||
* <p/>
|
||||
* If <code>sqlTypeDescriptor</code> is a "standard basic" SQL type
|
||||
* descriptor, then this method uses {@link #getSqlTypeDescriptorOverride}
|
||||
* to get an optional override based on the SQL code returned by
|
||||
* {@link SqlTypeDescriptor#getSqlType()}.
|
||||
* <p/>
|
||||
* If this dialect does not provide an override, then this method
|
||||
* simply returns <code>sqlTypeDescriptor</code>
|
||||
*
|
||||
* @param sqlTypeDescriptor The {@link SqlTypeDescriptor} to override
|
||||
* @return The {@link SqlTypeDescriptor} that should be used for this dialect;
|
||||
* if there is no override, then <code>sqlTypeDescriptor</code> is returned.
|
||||
* @throws IllegalArgumentException if <code>sqlTypeDescriptor</code> is null.
|
||||
*
|
||||
* @see {@link SqlTypeDescriptor}
|
||||
* @see {@link #getSqlTypeDescriptorOverride}
|
||||
* @see {@link StandardBasicTypes#isStandardBasicSqlTypeDescriptor(org.hibernate.type.descriptor.sql.SqlTypeDescriptor)}
|
||||
*/
|
||||
public SqlTypeDescriptor resolveSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
if ( sqlTypeDescriptor == null ) {
|
||||
throw new IllegalArgumentException( "sqlTypeDescriptor is null" );
|
||||
}
|
||||
SqlTypeDescriptor overrideBySqlCode = null;
|
||||
if ( StandardBasicTypes.isStandardBasicSqlTypeDescriptor( sqlTypeDescriptor ) ) {
|
||||
overrideBySqlCode = getSqlTypeDescriptorOverride( sqlTypeDescriptor.getSqlType() );
|
||||
}
|
||||
return overrideBySqlCode == null ? sqlTypeDescriptor : overrideBySqlCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link SqlTypeDescriptor} that should override the
|
||||
* "standard basic" SQL type descriptor for values of the specified
|
||||
* column type, or null, if there is no override.
|
||||
*
|
||||
* @param sqlCode A {@link Types} constant indicating the SQL column type
|
||||
* @return The {@link SqlTypeDescriptor} that should override the
|
||||
* "standard basic" SQL type descriptor, or null, if there is no override.
|
||||
*
|
||||
* @see {@link SqlTypeDescriptor}
|
||||
* @see {@link StandardBasicTypes#isStandardBasicSqlTypeDescriptor(org.hibernate.type.descriptor.sql.SqlTypeDescriptor)}
|
||||
*/
|
||||
protected SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) {
|
||||
SqlTypeDescriptor descriptor;
|
||||
switch ( sqlCode ) {
|
||||
case Types.BLOB: {
|
||||
descriptor = useInputStreamToInsertBlob() ? BlobTypeDescriptor.STREAM_BINDING : null;
|
||||
break;
|
||||
}
|
||||
case Types.CLOB: {
|
||||
descriptor = useInputStreamToInsertBlob() ? ClobTypeDescriptor.STREAM_BINDING : null;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
descriptor = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
// hibernate type mapping support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -40,6 +40,9 @@ import org.hibernate.exception.JDBCExceptionHelper;
|
|||
import org.hibernate.exception.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.id.SequenceGenerator;
|
||||
import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* An SQL dialect for Postgres
|
||||
|
@ -144,6 +147,30 @@ public class PostgreSQLDialect extends Dialect {
|
|||
registerFunction( "str", new SQLFunctionTemplate(Hibernate.STRING, "cast(?1 as varchar)") );
|
||||
|
||||
getDefaultProperties().setProperty(Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE);
|
||||
getDefaultProperties().setProperty( Environment.NON_CONTEXTUAL_LOB_CREATION, "true" );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) {
|
||||
SqlTypeDescriptor descriptor;
|
||||
switch ( sqlCode ) {
|
||||
case Types.BLOB: {
|
||||
descriptor = BlobTypeDescriptor.BLOB_BINDING;
|
||||
break;
|
||||
}
|
||||
case Types.CLOB: {
|
||||
descriptor = ClobTypeDescriptor.CLOB_BINDING;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
descriptor = super.getSqlTypeDescriptorOverride( sqlCode );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public String getAddColumnString() {
|
||||
|
@ -364,8 +391,18 @@ public class PostgreSQLDialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsExpectedLobUsagePattern() {
|
||||
// seems to have spotty LOB suppport
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsLobValueChangePropogation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsUnboundedLobLocatorMaterialization() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,10 @@ public abstract class AbstractSingleColumnStandardBasicType<T>
|
|||
public LobCreator getLobCreator() {
|
||||
return NonContextualLobCreator.INSTANCE;
|
||||
}
|
||||
|
||||
public SqlTypeDescriptor resolveSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
return sqlTypeDescriptor;
|
||||
}
|
||||
};
|
||||
|
||||
public final int sqlType() {
|
||||
|
|
|
@ -244,13 +244,17 @@ public abstract class AbstractStandardBasicType<T>
|
|||
public LobCreator getLobCreator() {
|
||||
return Hibernate.getLobCreator( session );
|
||||
}
|
||||
|
||||
public SqlTypeDescriptor resolveSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
return session.getFactory().getTypeResolver().resolveSqlTypeDescriptor( sqlTypeDescriptor );
|
||||
}
|
||||
};
|
||||
|
||||
return nullSafeGet( rs, name, options );
|
||||
}
|
||||
|
||||
protected final T nullSafeGet(ResultSet rs, String name, WrapperOptions options) throws SQLException {
|
||||
return sqlTypeDescriptor.getExtractor( javaTypeDescriptor ).extract( rs, name, options );
|
||||
return resolveSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor ).extract( rs, name, options );
|
||||
}
|
||||
|
||||
public Object get(ResultSet rs, String name, SessionImplementor session) throws HibernateException, SQLException {
|
||||
|
@ -272,6 +276,10 @@ public abstract class AbstractStandardBasicType<T>
|
|||
public LobCreator getLobCreator() {
|
||||
return Hibernate.getLobCreator( session );
|
||||
}
|
||||
|
||||
public SqlTypeDescriptor resolveSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
return session.getFactory().getTypeResolver().resolveSqlTypeDescriptor( sqlTypeDescriptor );
|
||||
}
|
||||
};
|
||||
|
||||
nullSafeSet( st, value, index, options );
|
||||
|
@ -279,7 +287,11 @@ public abstract class AbstractStandardBasicType<T>
|
|||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
protected final void nullSafeSet(PreparedStatement st, Object value, int index, WrapperOptions options) throws SQLException {
|
||||
sqlTypeDescriptor.getBinder( javaTypeDescriptor ).bind( st, (T) value, index, options );
|
||||
resolveSqlTypeDescriptor( options ).getBinder( javaTypeDescriptor ).bind( st, ( T ) value, index, options );
|
||||
}
|
||||
|
||||
private SqlTypeDescriptor resolveSqlTypeDescriptor(WrapperOptions options) {
|
||||
return options.resolveSqlTypeDescriptor( sqlTypeDescriptor );
|
||||
}
|
||||
|
||||
public void set(PreparedStatement st, T value, int index, SessionImplementor session) throws HibernateException, SQLException {
|
||||
|
|
|
@ -37,7 +37,7 @@ public class BlobType extends AbstractSingleColumnStandardBasicType<Blob> {
|
|||
public static final BlobType INSTANCE = new BlobType();
|
||||
|
||||
public BlobType() {
|
||||
super( org.hibernate.type.descriptor.sql.BlobTypeDescriptor.INSTANCE, BlobTypeDescriptor.INSTANCE );
|
||||
super( org.hibernate.type.descriptor.sql.BlobTypeDescriptor.DEFAULT, BlobTypeDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -38,7 +38,7 @@ public class CharacterArrayClobType extends AbstractSingleColumnStandardBasicTyp
|
|||
public static final CharacterArrayClobType INSTANCE = new CharacterArrayClobType();
|
||||
|
||||
public CharacterArrayClobType() {
|
||||
super( ClobTypeDescriptor.INSTANCE, CharacterArrayTypeDescriptor.INSTANCE );
|
||||
super( ClobTypeDescriptor.DEFAULT, CharacterArrayTypeDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -37,7 +37,7 @@ public class ClobType extends AbstractSingleColumnStandardBasicType<Clob> {
|
|||
public static final ClobType INSTANCE = new ClobType();
|
||||
|
||||
public ClobType() {
|
||||
super( org.hibernate.type.descriptor.sql.ClobTypeDescriptor.INSTANCE, ClobTypeDescriptor.INSTANCE );
|
||||
super( org.hibernate.type.descriptor.sql.ClobTypeDescriptor.DEFAULT, ClobTypeDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -38,7 +38,7 @@ public class MaterializedBlobType extends AbstractSingleColumnStandardBasicType<
|
|||
public static final MaterializedBlobType INSTANCE = new MaterializedBlobType();
|
||||
|
||||
public MaterializedBlobType() {
|
||||
super( BlobTypeDescriptor.INSTANCE, PrimitiveByteArrayTypeDescriptor.INSTANCE );
|
||||
super( BlobTypeDescriptor.DEFAULT, PrimitiveByteArrayTypeDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -37,7 +37,7 @@ public class MaterializedClobType extends AbstractSingleColumnStandardBasicType<
|
|||
public static final MaterializedClobType INSTANCE = new MaterializedClobType();
|
||||
|
||||
public MaterializedClobType() {
|
||||
super( ClobTypeDescriptor.INSTANCE, StringTypeDescriptor.INSTANCE );
|
||||
super( ClobTypeDescriptor.DEFAULT, StringTypeDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -35,7 +35,7 @@ public class PrimitiveCharacterArrayClobType extends AbstractSingleColumnStandar
|
|||
public static final CharacterArrayClobType INSTANCE = new CharacterArrayClobType();
|
||||
|
||||
public PrimitiveCharacterArrayClobType() {
|
||||
super( ClobTypeDescriptor.INSTANCE, PrimitiveCharacterArrayTypeDescriptor.INSTANCE );
|
||||
super( ClobTypeDescriptor.DEFAULT, PrimitiveCharacterArrayTypeDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
*/
|
||||
package org.hibernate.type;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Centralizes access to the standard set of basic {@link Type types}.
|
||||
* <p/>
|
||||
|
@ -37,108 +42,111 @@ package org.hibernate.type;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardBasicTypes {
|
||||
|
||||
private static final Set<SqlTypeDescriptor> sqlTypeDescriptors = new HashSet<SqlTypeDescriptor>();
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Boolean} to JDBC {@link java.sql.Types#BIT BIT}.
|
||||
*
|
||||
* @see BooleanType
|
||||
*/
|
||||
public static final BooleanType BOOLEAN = BooleanType.INSTANCE;
|
||||
public static final BooleanType BOOLEAN = register( BooleanType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Boolean} to JDBC {@link java.sql.Types#INTEGER INTEGER}.
|
||||
*
|
||||
* @see NumericBooleanType
|
||||
*/
|
||||
public static final NumericBooleanType NUMERIC_BOOLEAN = NumericBooleanType.INSTANCE;
|
||||
public static final NumericBooleanType NUMERIC_BOOLEAN = register( NumericBooleanType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Boolean} to JDBC {@link java.sql.Types#CHAR CHAR(1)} (using 'T'/'F').
|
||||
*
|
||||
* @see TrueFalseType
|
||||
*/
|
||||
public static final TrueFalseType TRUE_FALSE = TrueFalseType.INSTANCE;
|
||||
public static final TrueFalseType TRUE_FALSE = register( TrueFalseType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Boolean} to JDBC {@link java.sql.Types#CHAR CHAR(1)} (using 'Y'/'N').
|
||||
*
|
||||
* @see YesNoType
|
||||
*/
|
||||
public static final YesNoType YES_NO = YesNoType.INSTANCE;
|
||||
public static final YesNoType YES_NO = register( YesNoType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Byte} to JDBC {@link java.sql.Types#TINYINT TINYINT}.
|
||||
*/
|
||||
public static final ByteType BYTE = ByteType.INSTANCE;
|
||||
public static final ByteType BYTE = register( ByteType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Short} to JDBC {@link java.sql.Types#SMALLINT SMALLINT}.
|
||||
*
|
||||
* @see ShortType
|
||||
*/
|
||||
public static final ShortType SHORT = ShortType.INSTANCE;
|
||||
public static final ShortType SHORT = register( ShortType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Integer} to JDBC {@link java.sql.Types#INTEGER INTEGER}.
|
||||
*
|
||||
* @see IntegerType
|
||||
*/
|
||||
public static final IntegerType INTEGER = IntegerType.INSTANCE;
|
||||
public static final IntegerType INTEGER = register( IntegerType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Long} to JDBC {@link java.sql.Types#BIGINT BIGINT}.
|
||||
*
|
||||
* @see LongType
|
||||
*/
|
||||
public static final LongType LONG = LongType.INSTANCE;
|
||||
public static final LongType LONG = register( LongType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Float} to JDBC {@link java.sql.Types#FLOAT FLOAT}.
|
||||
*
|
||||
* @see FloatType
|
||||
*/
|
||||
public static final FloatType FLOAT = FloatType.INSTANCE;
|
||||
public static final FloatType FLOAT = register( FloatType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Double} to JDBC {@link java.sql.Types#DOUBLE DOUBLE}.
|
||||
*
|
||||
* @see DoubleType
|
||||
*/
|
||||
public static final DoubleType DOUBLE = DoubleType.INSTANCE;
|
||||
public static final DoubleType DOUBLE = register( DoubleType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.math.BigInteger} to JDBC {@link java.sql.Types#NUMERIC NUMERIC}.
|
||||
*
|
||||
* @see BigIntegerType
|
||||
*/
|
||||
public static final BigIntegerType BIG_INTEGER = BigIntegerType.INSTANCE;
|
||||
public static final BigIntegerType BIG_INTEGER = register( BigIntegerType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.math.BigDecimal} to JDBC {@link java.sql.Types#NUMERIC NUMERIC}.
|
||||
*
|
||||
* @see BigDecimalType
|
||||
*/
|
||||
public static final BigDecimalType BIG_DECIMAL = BigDecimalType.INSTANCE;
|
||||
public static final BigDecimalType BIG_DECIMAL = register( BigDecimalType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Character} to JDBC {@link java.sql.Types#CHAR CHAR(1)}.
|
||||
*
|
||||
* @see CharacterType
|
||||
*/
|
||||
public static final CharacterType CHARACTER = CharacterType.INSTANCE;
|
||||
public static final CharacterType CHARACTER = register( CharacterType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link String} to JDBC {@link java.sql.Types#VARCHAR VARCHAR}.
|
||||
*
|
||||
* @see StringType
|
||||
*/
|
||||
public static final StringType STRING = StringType.INSTANCE;
|
||||
public static final StringType STRING = register( StringType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.net.URL} to JDBC {@link java.sql.Types#VARCHAR VARCHAR}.
|
||||
*
|
||||
* @see UrlType
|
||||
*/
|
||||
public static final UrlType URL = UrlType.INSTANCE;
|
||||
public static final UrlType URL = register( UrlType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.util.Date} ({@link java.sql.Time}) to JDBC
|
||||
|
@ -146,7 +154,7 @@ public class StandardBasicTypes {
|
|||
*
|
||||
* @see TimeType
|
||||
*/
|
||||
public static final TimeType TIME = TimeType.INSTANCE;
|
||||
public static final TimeType TIME = register( TimeType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.util.Date} ({@link java.sql.Date}) to JDBC
|
||||
|
@ -154,7 +162,7 @@ public class StandardBasicTypes {
|
|||
*
|
||||
* @see TimeType
|
||||
*/
|
||||
public static final DateType DATE = DateType.INSTANCE;
|
||||
public static final DateType DATE = register( DateType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.util.Date} ({@link java.sql.Timestamp}) to JDBC
|
||||
|
@ -162,7 +170,7 @@ public class StandardBasicTypes {
|
|||
*
|
||||
* @see TimeType
|
||||
*/
|
||||
public static final TimestampType TIMESTAMP = TimestampType.INSTANCE;
|
||||
public static final TimestampType TIMESTAMP = register( TimestampType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.util.Calendar} to JDBC
|
||||
|
@ -170,7 +178,7 @@ public class StandardBasicTypes {
|
|||
*
|
||||
* @see CalendarType
|
||||
*/
|
||||
public static final CalendarType CALENDAR = CalendarType.INSTANCE;
|
||||
public static final CalendarType CALENDAR = register( CalendarType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.util.Calendar} to JDBC
|
||||
|
@ -178,63 +186,63 @@ public class StandardBasicTypes {
|
|||
*
|
||||
* @see CalendarDateType
|
||||
*/
|
||||
public static final CalendarDateType CALENDAR_DATE = CalendarDateType.INSTANCE;
|
||||
public static final CalendarDateType CALENDAR_DATE = register( CalendarDateType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Class} to JDBC {@link java.sql.Types#VARCHAR VARCHAR}.
|
||||
*
|
||||
* @see ClassType
|
||||
*/
|
||||
public static final ClassType CLASS = ClassType.INSTANCE;
|
||||
public static final ClassType CLASS = register( ClassType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.util.Locale} to JDBC {@link java.sql.Types#VARCHAR VARCHAR}.
|
||||
*
|
||||
* @see LocaleType
|
||||
*/
|
||||
public static final LocaleType LOCALE = LocaleType.INSTANCE;
|
||||
public static final LocaleType LOCALE = register( LocaleType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.util.Currency} to JDBC {@link java.sql.Types#VARCHAR VARCHAR}.
|
||||
*
|
||||
* @see CurrencyType
|
||||
*/
|
||||
public static final CurrencyType CURRENCY = CurrencyType.INSTANCE;
|
||||
public static final CurrencyType CURRENCY = register( CurrencyType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.util.TimeZone} to JDBC {@link java.sql.Types#VARCHAR VARCHAR}.
|
||||
*
|
||||
* @see TimeZoneType
|
||||
*/
|
||||
public static final TimeZoneType TIMEZONE = TimeZoneType.INSTANCE;
|
||||
public static final TimeZoneType TIMEZONE = register( TimeZoneType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.util.UUID} to JDBC {@link java.sql.Types#BINARY BINARY}.
|
||||
*
|
||||
* @see UUIDBinaryType
|
||||
*/
|
||||
public static final UUIDBinaryType UUID_BINARY = UUIDBinaryType.INSTANCE;
|
||||
public static final UUIDBinaryType UUID_BINARY = register( UUIDBinaryType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.util.UUID} to JDBC {@link java.sql.Types#CHAR CHAR}.
|
||||
*
|
||||
* @see UUIDCharType
|
||||
*/
|
||||
public static final UUIDCharType UUID_CHAR = UUIDCharType.INSTANCE;
|
||||
public static final UUIDCharType UUID_CHAR = register( UUIDCharType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@code byte[]} to JDBC {@link java.sql.Types#VARBINARY VARBINARY}.
|
||||
*
|
||||
* @see BinaryType
|
||||
*/
|
||||
public static final BinaryType BINARY = BinaryType.INSTANCE;
|
||||
public static final BinaryType BINARY = register( BinaryType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Byte Byte[]} to JDBC {@link java.sql.Types#VARBINARY VARBINARY}.
|
||||
*
|
||||
* @see WrapperBinaryType
|
||||
*/
|
||||
public static final WrapperBinaryType WRAPPER_BINARY = WrapperBinaryType.INSTANCE;
|
||||
public static final WrapperBinaryType WRAPPER_BINARY = register( WrapperBinaryType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@code byte[]} to JDBC {@link java.sql.Types#LONGVARBINARY LONGVARBINARY}.
|
||||
|
@ -242,7 +250,7 @@ public class StandardBasicTypes {
|
|||
* @see ImageType
|
||||
* @see #MATERIALIZED_BLOB
|
||||
*/
|
||||
public static final ImageType IMAGE = ImageType.INSTANCE;
|
||||
public static final ImageType IMAGE = register( ImageType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.sql.Blob} to JDBC {@link java.sql.Types#BLOB BLOB}.
|
||||
|
@ -250,7 +258,7 @@ public class StandardBasicTypes {
|
|||
* @see BlobType
|
||||
* @see #MATERIALIZED_BLOB
|
||||
*/
|
||||
public static final BlobType BLOB = BlobType.INSTANCE;
|
||||
public static final BlobType BLOB = register( BlobType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@code byte[]} to JDBC {@link java.sql.Types#BLOB BLOB}.
|
||||
|
@ -259,14 +267,14 @@ public class StandardBasicTypes {
|
|||
* @see #MATERIALIZED_BLOB
|
||||
* @see #IMAGE
|
||||
*/
|
||||
public static final MaterializedBlobType MATERIALIZED_BLOB = MaterializedBlobType.INSTANCE;
|
||||
public static final MaterializedBlobType MATERIALIZED_BLOB = register( MaterializedBlobType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@code char[]} to JDBC {@link java.sql.Types#VARCHAR VARCHAR}.
|
||||
*
|
||||
* @see CharArrayType
|
||||
*/
|
||||
public static final CharArrayType CHAR_ARRAY = CharArrayType.INSTANCE;
|
||||
public static final CharArrayType CHAR_ARRAY = register( CharArrayType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Character Character[]} to JDBC
|
||||
|
@ -274,7 +282,7 @@ public class StandardBasicTypes {
|
|||
*
|
||||
* @see CharacterArrayType
|
||||
*/
|
||||
public static final CharacterArrayType CHARACTER_ARRAY = CharacterArrayType.INSTANCE;
|
||||
public static final CharacterArrayType CHARACTER_ARRAY = register( CharacterArrayType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link String} to JDBC {@link java.sql.Types#LONGVARCHAR LONGVARCHAR}.
|
||||
|
@ -283,7 +291,7 @@ public class StandardBasicTypes {
|
|||
*
|
||||
* @see TextType
|
||||
*/
|
||||
public static final TextType TEXT = TextType.INSTANCE;
|
||||
public static final TextType TEXT = register( TextType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.sql.Clob} to JDBC {@link java.sql.Types#CLOB CLOB}.
|
||||
|
@ -291,7 +299,7 @@ public class StandardBasicTypes {
|
|||
* @see ClobType
|
||||
* @see #MATERIALIZED_CLOB
|
||||
*/
|
||||
public static final ClobType CLOB = ClobType.INSTANCE;
|
||||
public static final ClobType CLOB = register( ClobType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link String} to JDBC {@link java.sql.Types#CLOB CLOB}.
|
||||
|
@ -300,7 +308,7 @@ public class StandardBasicTypes {
|
|||
* @see #MATERIALIZED_CLOB
|
||||
* @see #TEXT
|
||||
*/
|
||||
public static final MaterializedClobType MATERIALIZED_CLOB = MaterializedClobType.INSTANCE;
|
||||
public static final MaterializedClobType MATERIALIZED_CLOB = register( MaterializedClobType.INSTANCE );
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.io.Serializable} to JDBC {@link java.sql.Types#VARBINARY VARBINARY}.
|
||||
|
@ -309,5 +317,14 @@ public class StandardBasicTypes {
|
|||
*
|
||||
* @see SerializableType
|
||||
*/
|
||||
public static final SerializableType SERIALIZABLE = SerializableType.INSTANCE;
|
||||
public static final SerializableType SERIALIZABLE = register( SerializableType.INSTANCE );
|
||||
|
||||
private static <T extends AbstractSingleColumnStandardBasicType> T register(T type) {
|
||||
sqlTypeDescriptors.add( type.getSqlTypeDescriptor() );
|
||||
return type;
|
||||
}
|
||||
|
||||
public static final boolean isStandardBasicSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
return sqlTypeDescriptors.contains( sqlTypeDescriptor );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,6 +86,10 @@ public final class TypeFactory implements Serializable {
|
|||
typeScope.injectSessionFactory( factory );
|
||||
}
|
||||
|
||||
public SessionFactoryImplementor resolveSessionFactory() {
|
||||
return typeScope.resolveFactory();
|
||||
}
|
||||
|
||||
public Type byClass(Class clazz, Properties parameters) {
|
||||
if ( Type.class.isAssignableFrom( clazz ) ) {
|
||||
return type( (Class<Type>) clazz, parameters );
|
||||
|
|
|
@ -24,11 +24,17 @@
|
|||
package org.hibernate.type;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.classic.Lifecycle;
|
||||
import org.hibernate.engine.SessionFactoryImplementor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.usertype.CompositeUserType;
|
||||
import org.hibernate.usertype.UserType;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
|
@ -39,21 +45,31 @@ import org.hibernate.util.ReflectHelper;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TypeResolver implements Serializable {
|
||||
private static final Logger log = LoggerFactory.getLogger( TypeResolver.class );
|
||||
|
||||
private final BasicTypeRegistry basicTypeRegistry;
|
||||
private final TypeFactory typeFactory;
|
||||
private final Map<SqlTypeDescriptor, SqlTypeDescriptor> resolvedSqlTypeDescriptors;
|
||||
|
||||
public TypeResolver() {
|
||||
this( new BasicTypeRegistry(), new TypeFactory() );
|
||||
this( new BasicTypeRegistry(), new TypeFactory(), null );
|
||||
}
|
||||
|
||||
public TypeResolver(BasicTypeRegistry basicTypeRegistry, TypeFactory typeFactory) {
|
||||
public TypeResolver(BasicTypeRegistry basicTypeRegistry,
|
||||
TypeFactory typeFactory,
|
||||
Map<SqlTypeDescriptor, SqlTypeDescriptor> resolvedSqlTypeDescriptors) {
|
||||
this.basicTypeRegistry = basicTypeRegistry;
|
||||
this.typeFactory = typeFactory;
|
||||
this.resolvedSqlTypeDescriptors = resolvedSqlTypeDescriptors;
|
||||
}
|
||||
|
||||
public TypeResolver scope(SessionFactoryImplementor factory) {
|
||||
typeFactory.injectSessionFactory( factory );
|
||||
return new TypeResolver( basicTypeRegistry.shallowCopy(), typeFactory );
|
||||
return new TypeResolver(
|
||||
basicTypeRegistry.shallowCopy(),
|
||||
typeFactory,
|
||||
new HashMap<SqlTypeDescriptor, SqlTypeDescriptor>( 25 )
|
||||
);
|
||||
}
|
||||
|
||||
public void registerTypeOverride(BasicType type) {
|
||||
|
@ -135,4 +151,39 @@ public class TypeResolver implements Serializable {
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
public SqlTypeDescriptor resolveSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
if ( resolvedSqlTypeDescriptors == null ) {
|
||||
throw new IllegalStateException( "cannot resolve a SqlTypeDescriptor until the TypeResolver is scoped." );
|
||||
}
|
||||
SqlTypeDescriptor resolvedDescriptor = resolvedSqlTypeDescriptors.get( sqlTypeDescriptor );
|
||||
if ( resolvedDescriptor == null ) {
|
||||
resolvedDescriptor =
|
||||
typeFactory.resolveSessionFactory().getDialect().resolveSqlTypeDescriptor( sqlTypeDescriptor );
|
||||
if ( resolvedDescriptor == null ) {
|
||||
throw new IllegalStateException( "dialect returned a resolved SqlTypeDescriptor that was null." );
|
||||
}
|
||||
if ( sqlTypeDescriptor != resolvedDescriptor ) {
|
||||
log.info(
|
||||
"Adding override for {}: {}",
|
||||
new String[] {
|
||||
sqlTypeDescriptor.getClass().getName(),
|
||||
resolvedDescriptor.getClass().getName(),
|
||||
}
|
||||
);
|
||||
if ( sqlTypeDescriptor.getSqlType() != resolvedDescriptor.getSqlType() ) {
|
||||
log.warn( "Resolved SqlTypeDescriptor is for a different SQL code. {} has sqlCode={}; type override {} has sqlCode={}",
|
||||
new String[] {
|
||||
sqlTypeDescriptor.getClass().getName(),
|
||||
String.valueOf( sqlTypeDescriptor.getSqlType() ),
|
||||
resolvedDescriptor.getClass().getName(),
|
||||
String.valueOf( resolvedDescriptor.getSqlType() ),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
resolvedSqlTypeDescriptors.put( sqlTypeDescriptor, resolvedDescriptor );
|
||||
}
|
||||
return resolvedDescriptor;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class WrappedMaterializedBlobType extends AbstractSingleColumnStandardBas
|
|||
public static final WrappedMaterializedBlobType INSTANCE = new WrappedMaterializedBlobType();
|
||||
|
||||
public WrappedMaterializedBlobType() {
|
||||
super( BlobTypeDescriptor.INSTANCE, ByteArrayTypeDescriptor.INSTANCE );
|
||||
super( BlobTypeDescriptor.DEFAULT, ByteArrayTypeDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -23,7 +23,10 @@
|
|||
*/
|
||||
package org.hibernate.type.descriptor;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.LobCreator;
|
||||
import org.hibernate.type.TypeResolver;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* TODO : javadoc
|
||||
|
@ -33,4 +36,5 @@ import org.hibernate.engine.jdbc.LobCreator;
|
|||
public interface WrapperOptions {
|
||||
public boolean useStreamForLobBinding();
|
||||
public LobCreator getLobCreator();
|
||||
public SqlTypeDescriptor resolveSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.Comparator;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.jdbc.BlobProxy;
|
||||
import org.hibernate.engine.jdbc.WrappedBlob;
|
||||
import org.hibernate.type.descriptor.BinaryStream;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
/**
|
||||
|
@ -107,7 +108,7 @@ public class BlobTypeDescriptor extends AbstractTypeDescriptor<Blob> {
|
|||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X> X unwrap(Blob value, Class<X> type, WrapperOptions options) {
|
||||
if ( !Blob.class.isAssignableFrom( type ) ) {
|
||||
if ( ! ( Blob.class.isAssignableFrom( type ) || BinaryStream.class.isAssignableFrom( type ) ) ) {
|
||||
throw unknownUnwrap( type );
|
||||
}
|
||||
|
||||
|
@ -115,6 +116,15 @@ public class BlobTypeDescriptor extends AbstractTypeDescriptor<Blob> {
|
|||
return null;
|
||||
}
|
||||
|
||||
if ( BinaryStream.class.isAssignableFrom( type ) ) {
|
||||
try {
|
||||
return (X) new BinaryStreamImpl( DataHelper.extractBytes( value.getBinaryStream() ) );
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
throw new HibernateException( "Unable to access blob stream", e );
|
||||
}
|
||||
}
|
||||
|
||||
final Blob blob = WrappedBlob.class.isInstance( value )
|
||||
? ( (WrappedBlob) value ).getWrappedBlob()
|
||||
: value;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.hibernate.type.descriptor.java;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Clob;
|
||||
import java.sql.SQLException;
|
||||
|
@ -31,6 +32,7 @@ import java.util.Comparator;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.jdbc.ClobProxy;
|
||||
import org.hibernate.engine.jdbc.WrappedClob;
|
||||
import org.hibernate.type.descriptor.CharacterStream;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
/**
|
||||
|
@ -98,8 +100,8 @@ public class ClobTypeDescriptor extends AbstractTypeDescriptor<Clob> {
|
|||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X> X unwrap(Clob value, Class<X> type, WrapperOptions options) {
|
||||
if ( !Clob.class.isAssignableFrom( type ) ) {
|
||||
public <X> X unwrap(final Clob value, Class<X> type, WrapperOptions options) {
|
||||
if ( ! ( Clob.class.isAssignableFrom( type ) || CharacterStream.class.isAssignableFrom( type ) ) ) {
|
||||
throw unknownUnwrap( type );
|
||||
}
|
||||
|
||||
|
@ -107,6 +109,15 @@ public class ClobTypeDescriptor extends AbstractTypeDescriptor<Clob> {
|
|||
return null;
|
||||
}
|
||||
|
||||
if ( CharacterStream.class.isAssignableFrom( type ) ) {
|
||||
try {
|
||||
return (X) new CharacterStreamImpl( DataHelper.extractString( value.getCharacterStream() ) );
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
throw new HibernateException( "Unable to access lob stream", e );
|
||||
}
|
||||
}
|
||||
|
||||
final Clob clob = WrappedClob.class.isInstance( value )
|
||||
? ( (WrappedClob) value ).getWrappedClob()
|
||||
: value;
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
package org.hibernate.type.descriptor.sql;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.sql.Blob;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
@ -41,32 +40,72 @@ import org.hibernate.type.descriptor.WrapperOptions;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BlobTypeDescriptor implements SqlTypeDescriptor {
|
||||
public static final BlobTypeDescriptor INSTANCE = new BlobTypeDescriptor();
|
||||
public abstract class BlobTypeDescriptor implements SqlTypeDescriptor {
|
||||
|
||||
public int getSqlType() {
|
||||
return Types.BLOB;
|
||||
}
|
||||
private BlobTypeDescriptor() {}
|
||||
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
|
||||
if ( options.useStreamForLobBinding() ) {
|
||||
final BinaryStream binaryStream = javaTypeDescriptor.unwrap( value, BinaryStream.class, options );
|
||||
st.setBinaryStream( index, binaryStream.getInputStream(), binaryStream.getLength() );
|
||||
public static final BlobTypeDescriptor DEFAULT =
|
||||
new BlobTypeDescriptor() {
|
||||
public <X> BasicBinder<X> getBlobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
|
||||
if ( options.useStreamForLobBinding() ) {
|
||||
STREAM_BINDING.getBlobBinder( javaTypeDescriptor ).doBind( st, value, index, options );
|
||||
}
|
||||
else if ( byte[].class.isInstance( value ) ) {
|
||||
// performance shortcut for binding BLOB data in byte[] format
|
||||
PRIMITIVE_ARRAY_BINDING.getBlobBinder( javaTypeDescriptor ).doBind( st, value, index, options );
|
||||
}
|
||||
else {
|
||||
BLOB_BINDING.getBlobBinder( javaTypeDescriptor ).doBind( st, value, index, options );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
else if ( byte[].class.isInstance( value ) ) {
|
||||
// performance shortcut for binding BLOB data in byte[] format
|
||||
final byte[] bytes = (byte[]) value;
|
||||
st.setBytes( index, bytes );
|
||||
};
|
||||
|
||||
public static final BlobTypeDescriptor PRIMITIVE_ARRAY_BINDING =
|
||||
new BlobTypeDescriptor() {
|
||||
public <X> BasicBinder<X> getBlobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
public void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setBytes( index, javaTypeDescriptor.unwrap( value, byte[].class, options ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
st.setBlob( index, javaTypeDescriptor.unwrap( value, Blob.class, options ) );
|
||||
};
|
||||
|
||||
public static final BlobTypeDescriptor BLOB_BINDING =
|
||||
new BlobTypeDescriptor() {
|
||||
public <X> BasicBinder<X> getBlobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setBlob( index, javaTypeDescriptor.unwrap( value, Blob.class, options ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
public static final BlobTypeDescriptor STREAM_BINDING =
|
||||
new BlobTypeDescriptor() {
|
||||
public <X> BasicBinder<X> getBlobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
final BinaryStream binaryStream = javaTypeDescriptor.unwrap( value, BinaryStream.class, options );
|
||||
st.setBinaryStream( index, binaryStream.getInputStream(), binaryStream.getLength() );
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
protected abstract <X> BasicBinder<X> getBlobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor);
|
||||
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||
|
@ -76,4 +115,12 @@ public class BlobTypeDescriptor implements SqlTypeDescriptor {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int getSqlType() {
|
||||
return Types.BLOB;
|
||||
}
|
||||
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return getBlobBinder( javaTypeDescriptor );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,28 +41,62 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ClobTypeDescriptor implements SqlTypeDescriptor {
|
||||
public static final ClobTypeDescriptor INSTANCE = new ClobTypeDescriptor();
|
||||
public abstract class ClobTypeDescriptor implements SqlTypeDescriptor {
|
||||
|
||||
public static final ClobTypeDescriptor DEFAULT =
|
||||
new ClobTypeDescriptor() {
|
||||
public <X> BasicBinder<X> getClobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
|
||||
if ( options.useStreamForLobBinding() ) {
|
||||
STREAM_BINDING.getClobBinder( javaTypeDescriptor ).doBind( st, value, index, options );
|
||||
}
|
||||
else {
|
||||
CLOB_BINDING.getClobBinder( javaTypeDescriptor ).doBind( st, value, index, options );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
public static final ClobTypeDescriptor CLOB_BINDING =
|
||||
new ClobTypeDescriptor() {
|
||||
public <X> BasicBinder<X> getClobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
st.setClob( index, javaTypeDescriptor.unwrap( value, Clob.class, options ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
public static final ClobTypeDescriptor STREAM_BINDING =
|
||||
new ClobTypeDescriptor() {
|
||||
public <X> BasicBinder<X> getClobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
final CharacterStream characterStream = javaTypeDescriptor.unwrap( value, CharacterStream.class, options );
|
||||
st.setCharacterStream( index, characterStream.getReader(), characterStream.getLength() );
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
protected abstract <X> BasicBinder<X> getClobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor);
|
||||
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return getClobBinder( javaTypeDescriptor );
|
||||
}
|
||||
|
||||
public int getSqlType() {
|
||||
return Types.CLOB;
|
||||
}
|
||||
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
|
||||
if ( options.useStreamForLobBinding() ) {
|
||||
final CharacterStream characterStream = javaTypeDescriptor.unwrap( value, CharacterStream.class, options );
|
||||
st.setCharacterStream( index, characterStream.getReader(), characterStream.getLength() );
|
||||
}
|
||||
else {
|
||||
st.setClob( index, javaTypeDescriptor.unwrap( value, Clob.class, options ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
|
|
|
@ -28,7 +28,7 @@ import java.util.Arrays;
|
|||
import org.hibernate.Session;
|
||||
import org.hibernate.cfg.AnnotationConfiguration;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.test.annotations.TestCase;
|
||||
import org.hibernate.testing.junit.DialectChecks;
|
||||
import org.hibernate.testing.junit.RequiresDialectFeature;
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ Copyright (c) 2011, 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
|
||||
-->
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping package="org.hibernate.test.typeoverride">
|
||||
|
||||
<class name="Entity">
|
||||
|
||||
<id name="id">
|
||||
<generator class="native"/>
|
||||
</id>
|
||||
<property name="name"/>
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.test.typeoverride;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class Entity {
|
||||
private long id;
|
||||
private String name;
|
||||
|
||||
public Entity() {
|
||||
}
|
||||
|
||||
public Entity(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.test.typeoverride;
|
||||
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class H2DialectOverridePrefixedVarcharSqlTypeDesc extends H2Dialect {
|
||||
public SqlTypeDescriptor resolveSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
return sqlTypeDescriptor == StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor() ?
|
||||
VarcharTypeDescriptor.INSTANCE :
|
||||
super.resolveSqlTypeDescriptor( sqlTypeDescriptor );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.test.typeoverride;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class H2DialectOverrideVarcharSqlCode extends H2Dialect {
|
||||
public SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) {
|
||||
return sqlCode == Types.VARCHAR ?
|
||||
StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor() :
|
||||
super.getSqlTypeDescriptorOverride( sqlCode );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.test.typeoverride;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
|
||||
import org.hibernate.type.DiscriminatorType;
|
||||
import org.hibernate.type.StringType;
|
||||
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.hibernate.type.descriptor.sql.BasicBinder;
|
||||
import org.hibernate.type.descriptor.sql.BasicExtractor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class StoredPrefixedStringType
|
||||
extends AbstractSingleColumnStandardBasicType<String>
|
||||
implements DiscriminatorType<String> {
|
||||
public static final String PREFIX = "PRE:";
|
||||
private static final SqlTypeDescriptor PREFIXED_VARCHAR_TYPE_DESCRIPTOR =
|
||||
new VarcharTypeDescriptor() {
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
|
||||
String stringValue = javaTypeDescriptor.unwrap( value, String.class, options );
|
||||
st.setString( index, PREFIX + stringValue );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
|
||||
String stringValue = rs.getString( name );
|
||||
if ( ! stringValue.startsWith( PREFIX ) ) {
|
||||
throw new AssertionFailure( "Value read from resultset does not have prefix." );
|
||||
}
|
||||
return javaTypeDescriptor.wrap( stringValue.substring( PREFIX.length() ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static final StoredPrefixedStringType INSTANCE = new StoredPrefixedStringType();
|
||||
|
||||
public StoredPrefixedStringType() {
|
||||
super( PREFIXED_VARCHAR_TYPE_DESCRIPTOR, StringType.INSTANCE.getJavaTypeDescriptor() );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return StringType.INSTANCE.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean registerUnderJavaType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String objectToSQLString(String value, Dialect dialect) throws Exception {
|
||||
return StringType.INSTANCE.objectToSQLString( value, dialect );
|
||||
}
|
||||
|
||||
public String stringToObject(String xml) throws Exception {
|
||||
return StringType.INSTANCE.stringToObject( xml );
|
||||
}
|
||||
|
||||
public String toString(String value) {
|
||||
return StringType.INSTANCE.toString( value );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.test.typeoverride;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.engine.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.testing.junit.functional.FunctionalTestCase;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.IntegerTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class TypeOverrideTest extends FunctionalTestCase {
|
||||
|
||||
public TypeOverrideTest(String string) {
|
||||
super( string );
|
||||
}
|
||||
|
||||
public String[] getMappings() {
|
||||
return new String[] { "typeoverride/Entity.hbm.xml" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Configuration cfg) {
|
||||
cfg.registerTypeOverride( StoredPrefixedStringType.INSTANCE );
|
||||
}
|
||||
|
||||
public void testStandardBasicSqlTypeDescriptor() {
|
||||
// no override
|
||||
assertTrue( StandardBasicTypes.isStandardBasicSqlTypeDescriptor( IntegerTypeDescriptor.INSTANCE ) );
|
||||
assertSame( IntegerTypeDescriptor.INSTANCE, getResolvedSqlTypeDescriptor( IntegerTypeDescriptor.INSTANCE ) );
|
||||
|
||||
// override depends on Dialect.useInputStreamToInsertBlob();
|
||||
// Postgresql explicitly overrides BlobTypeDescriptor.DEFAULT
|
||||
assertTrue( StandardBasicTypes.isStandardBasicSqlTypeDescriptor( BlobTypeDescriptor.DEFAULT ) );
|
||||
if ( getDialect().useInputStreamToInsertBlob() ) {
|
||||
assertSame(
|
||||
BlobTypeDescriptor.STREAM_BINDING,
|
||||
getDialect().resolveSqlTypeDescriptor( BlobTypeDescriptor.DEFAULT )
|
||||
);
|
||||
}
|
||||
else if ( PostgreSQLDialect.class.isInstance( getDialect() ) ) {
|
||||
assertSame(
|
||||
BlobTypeDescriptor.BLOB_BINDING,
|
||||
getDialect().resolveSqlTypeDescriptor( BlobTypeDescriptor.DEFAULT )
|
||||
);
|
||||
}
|
||||
else {
|
||||
assertSame(
|
||||
BlobTypeDescriptor.DEFAULT,
|
||||
getDialect().resolveSqlTypeDescriptor( BlobTypeDescriptor.DEFAULT )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void testNonStandardSqlTypeDescriptor() {
|
||||
// no override
|
||||
SqlTypeDescriptor sqlTypeDescriptor = new IntegerTypeDescriptor();
|
||||
assertFalse( StandardBasicTypes.isStandardBasicSqlTypeDescriptor( sqlTypeDescriptor ) );
|
||||
assertSame( sqlTypeDescriptor, getResolvedSqlTypeDescriptor( sqlTypeDescriptor ) );
|
||||
|
||||
// no override; (ClobTypeDescriptor.DEFAULT is overridden
|
||||
// if Dialect.useInputStreamToInsertBlob() is true)
|
||||
assertFalse( StandardBasicTypes.isStandardBasicSqlTypeDescriptor( ClobTypeDescriptor.CLOB_BINDING ) );
|
||||
assertSame( ClobTypeDescriptor.CLOB_BINDING, getResolvedSqlTypeDescriptor( ClobTypeDescriptor.CLOB_BINDING ) );
|
||||
}
|
||||
|
||||
public void testDialectWithNonStandardSqlTypeDescriptor() {
|
||||
assertNotSame( VarcharTypeDescriptor.INSTANCE, StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor() );
|
||||
if ( H2DialectOverridePrefixedVarcharSqlTypeDesc.class.isInstance( getDialect() ) ) {
|
||||
// TODO: dialect is currently a global; how can this be tested in the testsuite?
|
||||
assertSame(
|
||||
VarcharTypeDescriptor.INSTANCE,
|
||||
getResolvedSqlTypeDescriptor( StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor() )
|
||||
);
|
||||
}
|
||||
else {
|
||||
assertSame(
|
||||
StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor(),
|
||||
getResolvedSqlTypeDescriptor( StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor() )
|
||||
);
|
||||
}
|
||||
|
||||
if ( H2DialectOverrideVarcharSqlCode.class.isInstance( getDialect() ) ) {
|
||||
// TODO: dialect is currently a global; how can this be tested in the testsuite?
|
||||
assertSame(
|
||||
StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor(),
|
||||
getResolvedSqlTypeDescriptor( VarcharTypeDescriptor.INSTANCE )
|
||||
);
|
||||
}
|
||||
else {
|
||||
assertSame(
|
||||
VarcharTypeDescriptor.INSTANCE,
|
||||
getResolvedSqlTypeDescriptor( VarcharTypeDescriptor.INSTANCE )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private SqlTypeDescriptor getResolvedSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
return ( ( SessionFactoryImplementor ) getSessions() )
|
||||
.getTypeResolver()
|
||||
.resolveSqlTypeDescriptor( sqlTypeDescriptor );
|
||||
}
|
||||
|
||||
public void testInsert() {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
Entity e = new Entity( "name" );
|
||||
s.save( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
e = ( Entity ) s.get( Entity.class, e.getId() );
|
||||
assertFalse( e.getName().startsWith( StoredPrefixedStringType.PREFIX ) );
|
||||
assertEquals( "name", e.getName() );
|
||||
s.delete( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
public void testRegisteredFunction() {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
Entity e = new Entity( "name " );
|
||||
s.save( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
e = ( Entity ) s.get( Entity.class, e.getId() );
|
||||
assertFalse( e.getName().startsWith( StoredPrefixedStringType.PREFIX ) );
|
||||
assertEquals( "name ", e.getName() );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
String trimmedName = ( String ) s.createQuery( "select trim( TRAILING from e.name ) from Entity e" ).uniqueResult();
|
||||
// trim(...) is a "standard" DB function returning VarcharTypeDescriptor.INSTANCE,
|
||||
// so the prefix will not be removed unless
|
||||
// 1) getDialect().getSqlTypeDescriptorOverride( VarcharTypeDescriptor.INSTANCE )
|
||||
// returns StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor()
|
||||
// (H2DialectOverrideVarcharSqlCode does this)
|
||||
// or 2) getDialect().getSqlTypeDescriptorOverride( StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor() )
|
||||
// returns VarcharTypeDescriptor.INSTANCE
|
||||
// (H2DialectOverridePrefixedVarcharSqlTypeDesc does this)
|
||||
// TODO: dialect is currently a global; how can this be tested in the testsuite?
|
||||
assertNotSame( VarcharTypeDescriptor.INSTANCE, StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor() );
|
||||
if ( getDialect().resolveSqlTypeDescriptor( VarcharTypeDescriptor.INSTANCE ) ==
|
||||
StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor() ||
|
||||
getDialect().resolveSqlTypeDescriptor( StoredPrefixedStringType.INSTANCE.getSqlTypeDescriptor() ) ==
|
||||
VarcharTypeDescriptor.INSTANCE ) {
|
||||
assertFalse( trimmedName.startsWith( StoredPrefixedStringType.PREFIX ) );
|
||||
assertEquals( "name", trimmedName );
|
||||
}
|
||||
else {
|
||||
assertSame(
|
||||
VarcharTypeDescriptor.INSTANCE,
|
||||
( ( SessionFactoryImplementor ) getSessions() )
|
||||
.getTypeResolver()
|
||||
.resolveSqlTypeDescriptor( VarcharTypeDescriptor.INSTANCE )
|
||||
);
|
||||
assertTrue( trimmedName.startsWith( StoredPrefixedStringType.PREFIX ) );
|
||||
assertEquals( StoredPrefixedStringType.PREFIX + "name", trimmedName );
|
||||
}
|
||||
s.delete( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -36,8 +36,6 @@ import org.hibernate.type.descriptor.ValueBinder;
|
|||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.StringTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
|
||||
|
||||
/**
|
||||
* TODO : javadoc
|
||||
|
@ -48,7 +46,7 @@ public class StringValueMappingTest extends TestCase {
|
|||
private final StringTypeDescriptor stringJavaDescriptor = new StringTypeDescriptor();
|
||||
|
||||
private final VarcharTypeDescriptor varcharSqlDescriptor = new VarcharTypeDescriptor();
|
||||
private final ClobTypeDescriptor clobSqlDescriptor = new ClobTypeDescriptor();
|
||||
private final ClobTypeDescriptor clobSqlDescriptor = ClobTypeDescriptor.DEFAULT;
|
||||
|
||||
private final WrapperOptions wrapperOptions = new WrapperOptions() {
|
||||
public boolean useStreamForLobBinding() {
|
||||
|
@ -58,6 +56,10 @@ public class StringValueMappingTest extends TestCase {
|
|||
public LobCreator getLobCreator() {
|
||||
return NonContextualLobCreator.INSTANCE;
|
||||
}
|
||||
|
||||
public SqlTypeDescriptor resolveSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
return sqlTypeDescriptor;
|
||||
}
|
||||
};
|
||||
|
||||
public static final String COLUMN_NAME = "n/a";
|
||||
|
|
Loading…
Reference in New Issue