HHH-7698 - In efficient LOB creations backed by streams

This commit is contained in:
Steve Ebersole 2012-10-19 17:28:46 -04:00 committed by brmeyer
parent e5d3b2b34c
commit d118c24776
31 changed files with 259 additions and 172 deletions

View File

@ -31,16 +31,12 @@ import java.sql.Clob;
* @author Steve Ebersole
*/
public abstract class AbstractLobCreator implements LobCreator {
/**
* {@inheritDoc}
*/
@Override
public Blob wrap(Blob blob) {
return SerializableBlobProxy.generateProxy( blob );
}
/**
* {@inheritDoc}
*/
@Override
public Clob wrap(Clob clob) {
if ( SerializableNClobProxy.isNClob( clob ) ) {
return SerializableNClobProxy.generateProxy( clob );

View File

@ -21,7 +21,8 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type.descriptor;
package org.hibernate.engine.jdbc;
import java.io.InputStream;
/**
@ -49,5 +50,10 @@ public interface BinaryStream {
*
* @return The input stream length
*/
public int getLength();
public long getLength();
/**
* Release any underlying resources.
*/
public void release();
}

View File

@ -23,11 +23,16 @@
*/
package org.hibernate.engine.jdbc;
/**
* Marker interface for non-contextually created {@link java.sql.Blob} instances..
*
* @author Steve Ebersole
*/
public interface BlobImplementer {
/**
* Gets access to the data underlying this BLOB.
*
* @return Access to the underlying data.
*/
public BinaryStream getUnderlyingStream();
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
@ -30,12 +31,12 @@ import java.lang.reflect.Proxy;
import java.sql.Blob;
import java.sql.SQLException;
import org.hibernate.type.descriptor.java.BinaryStreamImpl;
import org.hibernate.engine.jdbc.internal.BinaryStreamImpl;
import org.hibernate.type.descriptor.java.DataHelper;
/**
* Manages aspects of proxying {@link Blob Blobs} for non-contextual creation, including proxy creation and
* handling proxy invocations.
* Manages aspects of proxying {@link Blob} references for non-contextual creation, including proxy creation and
* handling proxy invocations. We use proxies here solely to avoid JDBC version incompatibilities.
*
* @author Gavin King
* @author Steve Ebersole
@ -44,8 +45,7 @@ import org.hibernate.type.descriptor.java.DataHelper;
public class BlobProxy implements InvocationHandler {
private static final Class[] PROXY_INTERFACES = new Class[] { Blob.class, BlobImplementer.class };
private InputStream stream;
private long length;
private BinaryStream binaryStream;
private boolean needsReset = false;
/**
@ -55,8 +55,7 @@ public class BlobProxy implements InvocationHandler {
* @see #generateProxy(byte[])
*/
private BlobProxy(byte[] bytes) {
this.stream = new BinaryStreamImpl( bytes );
this.length = bytes.length;
binaryStream = new BinaryStreamImpl( bytes );
}
/**
@ -67,17 +66,17 @@ public class BlobProxy implements InvocationHandler {
* @see #generateProxy(java.io.InputStream, long)
*/
private BlobProxy(InputStream stream, long length) {
this.stream = stream;
this.length = length;
this.binaryStream = new StreamBackedBinaryStream( stream, length );
}
private long getLength() {
return length;
return binaryStream.getLength();
}
private InputStream getStream() throws SQLException {
InputStream stream = binaryStream.getInputStream();
try {
if (needsReset) {
if ( needsReset ) {
stream.reset();
}
}
@ -94,6 +93,7 @@ public class BlobProxy implements InvocationHandler {
* @throws UnsupportedOperationException if any methods other than {@link Blob#length()}
* or {@link Blob#getBinaryStream} are invoked.
*/
@Override
@SuppressWarnings({ "UnnecessaryBoxing" })
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final String methodName = method.getName();
@ -102,6 +102,9 @@ public class BlobProxy implements InvocationHandler {
if ( "length".equals( methodName ) && argCount == 0 ) {
return Long.valueOf( getLength() );
}
if ( "getUnderlyingStream".equals( methodName ) ) {
return binaryStream;
}
if ( "getBinaryStream".equals( methodName ) ) {
if ( argCount == 0 ) {
return getStream();
@ -137,7 +140,7 @@ public class BlobProxy implements InvocationHandler {
}
}
if ( "free".equals( methodName ) && argCount == 0 ) {
stream.close();
binaryStream.release();
return null;
}
if ( "toString".equals( methodName ) && argCount == 0 ) {
@ -197,4 +200,43 @@ public class BlobProxy implements InvocationHandler {
}
return cl;
}
private static class StreamBackedBinaryStream implements BinaryStream {
private final InputStream stream;
private final long length;
private byte[] bytes;
private StreamBackedBinaryStream(InputStream stream, long length) {
this.stream = stream;
this.length = length;
}
@Override
public InputStream getInputStream() {
return stream;
}
@Override
public byte[] getBytes() {
if ( bytes == null ) {
bytes = DataHelper.extractBytes( stream );
}
return bytes;
}
@Override
public long getLength() {
return (int) length;
}
@Override
public void release() {
try {
stream.close();
}
catch (IOException ignore) {
}
}
}
}

View File

@ -21,7 +21,9 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type.descriptor;
package org.hibernate.engine.jdbc;
import java.io.InputStream;
import java.io.Reader;
/**
@ -32,17 +34,28 @@ import java.io.Reader;
*/
public interface CharacterStream {
/**
* Retrieve the reader.
* Provides access to the underlying data as a Reader.
*
* @return The reader.
*/
public Reader getReader();
public Reader asReader();
/**
* Retrieve the number of characters. JDBC 3 and earlier defined the length in terms of int type rather than
* long type :(
* Provides access to the underlying data as a String.
*
* @return The underlying String data
*/
public String asString();
/**
* Retrieve the number of characters.
*
* @return The number of characters.
*/
public int getLength();
public long getLength();
/**
* Release any underlying resources.
*/
public void release();
}

View File

@ -23,11 +23,16 @@
*/
package org.hibernate.engine.jdbc;
/**
* Marker interface for non-contextually created {@link java.sql.Clob} instances..
*
* @author Steve Ebersole
*/
public interface ClobImplementer {
/**
* Gets access to the data underlying this CLOB.
*
* @return Access to the underlying data.
*/
public CharacterStream getUnderlyingStream();
}

View File

@ -33,11 +33,12 @@ import java.lang.reflect.Proxy;
import java.sql.Clob;
import java.sql.SQLException;
import org.hibernate.engine.jdbc.internal.CharacterStreamImpl;
import org.hibernate.type.descriptor.java.DataHelper;
/**
* Manages aspects of proxying {@link Clob Clobs} for non-contextual creation, including proxy creation and
* handling proxy invocations.
* handling proxy invocations. We use proxies here solely to avoid JDBC version incompatibilities.
*
* @author Gavin King
* @author Steve Ebersole
@ -46,12 +47,9 @@ import org.hibernate.type.descriptor.java.DataHelper;
public class ClobProxy implements InvocationHandler {
private static final Class[] PROXY_INTERFACES = new Class[] { Clob.class, ClobImplementer.class };
private String string;
private Reader reader;
private long length;
private final CharacterStream characterStream;
private boolean needsReset = false;
/**
* Constructor used to build {@link Clob} from string data.
*
@ -59,9 +57,7 @@ public class ClobProxy implements InvocationHandler {
* @see #generateProxy(String)
*/
protected ClobProxy(String string) {
this.string = string;
reader = new StringReader(string);
length = string.length();
this.characterStream = new CharacterStreamImpl( string );
}
/**
@ -72,28 +68,25 @@ public class ClobProxy implements InvocationHandler {
* @see #generateProxy(java.io.Reader, long)
*/
protected ClobProxy(Reader reader, long length) {
this.reader = reader;
this.length = length;
this.characterStream = new CharacterStreamImpl( reader, length );
}
protected long getLength() {
return length;
return characterStream.getLength();
}
protected InputStream getAsciiStream() throws SQLException {
resetIfNeeded();
return new ReaderInputStream( reader );
return new ReaderInputStream( characterStream.asReader() );
}
protected Reader getCharacterStream() throws SQLException {
resetIfNeeded();
return reader;
return characterStream.asReader();
}
protected String getSubString(long start, int length) {
if ( string == null ) {
throw new UnsupportedOperationException( "Clob was not created from string; cannot substring" );
}
final String string = characterStream.asString();
// semi-naive implementation
int endIndex = Math.min( ((int)start)+length, string.length() );
return string.substring( (int)start, endIndex );
@ -105,6 +98,7 @@ public class ClobProxy implements InvocationHandler {
* @throws UnsupportedOperationException if any methods other than {@link Clob#length()},
* {@link Clob#getAsciiStream()}, or {@link Clob#getCharacterStream()} are invoked.
*/
@Override
@SuppressWarnings({ "UnnecessaryBoxing" })
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final String methodName = method.getName();
@ -113,6 +107,9 @@ public class ClobProxy implements InvocationHandler {
if ( "length".equals( methodName ) && argCount == 0 ) {
return Long.valueOf( getLength() );
}
if ( "getUnderlyingStream".equals( methodName ) ) {
return characterStream;
}
if ( "getAsciiStream".equals( methodName ) && argCount == 0 ) {
return getAsciiStream();
}
@ -152,7 +149,7 @@ public class ClobProxy implements InvocationHandler {
return getSubString( start-1, length );
}
if ( "free".equals( methodName ) && argCount == 0 ) {
reader.close();
characterStream.release();
return null;
}
if ( "toString".equals( methodName ) && argCount == 0 ) {
@ -171,7 +168,7 @@ public class ClobProxy implements InvocationHandler {
protected void resetIfNeeded() throws SQLException {
try {
if ( needsReset ) {
reader.reset();
characterStream.asReader().reset();
}
}
catch ( IOException ioe ) {

View File

@ -59,9 +59,7 @@ public class ContextualLobCreator extends AbstractLobCreator implements LobCreat
return lobCreationContext.execute( CREATE_BLOB_CALLBACK );
}
/**
* {@inheritDoc}
*/
@Override
public Blob createBlob(byte[] bytes) {
try {
Blob blob = createBlob();
@ -73,25 +71,11 @@ public class ContextualLobCreator extends AbstractLobCreator implements LobCreat
}
}
/**
* {@inheritDoc}
*/
@Override
public Blob createBlob(InputStream inputStream, long length) {
try {
Blob blob = createBlob();
OutputStream byteStream = blob.setBinaryStream( 1 );
StreamUtils.copy( inputStream, byteStream );
byteStream.flush();
byteStream.close();
// todo : validate length written versus length given?
return blob;
}
catch ( SQLException e ) {
throw new JDBCException( "Unable to prepare BLOB binary stream for writing",e );
}
catch ( IOException e ) {
throw new HibernateException( "Unable to write stream contents to BLOB", e );
}
// IMPL NOTE : it is inefficient to use JDBC LOB locator creation to create a LOB
// backed by a given stream. So just wrap the stream (which is what the NonContextualLobCreator does).
return NonContextualLobCreator.INSTANCE.createBlob( inputStream, length );
}
/**
@ -103,9 +87,7 @@ public class ContextualLobCreator extends AbstractLobCreator implements LobCreat
return lobCreationContext.execute( CREATE_CLOB_CALLBACK );
}
/**
* {@inheritDoc}
*/
@Override
public Clob createClob(String string) {
try {
Clob clob = createClob();
@ -117,24 +99,11 @@ public class ContextualLobCreator extends AbstractLobCreator implements LobCreat
}
}
/**
* {@inheritDoc}
*/
@Override
public Clob createClob(Reader reader, long length) {
try {
Clob clob = createClob();
Writer writer = clob.setCharacterStream( 1 );
StreamUtils.copy( reader, writer );
writer.flush();
writer.close();
return clob;
}
catch ( SQLException e ) {
throw new JDBCException( "Unable to prepare CLOB stream for writing", e );
}
catch ( IOException e ) {
throw new HibernateException( "Unable to write CLOB stream content", e );
}
// IMPL NOTE : it is inefficient to use JDBC LOB locator creation to create a LOB
// backed by a given stream. So just wrap the stream (which is what the NonContextualLobCreator does).
return NonContextualLobCreator.INSTANCE.createClob( reader, length );
}
/**
@ -146,9 +115,7 @@ public class ContextualLobCreator extends AbstractLobCreator implements LobCreat
return lobCreationContext.execute( CREATE_NCLOB_CALLBACK );
}
/**
* {@inheritDoc}
*/
@Override
public NClob createNClob(String string) {
try {
NClob nclob = createNClob();
@ -160,24 +127,11 @@ public class ContextualLobCreator extends AbstractLobCreator implements LobCreat
}
}
/**
* {@inheritDoc}
*/
@Override
public NClob createNClob(Reader reader, long length) {
try {
NClob nclob = createNClob();
Writer writer = nclob.setCharacterStream( 1 );
StreamUtils.copy( reader, writer );
writer.flush();
writer.close();
return nclob;
}
catch ( SQLException e ) {
throw new JDBCException( "Unable to prepare NCLOB stream for writing", e );
}
catch ( IOException e ) {
throw new HibernateException( "Unable to write NCLOB stream content", e );
}
// IMPL NOTE : it is inefficient to use JDBC LOB locator creation to create a LOB
// backed by a given stream. So just wrap the stream (which is what the NonContextualLobCreator does).
return NonContextualLobCreator.INSTANCE.createNClob( reader, length );
}
public static final LobCreationContext.Callback<Blob> CREATE_BLOB_CALLBACK = new LobCreationContext.Callback<Blob>() {

View File

@ -30,8 +30,6 @@ import java.sql.NClob;
/**
* Contract for creating various LOB references.
*
* @todo LobCreator really needs to be an api since we expose it to users.
*
* @author Steve Ebersole
* @author Gail Badner

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc;
import java.io.Reader;
import java.lang.reflect.Proxy;
import java.sql.Clob;
@ -29,10 +30,10 @@ import java.sql.NClob;
/**
* Manages aspects of proxying java.sql.NClobs for non-contextual creation, including proxy creation and
* handling proxy invocations.
* handling proxy invocations. We use proxies here solely to avoid JDBC version incompatibilities.
* <p/>
* Generated proxies are typed as {@link java.sql.Clob} (java.sql.NClob extends {@link java.sql.Clob}) and in JDK 1.6 environments, they
* are also typed to java.sql.NClob
* Generated proxies are typed as {@link java.sql.Clob} (java.sql.NClob extends {@link java.sql.Clob})
* and in JDK 1.6+ environments, they are also typed to java.sql.NClob
*
* @author Steve Ebersole
*/

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc;
import java.io.InputStream;
import java.io.Reader;
import java.sql.Blob;
@ -41,44 +42,32 @@ public class NonContextualLobCreator extends AbstractLobCreator implements LobCr
private NonContextualLobCreator() {
}
/**
* {@inheritDoc}
*/
@Override
public Blob createBlob(byte[] bytes) {
return BlobProxy.generateProxy( bytes );
}
/**
* {@inheritDoc}
*/
@Override
public Blob createBlob(InputStream stream, long length) {
return BlobProxy.generateProxy( stream, length );
}
/**
* {@inheritDoc}
*/
@Override
public Clob createClob(String string) {
return ClobProxy.generateProxy( string );
}
/**
* {@inheritDoc}
*/
@Override
public Clob createClob(Reader reader, long length) {
return ClobProxy.generateProxy( reader, length );
}
/**
* {@inheritDoc}
*/
@Override
public NClob createNClob(String string) {
return NClobProxy.generateProxy( string );
}
/**
* {@inheritDoc}
*/
@Override
public NClob createNClob(Reader reader, long length) {
return NClobProxy.generateProxy( reader, length );
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 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 Middleware LLC.
* 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
@ -20,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.engine.jdbc;
import java.io.IOException;
@ -42,5 +41,4 @@ public class ReaderInputStream extends InputStream {
public int read() throws IOException {
return reader.read();
}
}

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@ -62,9 +63,7 @@ public class SerializableBlobProxy implements InvocationHandler, Serializable {
}
}
/**
* {@inheritDoc}
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ( "getWrappedBlob".equals( method.getName() ) ) {
return getWrappedBlob();

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@ -62,9 +63,7 @@ public class SerializableClobProxy implements InvocationHandler, Serializable {
}
}
/**
* {@inheritDoc}
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ( "getWrappedClob".equals( method.getName() ) ) {
return getWrappedClob();

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc;
import java.lang.reflect.Proxy;
import java.sql.Clob;

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc;
import java.sql.Blob;
/**

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc;
import java.sql.Clob;
/**

View File

@ -21,12 +21,13 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type.descriptor.java;
package org.hibernate.engine.jdbc.internal;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.hibernate.type.descriptor.BinaryStream;
import org.hibernate.engine.jdbc.BinaryStream;
/**
* Implementation of {@link BinaryStream}
@ -50,7 +51,16 @@ public class BinaryStreamImpl extends ByteArrayInputStream implements BinaryStre
return buf;
}
public int getLength() {
public long getLength() {
return length;
}
@Override
public void release() {
try {
super.close();
}
catch (IOException ignore) {
}
}
}

View File

@ -21,12 +21,15 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type.descriptor.java;
package org.hibernate.engine.jdbc.internal;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import org.hibernate.type.descriptor.CharacterStream;
import org.hibernate.engine.jdbc.CharacterStream;
import org.hibernate.type.descriptor.java.DataHelper;
/**
* Implementation of {@link CharacterStream}
@ -34,19 +37,51 @@ import org.hibernate.type.descriptor.CharacterStream;
* @author Steve Ebersole
*/
public class CharacterStreamImpl implements CharacterStream {
private final StringReader reader;
private final int length;
private final long length;
private Reader reader;
private String string;
public CharacterStreamImpl(String chars) {
reader = new StringReader( chars );
length = chars.length();
this.string = chars;
this.length = chars.length();
}
public Reader getReader() {
public CharacterStreamImpl(Reader reader, long length) {
this.reader = reader;
this.length = length;
}
@Override
public Reader asReader() {
if ( reader == null ) {
reader = new StringReader( string );
}
return reader;
}
public int getLength() {
@Override
public String asString() {
if ( string == null ) {
string = DataHelper.extractString( reader );
}
return string;
}
@Override
public long getLength() {
return length;
}
@Override
public void release() {
if ( reader == null ) {
return;
}
try {
reader.close();
}
catch (IOException ignore) {
}
}
}

View File

@ -31,9 +31,11 @@ import java.sql.SQLException;
import java.util.Comparator;
import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.BlobImplementer;
import org.hibernate.engine.jdbc.BlobProxy;
import org.hibernate.engine.jdbc.WrappedBlob;
import org.hibernate.type.descriptor.BinaryStream;
import org.hibernate.engine.jdbc.BinaryStream;
import org.hibernate.engine.jdbc.internal.BinaryStreamImpl;
import org.hibernate.type.descriptor.WrapperOptions;
/**
@ -117,16 +119,33 @@ public class BlobTypeDescriptor extends AbstractTypeDescriptor<Blob> {
try {
if ( BinaryStream.class.isAssignableFrom( type ) ) {
return (X) new BinaryStreamImpl( DataHelper.extractBytes( value.getBinaryStream() ) );
} else if ( byte[].class.isAssignableFrom( type )) {
return (X) DataHelper.extractBytes( value.getBinaryStream() );
} else if (Blob.class.isAssignableFrom( type )) {
if ( BlobImplementer.class.isInstance( value ) ) {
// if the incoming Blob is a wrapper, just pass along its BinaryStream
return (X) ( (BlobImplementer) value ).getUnderlyingStream();
}
else {
// otherwise we need to build a BinaryStream...
return (X) new BinaryStreamImpl( DataHelper.extractBytes( value.getBinaryStream() ) );
}
}
else if ( byte[].class.isAssignableFrom( type )) {
if ( BlobImplementer.class.isInstance( value ) ) {
// if the incoming Blob is a wrapper, just grab the bytes from its BinaryStream
return (X) ( (BlobImplementer) value ).getUnderlyingStream().getBytes();
}
else {
// otherwise extract the bytes from the stream manually
return (X) DataHelper.extractBytes( value.getBinaryStream() );
}
}
else if (Blob.class.isAssignableFrom( type )) {
final Blob blob = WrappedBlob.class.isInstance( value )
? ( (WrappedBlob) value ).getWrappedBlob()
: value;
return (X) blob;
}
} catch ( SQLException e ) {
}
catch ( SQLException e ) {
throw new HibernateException( "Unable to access blob stream", e );
}
@ -142,9 +161,11 @@ public class BlobTypeDescriptor extends AbstractTypeDescriptor<Blob> {
// 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() ) ) {
}
else if ( byte[].class.isAssignableFrom( value.getClass() ) ) {
return options.getLobCreator().createBlob( ( byte[] ) value);
} else if ( InputStream.class.isAssignableFrom( value.getClass() ) ) {
}
else if ( InputStream.class.isAssignableFrom( value.getClass() ) ) {
InputStream inputStream = ( InputStream ) value;
try {
return options.getLobCreator().createBlob( inputStream, inputStream.available() );
@ -154,7 +175,6 @@ public class BlobTypeDescriptor extends AbstractTypeDescriptor<Blob> {
}
}
throw unknownWrap( value.getClass() );
}
}

View File

@ -29,7 +29,8 @@ import java.sql.Blob;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.type.descriptor.BinaryStream;
import org.hibernate.engine.jdbc.BinaryStream;
import org.hibernate.engine.jdbc.internal.BinaryStreamImpl;
import org.hibernate.type.descriptor.WrapperOptions;
/**

View File

@ -28,7 +28,8 @@ import java.io.StringReader;
import java.sql.Clob;
import java.util.Arrays;
import org.hibernate.type.descriptor.CharacterStream;
import org.hibernate.engine.jdbc.CharacterStream;
import org.hibernate.engine.jdbc.internal.CharacterStreamImpl;
import org.hibernate.type.descriptor.WrapperOptions;
/**

View File

@ -27,9 +27,11 @@ import java.io.Serializable;
import java.sql.Clob;
import java.util.Comparator;
import org.hibernate.engine.jdbc.ClobImplementer;
import org.hibernate.engine.jdbc.ClobProxy;
import org.hibernate.engine.jdbc.WrappedClob;
import org.hibernate.type.descriptor.CharacterStream;
import org.hibernate.engine.jdbc.CharacterStream;
import org.hibernate.engine.jdbc.internal.CharacterStreamImpl;
import org.hibernate.type.descriptor.WrapperOptions;
/**
@ -102,7 +104,14 @@ public class ClobTypeDescriptor extends AbstractTypeDescriptor<Clob> {
}
if ( CharacterStream.class.isAssignableFrom( type ) ) {
return (X) new CharacterStreamImpl( DataHelper.extractString( value ) );
if ( ClobImplementer.class.isInstance( value ) ) {
// if the incoming Clob is a wrapper, just pass along its CharacterStream
return (X) ( (ClobImplementer) value ).getUnderlyingStream();
}
else {
// otherwise we need to build one...
return (X) new CharacterStreamImpl( DataHelper.extractString( value ) );
}
}
final Clob clob = WrappedClob.class.isInstance( value )

View File

@ -34,8 +34,9 @@ import java.sql.SQLException;
import org.jboss.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.internal.BinaryStreamImpl;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.type.descriptor.BinaryStream;
import org.hibernate.engine.jdbc.BinaryStream;
/**
* A help for dealing with BLOB and CLOB data

View File

@ -30,7 +30,8 @@ import java.sql.SQLException;
import java.util.Arrays;
import org.hibernate.HibernateException;
import org.hibernate.type.descriptor.BinaryStream;
import org.hibernate.engine.jdbc.BinaryStream;
import org.hibernate.engine.jdbc.internal.BinaryStreamImpl;
import org.hibernate.type.descriptor.WrapperOptions;
/**

View File

@ -28,7 +28,8 @@ import java.io.StringReader;
import java.sql.Clob;
import java.util.Arrays;
import org.hibernate.type.descriptor.CharacterStream;
import org.hibernate.engine.jdbc.CharacterStream;
import org.hibernate.engine.jdbc.internal.CharacterStreamImpl;
import org.hibernate.type.descriptor.WrapperOptions;
/**

View File

@ -30,8 +30,9 @@ import java.sql.Blob;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.internal.BinaryStreamImpl;
import org.hibernate.internal.util.SerializationHelper;
import org.hibernate.type.descriptor.BinaryStream;
import org.hibernate.engine.jdbc.BinaryStream;
import org.hibernate.type.descriptor.WrapperOptions;
/**

View File

@ -27,7 +27,8 @@ import java.io.Reader;
import java.io.StringReader;
import java.sql.Clob;
import org.hibernate.type.descriptor.CharacterStream;
import org.hibernate.engine.jdbc.CharacterStream;
import org.hibernate.engine.jdbc.internal.CharacterStreamImpl;
import org.hibernate.type.descriptor.WrapperOptions;
/**

View File

@ -29,7 +29,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.type.descriptor.BinaryStream;
import org.hibernate.engine.jdbc.BinaryStream;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;

View File

@ -29,7 +29,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.type.descriptor.CharacterStream;
import org.hibernate.engine.jdbc.CharacterStream;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
@ -80,7 +80,7 @@ public abstract class ClobTypeDescriptor implements SqlTypeDescriptor {
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() );
st.setCharacterStream( index, characterStream.asReader(), characterStream.getLength() );
}
};
}