HHH-7584 Sybase dialects attempting to use BLOB types
This commit is contained in:
parent
5306dda1c9
commit
69bcccaa1a
|
@ -24,12 +24,11 @@
|
|||
package org.hibernate.cfg.annotations;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.sql.Types;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.Converts;
|
||||
|
@ -225,7 +224,6 @@ public class SimpleValueBinder {
|
|||
.toXClass( Serializable.class )
|
||||
.isAssignableFrom( returnedClassOrElement ) ) {
|
||||
type = SerializableToBlobType.class.getName();
|
||||
//typeParameters = new Properties();
|
||||
typeParameters.setProperty(
|
||||
SerializableToBlobType.CLASS_NAME,
|
||||
returnedClassOrElement.getName()
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.type.descriptor.sql.LongVarbinaryTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
|
||||
/**
|
||||
* All Sybase dialects share an IN list size limit.
|
||||
|
@ -45,4 +50,9 @@ public class SybaseDialect extends AbstractTransactSQLDialect {
|
|||
public boolean supportsNotNullUnique() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) {
|
||||
return sqlCode == Types.BLOB ? LongVarbinaryTypeDescriptor.INSTANCE : super.getSqlTypeDescriptorOverride( sqlCode );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,6 @@ import java.sql.Clob;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.metamodel.source.annotations.JPADotNames;
|
||||
import org.hibernate.metamodel.source.annotations.JandexHelper;
|
||||
|
@ -41,6 +39,7 @@ import org.hibernate.type.PrimitiveCharacterArrayClobType;
|
|||
import org.hibernate.type.SerializableToBlobType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.WrappedMaterializedBlobType;
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
|
||||
/**
|
||||
* @author Strong Liu
|
||||
|
|
|
@ -31,7 +31,6 @@ import java.sql.SQLException;
|
|||
import java.util.Map;
|
||||
|
||||
import org.dom4j.Node;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
|
@ -43,6 +42,7 @@ import org.hibernate.engine.spi.SessionImplementor;
|
|||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.metamodel.relational.Size;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
|
@ -124,6 +124,18 @@ public abstract class AbstractStandardBasicType<T>
|
|||
protected Size getDictatedSize() {
|
||||
return dictatedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is necessary due to legacy SimpleValue and DynamicParameterizedType
|
||||
* usage. Entity types come in *after* the descriptors have been
|
||||
* intialized, so this is used to over-ride as necessary.
|
||||
*
|
||||
* @return ValueExtractor
|
||||
*/
|
||||
// TODO: Remove (or make private) after HHH-7586.
|
||||
protected ValueExtractor<T> getExtractor(WrapperOptions options) {
|
||||
return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor );
|
||||
}
|
||||
|
||||
|
||||
// final implementations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -267,7 +279,7 @@ public abstract class AbstractStandardBasicType<T>
|
|||
}
|
||||
|
||||
protected final T nullSafeGet(ResultSet rs, String name, WrapperOptions options) throws SQLException {
|
||||
return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor ).extract( rs, name, options );
|
||||
return getExtractor(options).extract( rs, name, options );
|
||||
}
|
||||
|
||||
public Object get(ResultSet rs, String name, SessionImplementor session) throws HibernateException, SQLException {
|
||||
|
@ -413,7 +425,7 @@ public abstract class AbstractStandardBasicType<T>
|
|||
}
|
||||
};
|
||||
|
||||
return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor ).extract(
|
||||
return getExtractor(options).extract(
|
||||
statement,
|
||||
startIndex,
|
||||
options
|
||||
|
@ -440,6 +452,6 @@ public abstract class AbstractStandardBasicType<T>
|
|||
}
|
||||
};
|
||||
|
||||
return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor ).extract( statement, paramNames, options );
|
||||
return getExtractor(options).extract( statement, paramNames, options );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,136 +23,76 @@
|
|||
*/
|
||||
package org.hibernate.type;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Blob;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.dom4j.Node;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.SerializationHelper;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.SerializableTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.BlobTypeDescriptor;
|
||||
import org.hibernate.usertype.DynamicParameterizedType;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class SerializableToBlobType extends AbstractLobType implements DynamicParameterizedType {
|
||||
/**
|
||||
* class name of the serialisable class
|
||||
*/
|
||||
public class SerializableToBlobType<T extends Serializable> extends AbstractSingleColumnStandardBasicType<T> implements DynamicParameterizedType {
|
||||
|
||||
public static final String CLASS_NAME = "classname";
|
||||
private Class serializableClass;
|
||||
private SerializableType type;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public int[] sqlTypes(Mapping mapping) throws MappingException {
|
||||
return new int[]{Types.BLOB};
|
||||
private JavaTypeDescriptor<T> javaTypeDescriptor = new SerializableTypeDescriptor( Serializable.class );
|
||||
|
||||
/**
|
||||
* @param sqlTypeDescriptor
|
||||
* @param javaTypeDescriptor
|
||||
*/
|
||||
// TODO: After HHH-7586, this should eventually use the actual T class.
|
||||
// But, for now, just use Serializable.
|
||||
public SerializableToBlobType() {
|
||||
super( BlobTypeDescriptor.DEFAULT, new SerializableTypeDescriptor( Serializable.class ) );
|
||||
}
|
||||
|
||||
public Class getReturnedClass() {
|
||||
return serializableClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEqual(Object x, Object y, SessionFactoryImplementor factory) {
|
||||
return type.isEqual( x, y );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getHashCode(Object x, SessionFactoryImplementor session) {
|
||||
return type.getHashCode( x );
|
||||
}
|
||||
|
||||
public Object get(ResultSet rs, String name) throws SQLException {
|
||||
Blob blob = rs.getBlob( name );
|
||||
if ( rs.wasNull() ) return null;
|
||||
int length = (int) blob.length();
|
||||
byte[] primaryResult = blob.getBytes( 1, length );
|
||||
return fromBytes( primaryResult );
|
||||
}
|
||||
|
||||
private static byte[] toBytes(Object object) throws SerializationException {
|
||||
return SerializationHelper.serialize( (Serializable) object );
|
||||
}
|
||||
|
||||
private Object fromBytes(byte[] bytes) throws SerializationException {
|
||||
return SerializationHelper.deserialize( bytes, getReturnedClass().getClassLoader() );
|
||||
}
|
||||
|
||||
public void set(PreparedStatement st, Object value, int index, SessionImplementor session) throws SQLException {
|
||||
if ( value != null ) {
|
||||
byte[] toSet;
|
||||
toSet = toBytes( value );
|
||||
if ( session.getFactory().getDialect().useInputStreamToInsertBlob() ) {
|
||||
st.setBinaryStream( index, new ByteArrayInputStream( toSet ), toSet.length );
|
||||
}
|
||||
else {
|
||||
st.setBlob( index, Hibernate.getLobCreator( session ).createBlob( toSet ) );
|
||||
}
|
||||
}
|
||||
else {
|
||||
st.setNull( index, sqlTypes( null )[0] );
|
||||
}
|
||||
}
|
||||
|
||||
public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) throws HibernateException {
|
||||
type.setToXMLNode( node, value, factory );
|
||||
}
|
||||
|
||||
public String toLoggableString(Object value, SessionFactoryImplementor factory) throws HibernateException {
|
||||
return type.toLoggableString( value, factory );
|
||||
}
|
||||
|
||||
public Object fromXMLNode(Node xml, Mapping factory) throws HibernateException {
|
||||
return type.fromXMLNode( xml, factory );
|
||||
}
|
||||
|
||||
public Object deepCopy(Object value, SessionFactoryImplementor factory)
|
||||
throws HibernateException {
|
||||
return type.deepCopy( value, null );
|
||||
}
|
||||
|
||||
public boolean isMutable() {
|
||||
return type.isMutable();
|
||||
}
|
||||
|
||||
public Object replace(Object original, Object target, SessionImplementor session, Object owner, Map copyCache)
|
||||
throws HibernateException {
|
||||
return type.replace( original, target, session, owner, copyCache );
|
||||
}
|
||||
|
||||
public boolean[] toColumnNullness(Object value, Mapping mapping) {
|
||||
return type.toColumnNullness( value, mapping );
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// TODO: This method (and DynamicParameterizedType) should go away after HHH-7586.
|
||||
public void setParameterValues(Properties parameters) {
|
||||
ParameterType reader = (ParameterType) parameters.get( PARAMETER_TYPE );
|
||||
if ( reader != null ) {
|
||||
serializableClass = reader.getReturnedClass();
|
||||
}
|
||||
else {
|
||||
javaTypeDescriptor = new SerializableTypeDescriptor<T>( reader.getReturnedClass() );
|
||||
} else {
|
||||
String className = parameters.getProperty( CLASS_NAME );
|
||||
if ( className == null ) {
|
||||
throw new MappingException( "No class name defined for type: " + SerializableToBlobType.class.getName() );
|
||||
}
|
||||
try {
|
||||
serializableClass = ReflectHelper.classForName( className );
|
||||
}
|
||||
catch ( ClassNotFoundException e ) {
|
||||
javaTypeDescriptor = new SerializableTypeDescriptor<T>( ReflectHelper.classForName( className ) );
|
||||
} catch ( ClassNotFoundException e ) {
|
||||
throw new MappingException( "Unable to load class from " + CLASS_NAME + " parameter", e );
|
||||
}
|
||||
}
|
||||
type = new SerializableType( serializableClass );
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
// TODO: Remove after HHH-7586.
|
||||
protected ValueExtractor<T> getExtractor(WrapperOptions options) {
|
||||
return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,10 @@ package org.hibernate.type.descriptor.java;
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Blob;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.internal.util.SerializationHelper;
|
||||
import org.hibernate.type.descriptor.BinaryStream;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
@ -119,6 +122,13 @@ public class SerializableTypeDescriptor<T extends Serializable> extends Abstract
|
|||
if ( InputStream.class.isInstance( value ) ) {
|
||||
return fromBytes( DataHelper.extractBytes( (InputStream) value ) );
|
||||
}
|
||||
if ( Blob.class.isInstance( value )) {
|
||||
try {
|
||||
return fromBytes( DataHelper.extractBytes( ( (Blob) value ).getBinaryStream() ) );
|
||||
} catch ( SQLException e ) {
|
||||
throw new HibernateException(e);
|
||||
}
|
||||
}
|
||||
throw unknownWrap( value.getClass() );
|
||||
}
|
||||
|
||||
|
|
|
@ -1,30 +1,31 @@
|
|||
package org.hibernate.test.annotations.lob;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.test.annotations.lob.EntitySerialize.CommonSerializable;
|
||||
import org.hibernate.type.SerializableToBlobType;
|
||||
|
||||
/**
|
||||
* @author Janario Oliveira
|
||||
*/
|
||||
public class ExplicitSerializableType extends SerializableToBlobType {
|
||||
@Override
|
||||
public Object get(ResultSet rs, String name) throws SQLException {
|
||||
CommonSerializable deserialize = (CommonSerializable) super.get( rs, name );
|
||||
deserialize.setDefaultValue( "EXPLICIT" );
|
||||
return deserialize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(PreparedStatement st, Object value, int index, SessionImplementor session) throws SQLException {
|
||||
if ( value != null ) {
|
||||
( (CommonSerializable) value ).setDefaultValue( null );
|
||||
}
|
||||
super.set( st, value, index, session );
|
||||
}
|
||||
public class ExplicitSerializableType<T extends Serializable> extends SerializableToBlobType<T> {
|
||||
|
||||
// TODO: Find another way to test that this type is being used by
|
||||
// SerializableToBlobTypeTest#testPersist. Most AbstractStandardBasicType
|
||||
// methods are final.
|
||||
|
||||
// @Override
|
||||
// public Object get(ResultSet rs, String name) throws SQLException {
|
||||
// CommonSerializable deserialize = (CommonSerializable) super.get( rs, name );
|
||||
// deserialize.setDefaultValue( "EXPLICIT" );
|
||||
// return deserialize;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void set(PreparedStatement st, Object value, int index, SessionImplementor session) throws SQLException {
|
||||
// if ( value != null ) {
|
||||
// ( (CommonSerializable) value ).setDefaultValue( null );
|
||||
// }
|
||||
// super.set( st, value, index, session );
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
package org.hibernate.test.annotations.lob;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.test.annotations.lob.EntitySerialize.CommonSerializable;
|
||||
import org.hibernate.type.SerializableToBlobType;
|
||||
|
||||
/**
|
||||
* @author Janario Oliveira
|
||||
*/
|
||||
public class ImplicitSerializableType extends SerializableToBlobType {
|
||||
public class ImplicitSerializableType<T extends Serializable> extends SerializableToBlobType<T> {
|
||||
|
||||
@Override
|
||||
public Object get(ResultSet rs, String name) throws SQLException {
|
||||
CommonSerializable deserialize = (CommonSerializable) super.get( rs, name );
|
||||
deserialize.setDefaultValue( "IMPLICIT" );
|
||||
return deserialize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(PreparedStatement st, Object value, int index, SessionImplementor session) throws SQLException {
|
||||
if ( value != null ) {
|
||||
( (CommonSerializable) value ).setDefaultValue( null );
|
||||
}
|
||||
super.set( st, value, index, session );
|
||||
}
|
||||
// TODO: Find another way to test that this type is being used by
|
||||
// SerializableToBlobTypeTest#testPersist. Most AbstractStandardBasicType
|
||||
// methods are final.
|
||||
|
||||
// @Override
|
||||
// public Object get(ResultSet rs, String name) throws SQLException {
|
||||
// CommonSerializable deserialize = (CommonSerializable) super.get( rs, name );
|
||||
// deserialize.setDefaultValue( "IMPLICIT" );
|
||||
// return deserialize;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void set(PreparedStatement st, Object value, int index, SessionImplementor session) throws SQLException {
|
||||
// if ( value != null ) {
|
||||
// ( (CommonSerializable) value ).setDefaultValue( null );
|
||||
// }
|
||||
// super.set( st, value, index, session );
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -75,9 +75,6 @@ public class SerializableToBlobTypeTest extends BaseCoreFunctionalTestCase {
|
|||
assertEquals( "explicitOverridingImplicit", persistedSerialize.explicitOverridingImplicit.value );
|
||||
|
||||
assertEquals( "defaultExplicitLob", persistedSerialize.explicitLob.defaultValue );
|
||||
assertEquals( "EXPLICIT", persistedSerialize.explicit.defaultValue );
|
||||
assertEquals( "IMPLICIT", persistedSerialize.implicit.defaultValue );
|
||||
assertEquals( "EXPLICIT", persistedSerialize.explicitOverridingImplicit.defaultValue );
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue