HHH-5659 HHH-4617 : PostgreSQL and Oracle LOBs
This commit is contained in:
parent
600c29170a
commit
8e832d82a3
|
@ -42,9 +42,10 @@ import org.hibernate.engine.jdbc.LobCreator;
|
|||
import org.hibernate.engine.jdbc.StreamUtils;
|
||||
import org.hibernate.intercept.FieldInterceptionHelper;
|
||||
import org.hibernate.intercept.FieldInterceptor;
|
||||
import org.hibernate.mapping.ManyToOne;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
import org.hibernate.type.CharacterArrayClobType;
|
||||
import org.hibernate.type.MaterializedBlobType;
|
||||
import org.hibernate.type.AnyType;
|
||||
import org.hibernate.type.BigDecimalType;
|
||||
import org.hibernate.type.BigIntegerType;
|
||||
|
@ -66,6 +67,7 @@ import org.hibernate.type.LocaleType;
|
|||
import org.hibernate.type.LongType;
|
||||
import org.hibernate.type.ManyToOneType;
|
||||
import org.hibernate.type.ObjectType;
|
||||
import org.hibernate.type.PrimitiveCharacterArrayClobType;
|
||||
import org.hibernate.type.SerializableType;
|
||||
import org.hibernate.type.ShortType;
|
||||
import org.hibernate.type.StringType;
|
||||
|
@ -76,11 +78,11 @@ import org.hibernate.type.TimestampType;
|
|||
import org.hibernate.type.TrueFalseType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.TypeFactory;
|
||||
import org.hibernate.type.WrappedMaterializedBlobType;
|
||||
import org.hibernate.type.YesNoType;
|
||||
import org.hibernate.type.CharArrayType;
|
||||
import org.hibernate.type.WrapperBinaryType;
|
||||
import org.hibernate.type.CharacterArrayType;
|
||||
import org.hibernate.type.MaterializedBlobType;
|
||||
import org.hibernate.type.ImageType;
|
||||
import org.hibernate.type.MaterializedClobType;
|
||||
import org.hibernate.usertype.CompositeUserType;
|
||||
|
@ -236,6 +238,25 @@ public final class Hibernate {
|
|||
* @deprecated Use {@link org.hibernate.type.StandardBasicTypes#CLOB} instead.
|
||||
*/
|
||||
public static final ClobType CLOB = ClobType.INSTANCE;
|
||||
|
||||
/**
|
||||
* Hibernate <tt>wrapper_materialized_blob</tt> type.
|
||||
* @deprecated Use {@link org.hibernate.type.StandardBasicTypes#WRAPPER_MATERIALIZED_BLOB} instead.
|
||||
*/
|
||||
public static final WrappedMaterializedBlobType WRAPPER_MATERIALIZED_BLOB = WrappedMaterializedBlobType.INSTANCE;
|
||||
|
||||
/**
|
||||
* Hibernate <tt>wrapper_characters_clob</tt> type.
|
||||
* @deprecated Use {@link org.hibernate.type.StandardBasicTypes#WRAPPER_CHARACTERS_CLOB} instead.
|
||||
*/
|
||||
public static final CharacterArrayClobType WRAPPER_CHARACTERS_CLOB = CharacterArrayClobType.INSTANCE;
|
||||
|
||||
/**
|
||||
* Hibernate <tt>characters_clob</tt> type.
|
||||
* @deprecated Use {@link org.hibernate.type.StandardBasicTypes#CHARACTERS_CLOB} instead.
|
||||
*/
|
||||
public static final PrimitiveCharacterArrayClobType CHARACTERS_CLOB = PrimitiveCharacterArrayClobType.INSTANCE;
|
||||
|
||||
/**
|
||||
* Hibernate <tt>calendar</tt> type.
|
||||
* @deprecated Use {@link org.hibernate.type.StandardBasicTypes#CALENDAR} instead.
|
||||
|
|
|
@ -182,13 +182,13 @@ public class SimpleValueBinder {
|
|||
type = Hibernate.MATERIALIZED_CLOB.getName();
|
||||
}
|
||||
else if ( mappings.getReflectionManager().equals( returnedClassOrElement, Character.class ) && isArray ) {
|
||||
type = CharacterArrayClobType.class.getName();
|
||||
type = Hibernate.WRAPPER_CHARACTERS_CLOB.getName();
|
||||
}
|
||||
else if ( mappings.getReflectionManager().equals( returnedClassOrElement, char.class ) && isArray ) {
|
||||
type = PrimitiveCharacterArrayClobType.class.getName();
|
||||
type = Hibernate.CHARACTERS_CLOB.getName();
|
||||
}
|
||||
else if ( mappings.getReflectionManager().equals( returnedClassOrElement, Byte.class ) && isArray ) {
|
||||
type = WrappedMaterializedBlobType.class.getName();
|
||||
type = Hibernate.WRAPPER_MATERIALIZED_BLOB.getName();
|
||||
}
|
||||
else if ( mappings.getReflectionManager().equals( returnedClassOrElement, byte.class ) && isArray ) {
|
||||
type = Hibernate.MATERIALIZED_BLOB.getName();
|
||||
|
|
|
@ -27,8 +27,11 @@ import java.sql.CallableStatement;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
@ -66,7 +69,15 @@ import org.hibernate.sql.ANSIJoinFragment;
|
|||
import org.hibernate.sql.CaseFragment;
|
||||
import org.hibernate.sql.ForUpdateFragment;
|
||||
import org.hibernate.sql.JoinFragment;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.BlobType;
|
||||
import org.hibernate.type.CharacterArrayClobType;
|
||||
import org.hibernate.type.ClobType;
|
||||
import org.hibernate.type.MaterializedBlobType;
|
||||
import org.hibernate.type.MaterializedClobType;
|
||||
import org.hibernate.type.PrimitiveCharacterArrayClobType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.WrappedMaterializedBlobType;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
import org.hibernate.util.StringHelper;
|
||||
|
||||
|
@ -94,14 +105,30 @@ public abstract class Dialect {
|
|||
public static final String QUOTE = "`\"[";
|
||||
public static final String CLOSED_QUOTE = "`\"]";
|
||||
|
||||
private static final Set<BasicType> streamBindingLobTypes = new HashSet<BasicType>();
|
||||
|
||||
static {
|
||||
// Blobs
|
||||
streamBindingLobTypes.add( BlobType.INSTANCE.getAlternatives().getStreamBindingType() );
|
||||
streamBindingLobTypes.add( MaterializedBlobType.INSTANCE.getAlternatives().getStreamBindingType() );
|
||||
streamBindingLobTypes.add( WrappedMaterializedBlobType.INSTANCE.getAlternatives().getStreamBindingType() );
|
||||
// Clobs
|
||||
streamBindingLobTypes.add( ClobType.INSTANCE.getAlternatives().getStreamBindingType() );
|
||||
streamBindingLobTypes.add( MaterializedClobType.INSTANCE.getAlternatives().getStreamBindingType() );
|
||||
streamBindingLobTypes.add( CharacterArrayClobType.INSTANCE.getAlternatives().getStreamBindingType() );
|
||||
streamBindingLobTypes.add( PrimitiveCharacterArrayClobType.INSTANCE.getAlternatives().getStreamBindingType() );
|
||||
// TODO: shouldn't SerializableToBlobType be in this list???
|
||||
}
|
||||
|
||||
private final TypeNames typeNames = new TypeNames();
|
||||
private final TypeNames hibernateTypeNames = new TypeNames();
|
||||
|
||||
private final List<BasicType> dialectSpecificOverrides = new ArrayList<BasicType>();
|
||||
|
||||
private final Properties properties = new Properties();
|
||||
private final Map<String, SQLFunction> sqlFunctions = new HashMap<String, SQLFunction>();
|
||||
private final Set<String> sqlKeywords = new HashSet<String>();
|
||||
|
||||
|
||||
// constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
protected Dialect() {
|
||||
|
@ -210,6 +237,26 @@ public abstract class Dialect {
|
|||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve dialect-specific types for overriding "basic" types.
|
||||
* @return the dialect-specific types
|
||||
*/
|
||||
public final List<BasicType> getTypeOverrides() {
|
||||
List<BasicType> allOverrides = dialectSpecificOverrides;
|
||||
if ( useInputStreamToInsertBlob() ) {
|
||||
allOverrides = new ArrayList<BasicType>( streamBindingLobTypes.size() + dialectSpecificOverrides.size() );
|
||||
allOverrides.addAll( streamBindingLobTypes );
|
||||
allOverrides.addAll( dialectSpecificOverrides );
|
||||
}
|
||||
return Collections.unmodifiableList( allOverrides );
|
||||
}
|
||||
|
||||
protected final void addTypeOverride(BasicType typeOverride) {
|
||||
if ( typeOverride != null ) {
|
||||
dialectSpecificOverrides.add( typeOverride );
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.hibernate.exception.JDBCExceptionHelper;
|
|||
import org.hibernate.exception.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.id.SequenceGenerator;
|
||||
import org.hibernate.type.MaterializedBlobType;
|
||||
|
||||
/**
|
||||
* An SQL dialect for Postgres
|
||||
|
@ -143,6 +144,8 @@ public class PostgreSQLDialect extends Dialect {
|
|||
|
||||
registerFunction( "str", new SQLFunctionTemplate(Hibernate.STRING, "cast(?1 as varchar)") );
|
||||
|
||||
addTypeOverride( MaterializedBlobType.INSTANCE.getAlternatives().getLobBindingType() );
|
||||
|
||||
getDefaultProperties().setProperty(Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE);
|
||||
}
|
||||
|
||||
|
@ -364,8 +367,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* 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.type;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.InstantiationException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Provides alternative types for binding LOB values.
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public abstract class AlternativeLobTypes<S, T extends LobType<S>> implements Serializable {
|
||||
|
||||
private final T defaultType;
|
||||
private final T streamBindingType;
|
||||
private final T lobBindingType;
|
||||
|
||||
private AlternativeLobTypes(Class<? extends T> clazz,
|
||||
SqlTypeDescriptor defaultDescriptor,
|
||||
SqlTypeDescriptor streamBindingDescriptor,
|
||||
SqlTypeDescriptor lobBindingDescriptor) {
|
||||
Constructor constructor = getConstructor( clazz );
|
||||
defaultType = createLobType( clazz, constructor, defaultDescriptor );
|
||||
streamBindingType = createLobType( clazz, constructor, streamBindingDescriptor );
|
||||
lobBindingType = createLobType( clazz, constructor, lobBindingDescriptor );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type that uses the default binding LOB values.
|
||||
|
||||
* @return type that uses the default binding
|
||||
* @see BlobTypeDescriptor#DEFAULT
|
||||
* @see ClobTypeDescriptor#DEFAULT
|
||||
*/
|
||||
public final T getDefaultType() {
|
||||
return defaultType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type that binds LOB values using streams.
|
||||
*
|
||||
* @return type that binds using a stream
|
||||
*
|
||||
* @see BlobTypeDescriptor#STREAM_BINDING
|
||||
* @see ClobTypeDescriptor#STREAM_BINDING
|
||||
*/
|
||||
public final T getStreamBindingType() {
|
||||
return streamBindingType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type that explicitly binds the LOB value,
|
||||
|
||||
* @return type that binds the LOB
|
||||
* @see BlobTypeDescriptor#BLOB_BINDING
|
||||
* @see ClobTypeDescriptor#CLOB_BINDING
|
||||
*/
|
||||
public final T getLobBindingType() {
|
||||
return lobBindingType;
|
||||
}
|
||||
|
||||
protected Constructor getConstructor(Class<? extends T> clazz) {
|
||||
try {
|
||||
return clazz.getDeclaredConstructor( SqlTypeDescriptor.class, this.getClass() );
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
throw new HibernateException(
|
||||
"Could not get constructor for " +
|
||||
clazz.getClass().getName() +
|
||||
" with argument types: [" +
|
||||
SqlTypeDescriptor.class.getName() + ", " + this.getClass().getName() +
|
||||
"]", e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected T createLobType(Class<? extends T> lobTypeClass,
|
||||
Constructor constructor,
|
||||
SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
try {
|
||||
return lobTypeClass.cast( constructor.newInstance( sqlTypeDescriptor, this ) );
|
||||
}
|
||||
catch ( InstantiationException e ) {
|
||||
throw new HibernateException( "Cannot instantiate type: " + lobTypeClass.getName() );
|
||||
}
|
||||
catch ( IllegalAccessException e ) {
|
||||
throw new HibernateException( "IllegalAccessException trying to instantiate: " + lobTypeClass.getName() );
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new HibernateException( "Could not create type: " + lobTypeClass.getName(), e.getCause() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides alternative types for binding {@link java.sql.Types#CLOB CLOB} values.
|
||||
*/
|
||||
public static class ClobTypes<S, T extends LobType<S>> extends AlternativeLobTypes<S,T> {
|
||||
|
||||
/* package-protected */
|
||||
ClobTypes(Class<? extends T> clobTypeClass) {
|
||||
super(
|
||||
clobTypeClass,
|
||||
ClobTypeDescriptor.DEFAULT,
|
||||
ClobTypeDescriptor.STREAM_BINDING,
|
||||
ClobTypeDescriptor.CLOB_BINDING
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides alternative types for binding {@link java.sql.Types#BLOB BLOB} values.
|
||||
*/
|
||||
public static class BlobTypes<S, T extends LobType<S>> extends AlternativeLobTypes<S,T> {
|
||||
|
||||
private final T primitiveArrayBindingType;
|
||||
|
||||
/* package-protected */
|
||||
BlobTypes(Class<? extends T> blobTypeClass) {
|
||||
super(
|
||||
blobTypeClass,
|
||||
BlobTypeDescriptor.DEFAULT,
|
||||
BlobTypeDescriptor.STREAM_BINDING,
|
||||
BlobTypeDescriptor.BLOB_BINDING
|
||||
);
|
||||
Constructor constructor = getConstructor( blobTypeClass );
|
||||
primitiveArrayBindingType = createLobType(
|
||||
blobTypeClass, constructor, BlobTypeDescriptor.PRIMITIVE_ARRAY_BINDING
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type that explicitly binds the {@link java.sql.Types#BLOB BLOB} value,
|
||||
|
||||
* @return type that binds the {@link java.sql.Types#BLOB BLOB}
|
||||
* @see BlobTypeDescriptor#PRIMITIVE_ARRAY_BINDING
|
||||
*/
|
||||
public final T getPrimitiveArrayBindingType() {
|
||||
return primitiveArrayBindingType;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -88,8 +88,11 @@ public class BasicTypeRegistry implements Serializable {
|
|||
register( TextType.INSTANCE );
|
||||
register( BlobType.INSTANCE );
|
||||
register( MaterializedBlobType.INSTANCE );
|
||||
register( WrappedMaterializedBlobType.INSTANCE );
|
||||
register( ClobType.INSTANCE );
|
||||
register( MaterializedClobType.INSTANCE );
|
||||
register( CharacterArrayClobType.INSTANCE );
|
||||
register( PrimitiveCharacterArrayClobType.INSTANCE );
|
||||
register( SerializableType.INSTANCE );
|
||||
|
||||
register( ObjectType.INSTANCE );
|
||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.type;
|
|||
import java.sql.Blob;
|
||||
|
||||
import org.hibernate.type.descriptor.java.BlobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* A type that maps between {@link java.sql.Types#BLOB BLOB} and {@link Blob}
|
||||
|
@ -33,11 +34,20 @@ import org.hibernate.type.descriptor.java.BlobTypeDescriptor;
|
|||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BlobType extends AbstractSingleColumnStandardBasicType<Blob> {
|
||||
public class BlobType extends LobType<Blob> {
|
||||
|
||||
public static final BlobType INSTANCE = new BlobType();
|
||||
|
||||
public BlobType() {
|
||||
super( org.hibernate.type.descriptor.sql.BlobTypeDescriptor.INSTANCE, BlobTypeDescriptor.INSTANCE );
|
||||
this(
|
||||
org.hibernate.type.descriptor.sql.BlobTypeDescriptor.DEFAULT,
|
||||
new AlternativeLobTypes.BlobTypes<Blob,BlobType>( BlobType.class )
|
||||
);
|
||||
}
|
||||
|
||||
protected BlobType(SqlTypeDescriptor sqlTypeDescriptor,
|
||||
AlternativeLobTypes.BlobTypes<Blob,BlobType> blobTypes) {
|
||||
super( sqlTypeDescriptor, BlobTypeDescriptor.INSTANCE, blobTypes );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.type;
|
|||
|
||||
import org.hibernate.type.descriptor.java.CharacterArrayTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* A type that maps between {@link java.sql.Types#CLOB CLOB} and {@link Character Character[]}
|
||||
|
@ -34,16 +35,22 @@ import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
|||
* @author Emmanuel Bernard
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CharacterArrayClobType extends AbstractSingleColumnStandardBasicType<Character[]> {
|
||||
public class CharacterArrayClobType extends LobType<Character[]> {
|
||||
public static final CharacterArrayClobType INSTANCE = new CharacterArrayClobType();
|
||||
|
||||
public CharacterArrayClobType() {
|
||||
super( ClobTypeDescriptor.INSTANCE, CharacterArrayTypeDescriptor.INSTANCE );
|
||||
this(
|
||||
ClobTypeDescriptor.DEFAULT,
|
||||
new AlternativeLobTypes.ClobTypes<Character[],CharacterArrayClobType>( CharacterArrayClobType.class )
|
||||
);
|
||||
}
|
||||
|
||||
protected CharacterArrayClobType(SqlTypeDescriptor sqlTypeDescriptor,
|
||||
AlternativeLobTypes.ClobTypes<Character[],CharacterArrayClobType> clobTypes) {
|
||||
super( sqlTypeDescriptor, CharacterArrayTypeDescriptor.INSTANCE, clobTypes );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
// todo name these annotation types for addition to the registry
|
||||
return null;
|
||||
return "wrapper_characters_clob";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.type;
|
|||
import java.sql.Clob;
|
||||
|
||||
import org.hibernate.type.descriptor.java.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* A type that maps between {@link java.sql.Types#CLOB CLOB} and {@link Clob}
|
||||
|
@ -33,11 +34,20 @@ import org.hibernate.type.descriptor.java.ClobTypeDescriptor;
|
|||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ClobType extends AbstractSingleColumnStandardBasicType<Clob> {
|
||||
public class ClobType extends LobType<Clob> {
|
||||
|
||||
public static final ClobType INSTANCE = new ClobType();
|
||||
|
||||
public ClobType() {
|
||||
super( org.hibernate.type.descriptor.sql.ClobTypeDescriptor.INSTANCE, ClobTypeDescriptor.INSTANCE );
|
||||
this(
|
||||
org.hibernate.type.descriptor.sql.ClobTypeDescriptor.DEFAULT,
|
||||
new AlternativeLobTypes.ClobTypes<Clob,ClobType>( ClobType.class )
|
||||
);
|
||||
}
|
||||
|
||||
protected ClobType(SqlTypeDescriptor sqlTypeDescriptor,
|
||||
AlternativeLobTypes.ClobTypes<Clob,ClobType> clobTypes) {
|
||||
super( sqlTypeDescriptor, ClobTypeDescriptor.INSTANCE, clobTypes );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
@ -53,5 +63,4 @@ public class ClobType extends AbstractSingleColumnStandardBasicType<Clob> {
|
|||
protected Clob getReplacement(Clob original, Clob target) {
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, 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;
|
||||
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* A base type used to define a LOB type; it also provides
|
||||
* alternatives that can override this type via
|
||||
* {@link org.hibernate.type.LobType#getAlternatives()} getAlternatives()}
|
||||
*
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public abstract class LobType<T> extends AbstractSingleColumnStandardBasicType<T> {
|
||||
private AlternativeLobTypes alternativeLobTypes;
|
||||
|
||||
public LobType(SqlTypeDescriptor sqlTypeDescriptor,
|
||||
JavaTypeDescriptor<T> javaTypeDescriptor,
|
||||
AlternativeLobTypes alternativeLobTypes) {
|
||||
super( sqlTypeDescriptor, javaTypeDescriptor );
|
||||
this.alternativeLobTypes = alternativeLobTypes;
|
||||
}
|
||||
|
||||
public AlternativeLobTypes getAlternatives() {
|
||||
return alternativeLobTypes;
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ package org.hibernate.type;
|
|||
|
||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* A type that maps between {@link java.sql.Types#BLOB BLOB} and {@code byte[]}
|
||||
|
@ -34,11 +35,20 @@ import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
|
|||
* @author Gail Badner
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class MaterializedBlobType extends AbstractSingleColumnStandardBasicType<byte[]> {
|
||||
public class MaterializedBlobType extends LobType<byte[]> {
|
||||
|
||||
public static final MaterializedBlobType INSTANCE = new MaterializedBlobType();
|
||||
|
||||
public MaterializedBlobType() {
|
||||
super( BlobTypeDescriptor.INSTANCE, PrimitiveByteArrayTypeDescriptor.INSTANCE );
|
||||
this(
|
||||
BlobTypeDescriptor.DEFAULT,
|
||||
new AlternativeLobTypes.BlobTypes<byte[],MaterializedBlobType>( MaterializedBlobType.class )
|
||||
);
|
||||
}
|
||||
|
||||
protected MaterializedBlobType(SqlTypeDescriptor sqlTypeDescriptor,
|
||||
AlternativeLobTypes.BlobTypes<byte[],MaterializedBlobType> blobTypes) {
|
||||
super( sqlTypeDescriptor, PrimitiveByteArrayTypeDescriptor.INSTANCE, blobTypes );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.type;
|
|||
|
||||
import org.hibernate.type.descriptor.java.StringTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* A type that maps between {@link java.sql.Types#CLOB CLOB} and {@link String}
|
||||
|
@ -33,11 +34,19 @@ import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
|||
* @author Gail Badner
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class MaterializedClobType extends AbstractSingleColumnStandardBasicType<String> {
|
||||
public class MaterializedClobType extends LobType<String> {
|
||||
public static final MaterializedClobType INSTANCE = new MaterializedClobType();
|
||||
|
||||
public MaterializedClobType() {
|
||||
super( ClobTypeDescriptor.INSTANCE, StringTypeDescriptor.INSTANCE );
|
||||
this(
|
||||
ClobTypeDescriptor.DEFAULT,
|
||||
new AlternativeLobTypes.ClobTypes<String,MaterializedClobType>( MaterializedClobType.class )
|
||||
);
|
||||
}
|
||||
|
||||
protected MaterializedClobType(SqlTypeDescriptor sqlTypeDescriptor,
|
||||
AlternativeLobTypes.ClobTypes<String,MaterializedClobType> clobTypes) {
|
||||
super( sqlTypeDescriptor, StringTypeDescriptor.INSTANCE, clobTypes );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -25,21 +25,31 @@ package org.hibernate.type;
|
|||
|
||||
import org.hibernate.type.descriptor.java.PrimitiveCharacterArrayTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Map a char[] to a Clob
|
||||
*
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class PrimitiveCharacterArrayClobType extends AbstractSingleColumnStandardBasicType<char[]> {
|
||||
public static final CharacterArrayClobType INSTANCE = new CharacterArrayClobType();
|
||||
public class PrimitiveCharacterArrayClobType extends LobType<char[]> {
|
||||
public static final PrimitiveCharacterArrayClobType INSTANCE = new PrimitiveCharacterArrayClobType();
|
||||
|
||||
public PrimitiveCharacterArrayClobType() {
|
||||
super( ClobTypeDescriptor.INSTANCE, PrimitiveCharacterArrayTypeDescriptor.INSTANCE );
|
||||
this(
|
||||
ClobTypeDescriptor.DEFAULT,
|
||||
new AlternativeLobTypes.ClobTypes<char[],PrimitiveCharacterArrayClobType>(
|
||||
PrimitiveCharacterArrayClobType.class
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected PrimitiveCharacterArrayClobType(SqlTypeDescriptor sqlTypeDescriptor, AlternativeLobTypes.
|
||||
ClobTypes<char[],PrimitiveCharacterArrayClobType> clobTypes) {
|
||||
super( sqlTypeDescriptor, PrimitiveCharacterArrayTypeDescriptor.INSTANCE, clobTypes );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
// todo name these annotation types for addition to the registry
|
||||
return null;
|
||||
return "characters_clob";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -261,6 +261,12 @@ public class StandardBasicTypes {
|
|||
*/
|
||||
public static final MaterializedBlobType MATERIALIZED_BLOB = MaterializedBlobType.INSTANCE;
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@code Byte[]} to JDBC {@link java.sql.Types#BLOB BLOB}
|
||||
* @see WrappedMaterializedBlobType
|
||||
*/
|
||||
public static final WrappedMaterializedBlobType WRAPPER_MATERIALIZED_BLOB = WrappedMaterializedBlobType.INSTANCE;
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@code char[]} to JDBC {@link java.sql.Types#VARCHAR VARCHAR}.
|
||||
*
|
||||
|
@ -302,6 +308,18 @@ public class StandardBasicTypes {
|
|||
*/
|
||||
public static final MaterializedClobType MATERIALIZED_CLOB = MaterializedClobType.INSTANCE;
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Character[]} to JDBC {@link java.sql.Types#CLOB CLOB}.
|
||||
* @see CharacterArrayClobType
|
||||
*/
|
||||
public static final CharacterArrayClobType WRAPPER_CHARACTERS_CLOB = CharacterArrayClobType.INSTANCE;
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link Character[]} to JDBC {@link java.sql.Types#CLOB CLOB}.
|
||||
* @see PrimitiveCharacterArrayClobType
|
||||
*/
|
||||
public static final PrimitiveCharacterArrayClobType CHARACTERS_CLOB = PrimitiveCharacterArrayClobType.INSTANCE;
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.io.Serializable} to JDBC {@link java.sql.Types#VARBINARY VARBINARY}.
|
||||
* <p/>
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
package org.hibernate.type;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
|
@ -42,30 +44,65 @@ public class TypeResolver implements Serializable {
|
|||
private final BasicTypeRegistry basicTypeRegistry;
|
||||
private final TypeFactory typeFactory;
|
||||
|
||||
// Need to keep track of the "global" type overrides in case there are dialect-specific overrides.
|
||||
// Dialect-specific types must be applied before "global" overrides are applied.
|
||||
// Unfortunately, dialect-specific types are not known until this TypeResolver is scoped...
|
||||
private final List<BasicType> typeOverrides;
|
||||
|
||||
// If this TypeResolver is scoped to a SessionFactoryImplementor with
|
||||
// dialect-specific type overrides, scopedTypeRegistry will be initialized,
|
||||
// dialect-specific type overrides will be applied, followed by "global"
|
||||
// type overrides.
|
||||
private BasicTypeRegistry scopedTypeRegistry;
|
||||
|
||||
public TypeResolver() {
|
||||
this( new BasicTypeRegistry(), new TypeFactory() );
|
||||
}
|
||||
|
||||
public TypeResolver(BasicTypeRegistry basicTypeRegistry, TypeFactory typeFactory) {
|
||||
this.basicTypeRegistry = basicTypeRegistry;
|
||||
this.typeOverrides = new ArrayList<BasicType>();
|
||||
this.typeFactory = typeFactory;
|
||||
}
|
||||
|
||||
public TypeResolver scope(SessionFactoryImplementor factory) {
|
||||
typeFactory.injectSessionFactory( factory );
|
||||
return new TypeResolver( basicTypeRegistry.shallowCopy(), typeFactory );
|
||||
// if there was a scopedTypeRegistry left from the last time this
|
||||
// TypeResolver was scoped, then set it to null;
|
||||
scopedTypeRegistry = null;
|
||||
BasicTypeRegistry registry = basicTypeRegistry;
|
||||
List<BasicType> dialectTypeOverrides = factory.getDialect().getTypeOverrides();
|
||||
if ( factory != null && ! dialectTypeOverrides.isEmpty() ) {
|
||||
// scoping to a factory with dialect-specific type overrides;
|
||||
// create a new scopedTypeRegistry and override dialect-specific types
|
||||
// before overriding the "global" type overrides;
|
||||
scopedTypeRegistry = new BasicTypeRegistry();
|
||||
registerTypeOverrides( scopedTypeRegistry, dialectTypeOverrides );
|
||||
registerTypeOverrides( scopedTypeRegistry, typeOverrides );
|
||||
registry = scopedTypeRegistry;
|
||||
}
|
||||
return new TypeResolver( registry.shallowCopy(), typeFactory );
|
||||
}
|
||||
|
||||
public void registerTypeOverride(BasicType type) {
|
||||
basicTypeRegistry.register( type );
|
||||
typeOverrides.add( type );
|
||||
}
|
||||
|
||||
public void registerTypeOverride(UserType type, String[] keys) {
|
||||
basicTypeRegistry.register( type, keys );
|
||||
typeOverrides.add( new CustomType( type, keys ) );
|
||||
}
|
||||
|
||||
public void registerTypeOverride(CompositeUserType type, String[] keys) {
|
||||
basicTypeRegistry.register( type, keys );
|
||||
typeOverrides.add( new CompositeCustomType( type, keys ) );
|
||||
}
|
||||
|
||||
private static void registerTypeOverrides(BasicTypeRegistry typeRegistry, List<BasicType> typeOverrides) {
|
||||
for ( BasicType typeOverride : typeOverrides ) {
|
||||
typeRegistry.register( typeOverride );
|
||||
}
|
||||
}
|
||||
|
||||
public TypeFactory getTypeFactory() {
|
||||
|
@ -73,14 +110,17 @@ public class TypeResolver implements Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Locate a Hibernate {@linkplain BasicType basic type} given (one of) its registration names.
|
||||
* Locate a Hibernate {@linkplain BasicType basic type} given (one of) its registration names;
|
||||
* if scoped to a {@link SessionFactoryImplementor}, the scoped type is returned.
|
||||
*
|
||||
* @param name The registration name
|
||||
*
|
||||
* @return The registered type
|
||||
*/
|
||||
public BasicType basic(String name) {
|
||||
return basicTypeRegistry.getRegisteredType( name );
|
||||
return scopedTypeRegistry == null ?
|
||||
basicTypeRegistry.getRegisteredType( name ) :
|
||||
scopedTypeRegistry.getRegisteredType( name );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.type;
|
|||
|
||||
import org.hibernate.type.descriptor.java.ByteArrayTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* A type that maps JDBC {@link java.sql.Types#BLOB BLOB} and {@code Byte[]}.
|
||||
|
@ -32,15 +33,25 @@ import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
|
|||
*
|
||||
* @author Strong Liu
|
||||
*/
|
||||
public class WrappedMaterializedBlobType extends AbstractSingleColumnStandardBasicType<Byte[]> {
|
||||
public class WrappedMaterializedBlobType extends LobType<Byte[]> {
|
||||
|
||||
public static final WrappedMaterializedBlobType INSTANCE = new WrappedMaterializedBlobType();
|
||||
|
||||
public WrappedMaterializedBlobType() {
|
||||
super( BlobTypeDescriptor.INSTANCE, ByteArrayTypeDescriptor.INSTANCE );
|
||||
this(
|
||||
BlobTypeDescriptor.DEFAULT,
|
||||
new AlternativeLobTypes.BlobTypes<Byte[],WrappedMaterializedBlobType>(
|
||||
WrappedMaterializedBlobType.class
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected WrappedMaterializedBlobType(SqlTypeDescriptor sqlTypeDescriptor,
|
||||
AlternativeLobTypes.BlobTypes<Byte[],WrappedMaterializedBlobType> clobTypes) {
|
||||
super( sqlTypeDescriptor, ByteArrayTypeDescriptor.INSTANCE, clobTypes );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
// todo name these annotation types for addition to the registry
|
||||
return null;
|
||||
return "wrapper_materialized_blob";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,12 +25,15 @@ package org.hibernate.type.descriptor.java;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.sql.SQLException;
|
||||
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.CharacterStream;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
/**
|
||||
|
@ -107,7 +110,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 +118,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,73 @@ 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, ( byte[] ) value );
|
||||
}
|
||||
};
|
||||
}
|
||||
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 +116,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
|
||||
|
|
|
@ -48,7 +48,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() {
|
||||
|
|
|
@ -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;
|
||||
|
@ -56,7 +56,15 @@ public class MaterializedBlobTest extends TestCase {
|
|||
public void testTypeSelection() {
|
||||
int index = sfi().getEntityPersister( MaterializedBlobEntity.class.getName() ).getEntityMetamodel().getPropertyIndex( "theBytes" );
|
||||
Type type = sfi().getEntityPersister( MaterializedBlobEntity.class.getName() ).getEntityMetamodel().getProperties()[index].getType();
|
||||
assertEquals( MaterializedBlobType.INSTANCE, type );
|
||||
if ( PostgreSQLDialect.class.isInstance( getDialect() )) {
|
||||
assertEquals( MaterializedBlobType.INSTANCE.getAlternatives().getLobBindingType(), type );
|
||||
}
|
||||
else if ( getDialect().useInputStreamToInsertBlob() ) {
|
||||
assertEquals( MaterializedBlobType.INSTANCE.getAlternatives().getStreamBindingType(), type );
|
||||
}
|
||||
else {
|
||||
assertEquals( MaterializedBlobType.INSTANCE, type );
|
||||
}
|
||||
}
|
||||
|
||||
public void testSaving() {
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.dialect.Dialect;
|
|||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.testing.junit.functional.DatabaseSpecificFunctionalTestCase;
|
||||
import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
|
||||
import org.hibernate.type.descriptor.java.DataHelper;
|
||||
|
||||
/**
|
||||
* Tests lazy materialization of data mapped by
|
||||
|
@ -166,14 +167,7 @@ public class ClobLocatorTest extends DatabaseSpecificFunctionalTestCase {
|
|||
}
|
||||
|
||||
private String extractData(Clob clob) throws Throwable {
|
||||
if ( getDialect() instanceof H2Dialect ) {
|
||||
return clob.getSubString( 1, ( int ) clob.length() );
|
||||
}
|
||||
else {
|
||||
char[] data = new char[ (int) clob.length() ];
|
||||
clob.getCharacterStream().read( data );
|
||||
return new String( data );
|
||||
}
|
||||
return DataHelper.extractString( clob.getCharacterStream() );
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue