Browse files

HHH-7586 Re-architect Type or TypeFactory dynamic descriptors

  • Loading branch information...
1 parent 7ce0764 commit 04ed36bf0a4efab3fb56004b3b0202757b280a46 brmeyer committed Sep 11, 2012
View
10 hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java
@@ -39,9 +39,6 @@
import java.util.Properties;
import java.util.Set;
-import org.hibernate.engine.spi.RowSelection;
-import org.jboss.logging.Logger;
-
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
@@ -62,6 +59,7 @@
import org.hibernate.dialect.pagination.LegacyLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.engine.jdbc.LobCreator;
+import org.hibernate.engine.spi.RowSelection;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.exception.spi.ConversionContext;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
@@ -83,9 +81,9 @@
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.jboss.logging.Logger;
/**
* Represents a dialect of SQL implemented by a particular RDBMS.
@@ -378,10 +376,6 @@ public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescrip
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;
View
3 hibernate-core/src/main/java/org/hibernate/dialect/SybaseDialect.java
@@ -25,6 +25,7 @@
import java.sql.Types;
+import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
import org.hibernate.type.descriptor.sql.LongVarbinaryTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
@@ -53,6 +54,6 @@ public boolean supportsNotNullUnique() {
@Override
protected SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) {
- return sqlCode == Types.BLOB ? LongVarbinaryTypeDescriptor.INSTANCE : super.getSqlTypeDescriptorOverride( sqlCode );
+ return sqlCode == Types.BLOB ? BlobTypeDescriptor.PRIMITIVE_ARRAY_BINDING : super.getSqlTypeDescriptorOverride( sqlCode );
}
}
View
72 hibernate-core/src/main/java/org/hibernate/type/AbstractStandardBasicType.java
@@ -51,6 +51,7 @@
* Convenience base class for {@link BasicType} implementations
*
* @author Steve Ebersole
+ * @author Brett Meyer
*/
public abstract class AbstractStandardBasicType<T>
implements BasicType, StringRepresentableType<T>, XmlRepresentableType<T>, ProcedureParameterExtractionAware<T> {
@@ -253,24 +254,7 @@ public final Object nullSafeGet(ResultSet rs, String name, SessionImplementor se
}
public final T nullSafeGet(ResultSet rs, String name, final SessionImplementor session) throws SQLException {
- // todo : have SessionImplementor extend WrapperOptions
- final WrapperOptions options = new WrapperOptions() {
- public boolean useStreamForLobBinding() {
- return Environment.useStreamsForBinary();
- }
-
- public LobCreator getLobCreator() {
- return Hibernate.getLobCreator( session );
- }
-
- public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
- final SqlTypeDescriptor remapped = sqlTypeDescriptor.canBeRemapped()
- ? session.getFactory().getDialect().remapSqlTypeDescriptor( sqlTypeDescriptor )
- : sqlTypeDescriptor;
- return remapped == null ? sqlTypeDescriptor : remapped;
- }
- };
-
+ final WrapperOptions options = getOptions(session);
return nullSafeGet( rs, name, options );
}
@@ -288,24 +272,7 @@ public final void nullSafeSet(
Object value,
int index,
final SessionImplementor session) throws SQLException {
- // todo : have SessionImplementor extend WrapperOptions
- final WrapperOptions options = new WrapperOptions() {
- public boolean useStreamForLobBinding() {
- return Environment.useStreamsForBinary();
- }
-
- public LobCreator getLobCreator() {
- return Hibernate.getLobCreator( session );
- }
-
- public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
- final SqlTypeDescriptor remapped = sqlTypeDescriptor.canBeRemapped()
- ? session.getFactory().getDialect().remapSqlTypeDescriptor( sqlTypeDescriptor )
- : sqlTypeDescriptor;
- return remapped == null ? sqlTypeDescriptor : remapped;
- }
- };
-
+ final WrapperOptions options = getOptions(session);
nullSafeSet( st, value, index, options );
}
@@ -403,24 +370,7 @@ public boolean canDoExtraction() {
@Override
public T extract(CallableStatement statement, int startIndex, final SessionImplementor session) throws SQLException {
- // todo : have SessionImplementor extend WrapperOptions
- final WrapperOptions options = new WrapperOptions() {
- public boolean useStreamForLobBinding() {
- return Environment.useStreamsForBinary();
- }
-
- public LobCreator getLobCreator() {
- return Hibernate.getLobCreator( session );
- }
-
- public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
- final SqlTypeDescriptor remapped = sqlTypeDescriptor.canBeRemapped()
- ? session.getFactory().getDialect().remapSqlTypeDescriptor( sqlTypeDescriptor )
- : sqlTypeDescriptor;
- return remapped == null ? sqlTypeDescriptor : remapped;
- }
- };
-
+ final WrapperOptions options = getOptions(session);
return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor ).extract(
statement,
startIndex,
@@ -430,10 +380,16 @@ public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescrip
@Override
public T extract(CallableStatement statement, String[] paramNames, final SessionImplementor session) throws SQLException {
- // todo : have SessionImplementor extend WrapperOptions
- final WrapperOptions options = new WrapperOptions() {
+ final WrapperOptions options = getOptions(session);
+ return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor ).extract( statement, paramNames, options );
+ }
+
+ // TODO : have SessionImplementor extend WrapperOptions
+ private WrapperOptions getOptions(final SessionImplementor session) {
+ return new WrapperOptions() {
public boolean useStreamForLobBinding() {
- return Environment.useStreamsForBinary();
+ return Environment.useStreamsForBinary()
+ || session.getFactory().getDialect().useInputStreamToInsertBlob();
}
public LobCreator getLobCreator() {
@@ -447,7 +403,5 @@ public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescrip
return remapped == null ? sqlTypeDescriptor : remapped;
}
};
-
- return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor ).extract( statement, paramNames, options );
}
}
View
22 hibernate-core/src/main/java/org/hibernate/type/descriptor/java/BlobTypeDescriptor.java
@@ -23,6 +23,8 @@
*/
package org.hibernate.type.descriptor.java;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.Serializable;
import java.sql.Blob;
import java.sql.SQLException;
@@ -41,6 +43,7 @@
* treat them as immutable because we cannot properly check them for changes nor deep copy them.
*
* @author Steve Ebersole
+ * @author Brett Meyer
*/
public class BlobTypeDescriptor extends AbstractTypeDescriptor<Blob> {
public static final BlobTypeDescriptor INSTANCE = new BlobTypeDescriptor();
@@ -136,10 +139,23 @@ public boolean areEqual(Blob one, Blob another) {
return null;
}
- if ( ! Blob.class.isAssignableFrom( value.getClass() ) ) {
- throw unknownWrap( value.getClass() );
+ // Support multiple return types from
+ // org.hibernate.type.descriptor.sql.BlobTypeDescriptor
+ if ( Blob.class.isAssignableFrom( value.getClass() ) ) {
+ return options.getLobCreator().wrap( (Blob) value );
+ } else if ( byte[].class.isAssignableFrom( value.getClass() ) ) {
+ return options.getLobCreator().createBlob( ( byte[] ) value);
+ } else if ( InputStream.class.isAssignableFrom( value.getClass() ) ) {
+ InputStream inputStream = ( InputStream ) value;
+ try {
+ return options.getLobCreator().createBlob( inputStream, inputStream.available() );
+ }
+ catch ( IOException e ) {
+ throw unknownWrap( value.getClass() );
+ }
}
- return options.getLobCreator().wrap( (Blob) value );
+
+ throw unknownWrap( value.getClass() );
}
}
View
117 hibernate-core/src/main/java/org/hibernate/type/descriptor/sql/BlobTypeDescriptor.java
@@ -31,7 +31,6 @@
import java.sql.Types;
import org.hibernate.type.descriptor.BinaryStream;
-import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@@ -56,24 +55,11 @@ public boolean canBeRemapped() {
return true;
}
+ protected abstract <X> BasicExtractor<X> getBlobExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor);
+
@Override
- 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 {
- return javaTypeDescriptor.wrap( rs.getBlob( name ), options );
- }
-
- @Override
- protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
- return javaTypeDescriptor.wrap( statement.getBlob( index ), options );
- }
-
- @Override
- protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
- return javaTypeDescriptor.wrap( statement.getBlob( name ), options );
- }
- };
+ public <X> BasicExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
+ return getBlobExtractor( javaTypeDescriptor );
}
protected abstract <X> BasicBinder<X> getBlobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor);
@@ -93,16 +79,39 @@ protected X doExtract(CallableStatement statement, String name, WrapperOptions o
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
+ BlobTypeDescriptor descriptor = BLOB_BINDING;
if ( options.useStreamForLobBinding() ) {
- STREAM_BINDING.getBlobBinder( javaTypeDescriptor ).doBind( st, value, index, options );
+ descriptor = STREAM_BINDING;
}
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 );
+ descriptor = PRIMITIVE_ARRAY_BINDING;
}
+ descriptor.getBlobBinder( javaTypeDescriptor ).doBind( st, value, index, options );
+ }
+ };
+ }
+
+ @Override
+ public <X> BasicExtractor<X> getBlobExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
+ return new BasicExtractor<X>( javaTypeDescriptor, this ) {
+ // For now, default to using getBlob. If extraction
+ // should also check useStreamForLobBinding, add
+ // checks here and use STREAM_BINDING.
+
+ @Override
+ protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
+ return BLOB_BINDING.getExtractor( javaTypeDescriptor ).doExtract( rs, name, options );
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
+ return BLOB_BINDING.getExtractor( javaTypeDescriptor ).doExtract( statement, index, options );
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
+ return BLOB_BINDING.getExtractor( javaTypeDescriptor ).doExtract( statement, name, options );
}
};
}
@@ -120,6 +129,26 @@ public void doBind(PreparedStatement st, X value, int index, WrapperOptions opti
}
};
}
+
+ @Override
+ public <X> BasicExtractor<X> getBlobExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
+ return new BasicExtractor<X>( javaTypeDescriptor, this ) {
+ @Override
+ protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
+ return javaTypeDescriptor.wrap( rs.getBytes( name ), options );
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
+ return javaTypeDescriptor.wrap( statement.getBytes( index ), options );
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
+ return javaTypeDescriptor.wrap( statement.getBytes( name ), options );
+ }
+ };
+ }
};
public static final BlobTypeDescriptor BLOB_BINDING =
@@ -134,6 +163,26 @@ protected void doBind(PreparedStatement st, X value, int index, WrapperOptions o
}
};
}
+
+ @Override
+ public <X> BasicExtractor<X> getBlobExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
+ return new BasicExtractor<X>( javaTypeDescriptor, this ) {
+ @Override
+ protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
+ return javaTypeDescriptor.wrap( rs.getBlob( name ), options );
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
+ return javaTypeDescriptor.wrap( statement.getBlob( index ), options );
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
+ return javaTypeDescriptor.wrap( statement.getBlob( name ), options );
+ }
+ };
+ }
};
public static final BlobTypeDescriptor STREAM_BINDING =
@@ -149,6 +198,28 @@ protected void doBind(PreparedStatement st, X value, int index, WrapperOptions o
}
};
}
+
+ @Override
+ public <X> BasicExtractor<X> getBlobExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
+ return new BasicExtractor<X>( javaTypeDescriptor, this ) {
+ @Override
+ protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
+ return javaTypeDescriptor.wrap( rs.getBinaryStream( name ), options );
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
+ // TODO: CallableStatement does not have getBinaryStream
+ return javaTypeDescriptor.wrap( statement.getBytes( index ), options );
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
+ // TODO: CallableStatement does not have getBinaryStream
+ return javaTypeDescriptor.wrap( statement.getBytes( name ), options );
+ }
+ };
+ }
};
}
View
23 hibernate-core/src/test/java/org/hibernate/test/typeoverride/TypeOverrideTest.java
@@ -23,25 +23,25 @@
*/
package org.hibernate.test.typeoverride;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SybaseASE15Dialect;
+import org.hibernate.dialect.SybaseDialect;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
import org.hibernate.type.descriptor.sql.IntegerTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertSame;
+import org.junit.Test;
/**
* @author Gail Badner
@@ -62,17 +62,16 @@ public void testStandardBasicSqlTypeDescriptor() {
// no override
assertSame( IntegerTypeDescriptor.INSTANCE, remapSqlTypeDescriptor( IntegerTypeDescriptor.INSTANCE ) );
- // override depends on Dialect.useInputStreamToInsertBlob();
- // Postgresql explicitly overrides BlobTypeDescriptor.DEFAULT
- if ( getDialect().useInputStreamToInsertBlob() ) {
+ // A few dialects explicitly override BlobTypeDescriptor.DEFAULT
+ if ( PostgreSQL81Dialect.class.isInstance( getDialect() ) || PostgreSQLDialect.class.isInstance( getDialect() ) ) {
assertSame(
- BlobTypeDescriptor.STREAM_BINDING,
+ BlobTypeDescriptor.BLOB_BINDING,
getDialect().remapSqlTypeDescriptor( BlobTypeDescriptor.DEFAULT )
);
}
- else if ( PostgreSQL81Dialect.class.isInstance( getDialect() ) || PostgreSQLDialect.class.isInstance( getDialect() ) ) {
+ else if (SybaseDialect.class.isInstance( getDialect() )) {
assertSame(
- BlobTypeDescriptor.BLOB_BINDING,
+ BlobTypeDescriptor.PRIMITIVE_ARRAY_BINDING,
getDialect().remapSqlTypeDescriptor( BlobTypeDescriptor.DEFAULT )
);
}

0 comments on commit 04ed36b

Please sign in to comment.