HHH-2412 - Support for JDBC4

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17767 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2009-10-15 16:26:26 +00:00
parent a000137e19
commit 36dbd3a06e
44 changed files with 2754 additions and 1329 deletions

View File

@ -34,11 +34,10 @@ import java.util.Map;
import org.dom4j.Node; import org.dom4j.Node;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.MappingException; import org.hibernate.Hibernate;
import org.hibernate.engine.Mapping; import org.hibernate.engine.Mapping;
import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor; import org.hibernate.engine.SessionImplementor;
import org.hibernate.lob.BlobImpl;
import org.hibernate.util.ArrayHelper; import org.hibernate.util.ArrayHelper;
/** /**
@ -51,9 +50,10 @@ import org.hibernate.util.ArrayHelper;
*/ */
@Deprecated @Deprecated
public class ByteArrayBlobType extends AbstractLobType { public class ByteArrayBlobType extends AbstractLobType {
private static final int[] TYPES = new int[] { Types.BLOB };
public int[] sqlTypes(Mapping mapping) throws MappingException { public int[] sqlTypes(Mapping mapping) {
return new int[]{Types.BLOB}; return TYPES;
} }
@Override @Override
@ -128,7 +128,7 @@ public class ByteArrayBlobType extends AbstractLobType {
st.setBinaryStream( index, new ByteArrayInputStream( toSet ), toSet.length ); st.setBinaryStream( index, new ByteArrayInputStream( toSet ), toSet.length );
} }
else { else {
st.setBlob( index, new BlobImpl( toSet ) ); st.setBlob( index, Hibernate.getLobCreator( session ).createBlob( toSet ) );
} }
} }
} }

View File

@ -37,10 +37,10 @@ import org.dom4j.Node;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.Hibernate;
import org.hibernate.engine.Mapping; import org.hibernate.engine.Mapping;
import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor; import org.hibernate.engine.SessionImplementor;
import org.hibernate.lob.BlobImpl;
import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.ParameterizedType;
import org.hibernate.util.ReflectHelper; import org.hibernate.util.ReflectHelper;
import org.hibernate.util.SerializationHelper; import org.hibernate.util.SerializationHelper;
@ -99,7 +99,7 @@ public class SerializableToBlobType extends AbstractLobType implements Parameter
st.setBinaryStream( index, new ByteArrayInputStream( toSet ), toSet.length ); st.setBinaryStream( index, new ByteArrayInputStream( toSet ), toSet.length );
} }
else { else {
st.setBlob( index, new BlobImpl( toSet ) ); st.setBlob( index, Hibernate.getLobCreator( session ).createBlob( toSet ) );
} }
} }
else { else {

View File

@ -28,6 +28,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.io.Serializable; import java.io.Serializable;
import java.io.ByteArrayOutputStream;
import java.sql.Blob; import java.sql.Blob;
import java.sql.Clob; import java.sql.Clob;
import java.util.Iterator; import java.util.Iterator;
@ -35,12 +36,13 @@ import java.util.Properties;
import org.hibernate.collection.PersistentCollection; import org.hibernate.collection.PersistentCollection;
import org.hibernate.engine.HibernateIterator; import org.hibernate.engine.HibernateIterator;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.StreamUtils;
import org.hibernate.intercept.FieldInterceptionHelper; import org.hibernate.intercept.FieldInterceptionHelper;
import org.hibernate.intercept.FieldInterceptor; import org.hibernate.intercept.FieldInterceptor;
import org.hibernate.lob.BlobImpl;
import org.hibernate.lob.ClobImpl;
import org.hibernate.lob.SerializableBlob;
import org.hibernate.lob.SerializableClob;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer; import org.hibernate.proxy.LazyInitializer;
import org.hibernate.type.AnyType; import org.hibernate.type.AnyType;
@ -386,54 +388,163 @@ public final class Hibernate {
} }
/** /**
* Create a new <tt>Blob</tt>. The returned object will be initially immutable. * Create a new {@link Blob}. The returned object will be initially immutable.
* *
* @param bytes a byte array * @param bytes a byte array
* @return the Blob * @return the Blob
* @deprecated Use {@link #createBlob(byte[], Session)} instead
*/ */
public static Blob createBlob(byte[] bytes) { public static Blob createBlob(byte[] bytes) {
return new SerializableBlob( new BlobImpl( bytes ) ); return NonContextualLobCreator.INSTANCE.wrap(
NonContextualLobCreator.INSTANCE.createBlob( bytes )
);
} }
/** /**
* Create a new <tt>Blob</tt>. The returned object will be initially immutable. * Create a new {@link Blob}.
*
* @param bytes a byte array
* @param session The session in which the {@link Blob} will be used.
* @return the Blob
*/
public static Blob createBlob(byte[] bytes, Session session) {
// todo : wrap?
return getLobCreator( session ).createBlob( bytes );
}
public static LobCreator getLobCreator(Session session) {
return getLobCreator( ( SessionImplementor ) session );
}
public static LobCreator getLobCreator(SessionImplementor session) {
return session.getFactory()
.getSettings()
.getJdbcSupport()
.getLobCreator( ( LobCreationContext ) session );
}
/**
* Create a new {@link Blob}. The returned object will be initially immutable.
* *
* @param stream a binary stream * @param stream a binary stream
* @param length the number of bytes in the stream * @param length the number of bytes in the stream
* @return the Blob * @return the Blob
* @deprecated Use {@link #createBlob(InputStream, long, Session)} instead
*/ */
public static Blob createBlob(InputStream stream, int length) { public static Blob createBlob(InputStream stream, int length) {
return new SerializableBlob( new BlobImpl( stream, length ) ); return NonContextualLobCreator.INSTANCE.wrap(
NonContextualLobCreator.INSTANCE.createBlob( stream, length )
);
} }
/** /**
* Create a new <tt>Blob</tt>. The returned object will be initially immutable. * Create a new {@link Blob}. The returned object will be initially immutable.
*
* @param stream a binary stream
* @param length the number of bytes in the stream
* @return the Blob
* @deprecated Use {@link #createBlob(InputStream, long, Session)} instead
*/
public static Blob createBlob(InputStream stream, long length) {
return NonContextualLobCreator.INSTANCE.wrap(
NonContextualLobCreator.INSTANCE.createBlob( stream, length )
);
}
/**
* Create a new {@link Blob}.
*
* @param stream a binary stream
* @param length the number of bytes in the stream
* @param session The session in which the {@link Blob} will be used.
* @return the Blob
*/
public static Blob createBlob(InputStream stream, long length, Session session) {
// todo : wrap?
return getLobCreator( session ).createBlob( stream, length );
}
/**
* Create a new {@link Blob}. The returned object will be initially immutable.
* <p/>
* NOTE: this method will read the entire contents of the incoming stream in order to properly
* handle the {@link Blob#length()} method. If you do not want the stream read, use the
* {@link #createBlob(InputStream,long)} version instead.
* *
* @param stream a binary stream * @param stream a binary stream
* @return the Blob * @return the Blob
* @throws IOException * @throws IOException Indicates an I/O problem accessing the stream
* @deprecated Use {@link #createBlob(InputStream, long, Session)} instead
*/ */
public static Blob createBlob(InputStream stream) throws IOException { public static Blob createBlob(InputStream stream) throws IOException {
return new SerializableBlob( new BlobImpl( stream, stream.available() ) ); ByteArrayOutputStream buffer = new ByteArrayOutputStream( stream.available() );
StreamUtils.copy( stream, buffer );
return createBlob( buffer.toByteArray() );
} }
/** /**
* Create a new <tt>Clob</tt>. The returned object will be initially immutable. * Create a new {@link Clob}. The returned object will be initially immutable.
* *
* @param string a <tt>String</tt> * @param string The string data
* @return The created {@link Clob}
* @deprecated Use {@link #createClob(String, Session)} instead
*/ */
public static Clob createClob(String string) { public static Clob createClob(String string) {
return new SerializableClob( new ClobImpl( string ) ); return NonContextualLobCreator.INSTANCE.wrap(
NonContextualLobCreator.INSTANCE.createClob( string )
);
} }
/** /**
* Create a new <tt>Clob</tt>. The returned object will be initially immutable. * Create a new {@link Clob}.
*
* @param string The string data
* @param session The session in which the {@link Clob} will be used.
* @return The created {@link Clob}
*/
public static Clob createClob(String string, Session session) {
// todo : wrap?
return getLobCreator( session ).createClob( string );
}
/**
* Create a new {@link Clob}. The returned object will be initially immutable.
* *
* @param reader a character stream * @param reader a character stream
* @param length the number of characters in the stream * @param length the number of characters in the stream
* @return The created {@link Clob}
* @deprecated Use {@link #createClob(Reader,long,Session)} instead
*/ */
public static Clob createClob(Reader reader, int length) { public static Clob createClob(Reader reader, int length) {
return new SerializableClob( new ClobImpl( reader, length ) ); return NonContextualLobCreator.INSTANCE.wrap(
NonContextualLobCreator.INSTANCE.createClob( reader, length )
);
}
/**
* Create a new {@link Clob}. The returned object will be initially immutable.
*
* @param reader a character stream
* @param length the number of characters in the stream
* @return The created {@link Clob}
* @deprecated Use {@link #createClob(Reader,long,Session)} instead
*/
public static Clob createClob(Reader reader, long length) {
return NonContextualLobCreator.INSTANCE.wrap(
NonContextualLobCreator.INSTANCE.createClob( reader, length )
);
}
/**
* Create a new {@link Clob}.
*
* @param reader a character stream
* @param length the number of characters in the stream
* @param session The session in which the {@link Clob} will be used.
* @return The created {@link Clob}
*/
public static Clob createClob(Reader reader, long length, Session session) {
return getLobCreator( session ).createClob( reader, length );
} }
/** /**
@ -460,8 +571,7 @@ public final class Hibernate {
* *
* @param proxy The potential proxy * @param proxy The potential proxy
* @param propertyName the name of a persistent attribute of the object * @param propertyName the name of a persistent attribute of the object
* @return true if the named property of the object is not listed as uninitialized * @return true if the named property of the object is not listed as uninitialized; false otherwise
* @return false if the object is an uninitialized proxy, or the named property is uninitialized
*/ */
public static boolean isPropertyInitialized(Object proxy, String propertyName) { public static boolean isPropertyInitialized(Object proxy, String propertyName) {

View File

@ -28,6 +28,7 @@ import java.util.Map;
import org.hibernate.ConnectionReleaseMode; import org.hibernate.ConnectionReleaseMode;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.engine.jdbc.JdbcSupport;
import org.hibernate.tuple.entity.EntityTuplizerFactory; import org.hibernate.tuple.entity.EntityTuplizerFactory;
import org.hibernate.tuple.component.ComponentTuplizerFactory; import org.hibernate.tuple.component.ComponentTuplizerFactory;
import org.hibernate.cache.QueryCacheFactory; import org.hibernate.cache.QueryCacheFactory;
@ -98,6 +99,7 @@ public final class Settings {
private boolean checkNullability; private boolean checkNullability;
// private ComponentTuplizerFactory componentTuplizerFactory; todo : HHH-3517 and HHH-1907 // private ComponentTuplizerFactory componentTuplizerFactory; todo : HHH-3517 and HHH-1907
// private BytecodeProvider bytecodeProvider; // private BytecodeProvider bytecodeProvider;
private JdbcSupport jdbcSupport;
/** /**
* Package protected constructor * Package protected constructor
@ -299,8 +301,12 @@ public final class Settings {
// return componentTuplizerFactory; // return componentTuplizerFactory;
// } // }
public JdbcSupport getJdbcSupport() {
return jdbcSupport;
}
// package protected setters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// package protected setters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// void setShowSqlEnabled(boolean b) { // void setShowSqlEnabled(boolean b) {
// showSql = b; // showSql = b;
@ -502,8 +508,11 @@ public final class Settings {
// this.componentTuplizerFactory = componentTuplizerFactory; // this.componentTuplizerFactory = componentTuplizerFactory;
// } // }
void setJdbcSupport(JdbcSupport jdbcSupport) {
this.jdbcSupport = jdbcSupport;
}
// public BytecodeProvider getBytecodeProvider() { // public BytecodeProvider getBytecodeProvider() {
// return bytecodeProvider; // return bytecodeProvider;
// } // }
// //

View File

@ -38,6 +38,8 @@ import org.slf4j.LoggerFactory;
import org.hibernate.ConnectionReleaseMode; import org.hibernate.ConnectionReleaseMode;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.JdbcSupport;
import org.hibernate.engine.jdbc.JdbcSupportLoader;
import org.hibernate.bytecode.BytecodeProvider; import org.hibernate.bytecode.BytecodeProvider;
import org.hibernate.cache.QueryCacheFactory; import org.hibernate.cache.QueryCacheFactory;
import org.hibernate.cache.RegionFactory; import org.hibernate.cache.RegionFactory;
@ -97,6 +99,7 @@ public class SettingsFactory implements Serializable {
boolean metaReportsDDLCausesTxnCommit = false; boolean metaReportsDDLCausesTxnCommit = false;
boolean metaReportsDDLInTxnSupported = true; boolean metaReportsDDLInTxnSupported = true;
Dialect dialect = null; Dialect dialect = null;
JdbcSupport jdbcSupport = null;
// 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value. // 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value.
// The need for it is intended to be alleviated with future developement, thus it is // The need for it is intended to be alleviated with future developement, thus it is
@ -115,6 +118,7 @@ public class SettingsFactory implements Serializable {
log.info( "JDBC driver: " + meta.getDriverName() + ", version: " + meta.getDriverVersion() ); log.info( "JDBC driver: " + meta.getDriverName() + ", version: " + meta.getDriverVersion() );
dialect = DialectFactory.buildDialect( props, conn ); dialect = DialectFactory.buildDialect( props, conn );
jdbcSupport = JdbcSupportLoader.loadJdbcSupport( conn );
metaSupportsScrollable = meta.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE ); metaSupportsScrollable = meta.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE );
metaSupportsBatchUpdates = meta.supportsBatchUpdates(); metaSupportsBatchUpdates = meta.supportsBatchUpdates();
@ -145,6 +149,10 @@ public class SettingsFactory implements Serializable {
settings.setDataDefinitionImplicitCommit( metaReportsDDLCausesTxnCommit ); settings.setDataDefinitionImplicitCommit( metaReportsDDLCausesTxnCommit );
settings.setDataDefinitionInTransactionSupported( metaReportsDDLInTxnSupported ); settings.setDataDefinitionInTransactionSupported( metaReportsDDLInTxnSupported );
settings.setDialect( dialect ); settings.setDialect( dialect );
if ( jdbcSupport == null ) {
jdbcSupport = JdbcSupportLoader.loadJdbcSupport( null );
}
settings.setJdbcSupport( jdbcSupport );
//use dialect default properties //use dialect default properties
final Properties properties = new Properties(); final Properties properties = new Properties();

View File

@ -0,0 +1,53 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.sql.Blob;
import java.sql.Clob;
/**
* Convenient base class for proxy-based LobCreator for handling wrapping.
*
* @author Steve Ebersole
*/
public abstract class AbstractLobCreator implements LobCreator {
/**
* {@inheritDoc}
*/
public Blob wrap(Blob blob) {
return SerializableBlobProxy.generateProxy( blob );
}
/**
* {@inheritDoc}
*/
public Clob wrap(Clob clob) {
if ( SerializableNClobProxy.isNClob( clob ) ) {
return SerializableNClobProxy.generateProxy( clob );
}
else {
return SerializableClobProxy.generateProxy( clob );
}
}
}

View File

@ -0,0 +1,32 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
/**
* Marker interface for non-contextually created {@link java.sql.Blob} instances..
*
* @author Steve Ebersole
*/
public interface BlobImplementer {
}

View File

@ -0,0 +1,154 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Blob;
import java.sql.SQLException;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
/**
* Manages aspects of proxying {@link Blob Blobs} for non-contextual creation, including proxy creation and
* handling proxy invocations.
*
* @author Gavin King
* @author Steve Ebersole
* @author Gail Badner
*/
public class BlobProxy implements InvocationHandler {
private static final Class[] PROXY_INTERFACES = new Class[] { Blob.class, BlobImplementer.class };
private InputStream stream;
private long length;
private boolean needsReset = false;
/**
* Ctor used to build {@link Blob} from byte array.
*
* @param bytes The byte array
* @see #generateProxy(byte[])
*/
private BlobProxy(byte[] bytes) {
this.stream = new ByteArrayInputStream( bytes );
this.length = bytes.length;
}
/**
* Ctor used to build {@link Blob} from a stream.
*
* @param stream The binary stream
* @param length The length of the stream
* @see #generateProxy(java.io.InputStream, long)
*/
private BlobProxy(InputStream stream, long length) {
this.stream = stream;
this.length = length;
}
private long getLength() {
return length;
}
private InputStream getStream() throws SQLException {
try {
if (needsReset) {
stream.reset();
}
}
catch ( IOException ioe) {
throw new SQLException("could not reset reader");
}
needsReset = true;
return stream;
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException if any methods other than {@link Blob#length()}
* or {@link Blob#getBinaryStream} are invoked.
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ( "length".equals( method.getName() ) ) {
return new Long( getLength() );
}
if ( "getBinaryStream".equals( method.getName() ) && method.getParameterTypes().length == 0 ) {
return getStream();
}
if ( "free".equals( method.getName() ) ) {
stream.close();
return null;
}
throw new UnsupportedOperationException( "Blob may not be manipulated from creating session" );
}
/**
* Generates a BlobImpl proxy using byte data.
*
* @param bytes The data to be created as a Blob.
*
* @return The generated proxy.
*/
public static Blob generateProxy(byte[] bytes) {
return ( Blob ) Proxy.newProxyInstance(
getProxyClassLoader(),
PROXY_INTERFACES,
new BlobProxy( bytes )
);
}
/**
* Generates a BlobImpl proxy using a given number of bytes from an InputStream.
*
* @param stream The input stream of bytes to be created as a Blob.
* @param length The number of bytes from stream to be written to the Blob.
*
* @return The generated proxy.
*/
public static Blob generateProxy(InputStream stream, long length) {
return ( Blob ) Proxy.newProxyInstance(
getProxyClassLoader(),
PROXY_INTERFACES,
new BlobProxy( stream, length )
);
}
/**
* Determines the appropriate class loader to which the generated proxy
* should be scoped.
*
* @return The class loader appropriate for proxy construction.
*/
private static ClassLoader getProxyClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if ( cl == null ) {
cl = BlobImplementer.class.getClassLoader();
}
return cl;
}
}

View File

@ -0,0 +1,32 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
/**
* Marker interface for non-contextually created {@link java.sql.Clob} instances..
*
* @author Steve Ebersole
*/
public interface ClobImplementer {
}

View File

@ -0,0 +1,168 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Clob;
import java.sql.SQLException;
import java.io.Reader;
import java.io.StringReader;
import java.io.InputStream;
import java.io.IOException;
/**
* Manages aspects of proxying {@link Clob Clobs} for non-contextual creation, including proxy creation and
* handling proxy invocations.
*
* @author Gavin King
* @author Steve Ebersole
* @author Gail Badner
*/
public class ClobProxy implements InvocationHandler {
private static final Class[] PROXY_INTERFACES = new Class[] { Clob.class, ClobImplementer.class };
private Reader reader;
private long length;
private boolean needsReset = false;
/**
* Ctor used to build {@link Clob} from string data.
*
* @param string The byte array
* @see #generateProxy(String)
*/
protected ClobProxy(String string) {
reader = new StringReader(string);
length = string.length();
}
/**
* Ctor used to build {@link Clob} from a reader.
*
* @param reader The character reader.
* @param length The length of the reader stream.
* @see #generateProxy(java.io.Reader, long)
*/
protected ClobProxy(Reader reader, long length) {
this.reader = reader;
this.length = length;
}
protected long getLength() {
return length;
}
protected InputStream getAsciiStream() throws SQLException {
resetIfNeeded();
return new ReaderInputStream( reader );
}
protected Reader getCharacterStream() throws SQLException {
resetIfNeeded();
return reader;
}
/**
* {@inheritDoc}
*
* @throws UnsupportedOperationException if any methods other than {@link Clob#length()},
* {@link Clob#getAsciiStream()}, or {@link Clob#getCharacterStream()} are invoked.
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ( "length".equals( method.getName() ) ) {
return new Long( getLength() );
}
if ( "getAsciiStream".equals( method.getName() ) ) {
return getAsciiStream();
}
if ( "getCharacterStream".equals( method.getName() ) ) {
return getCharacterStream();
}
if ( "free".equals( method.getName() ) ) {
reader.close();
return null;
}
throw new UnsupportedOperationException( "Clob may not be manipulated from creating session" );
}
protected void resetIfNeeded() throws SQLException {
try {
if ( needsReset ) {
reader.reset();
}
}
catch ( IOException ioe ) {
throw new SQLException( "could not reset reader" );
}
needsReset = true;
}
/**
* Generates a {@link Clob} proxy using the string data.
*
* @param string The data to be wrapped as a {@link Clob}.
*
* @return The generated proxy.
*/
public static Clob generateProxy(String string) {
return ( Clob ) Proxy.newProxyInstance(
getProxyClassLoader(),
PROXY_INTERFACES,
new ClobProxy( string )
);
}
/**
* Generates a {@link Clob} proxy using a character reader of given length.
*
* @param reader The character reader
* @param length The length of the character reader
*
* @return The generated proxy.
*/
public static Clob generateProxy(Reader reader, long length) {
return ( Clob ) Proxy.newProxyInstance(
getProxyClassLoader(),
PROXY_INTERFACES,
new ClobProxy( reader, length )
);
}
/**
* Determines the appropriate class loader to which the generated proxy
* should be scoped.
*
* @return The class loader appropriate for proxy construction.
*/
protected static ClassLoader getProxyClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if ( cl == null ) {
cl = ClobImplementer.class.getClassLoader();
}
return cl;
}
}

View File

@ -20,35 +20,36 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.jdbc; package org.hibernate.engine.jdbc;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.ResultSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
* Implementation of ColumnNameCache. * Cache of column-name -> column-index resolutions
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ColumnNameCache { public class ColumnNameCache {
public static final float LOAD_FACTOR = .75f;
private final Map columnNameToIndexCache; private final Map columnNameToIndexCache;
public ColumnNameCache(int columnCount) { public ColumnNameCache(int columnCount) {
// should *not* need to grow beyond the size of the total number of columns in the rs // should *not* need to grow beyond the size of the total number of columns in the rs
this.columnNameToIndexCache = new HashMap( columnCount ); this.columnNameToIndexCache = new HashMap( columnCount + (int)( columnCount * LOAD_FACTOR ) + 1, LOAD_FACTOR );
} }
public int getIndexForColumnName(String columnName, ResultSetWrapper rs)throws SQLException { public int getIndexForColumnName(String columnName, ResultSet rs) throws SQLException {
Integer cached = ( Integer ) columnNameToIndexCache.get( columnName ); Integer cached = ( Integer ) columnNameToIndexCache.get( columnName );
if ( cached != null ) { if ( cached != null ) {
return cached.intValue(); return cached.intValue();
} }
else { else {
int index = rs.getTarget().findColumn( columnName ); int index = rs.findColumn( columnName );
columnNameToIndexCache.put( columnName, new Integer(index) ); columnNameToIndexCache.put( columnName, new Integer(index) );
return index; return index;
} }

View File

@ -0,0 +1,237 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.sql.Blob;
import java.sql.SQLException;
import java.sql.Clob;
import java.sql.Connection;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import org.hibernate.HibernateException;
/**
* {@link LobCreator} implementation using contextual creation against the JDBC {@link java.sql.Connection} class's LOB creation
* methods.
*
* @author Steve Ebersole
* @author Gail Badner
*/
public class ContextualLobCreator extends AbstractLobCreator implements LobCreator {
private LobCreationContext lobCreationContext;
public ContextualLobCreator(LobCreationContext lobCreationContext) {
this.lobCreationContext = lobCreationContext;
}
/**
* Create the basic contextual BLOB reference.
*
* @return The created BLOB reference.
*/
public Blob createBlob() {
return ( Blob ) lobCreationContext.execute( CREATE_BLOB_CALLBACK );
}
/**
* {@inheritDoc}
*/
public Blob createBlob(byte[] bytes) {
try {
Blob blob = createBlob();
blob.setBytes( 1, bytes );
return blob;
}
catch ( SQLException e ) {
throw new IllegalStateException( "Unable to set BLOB bytes after creation", e );
}
}
/**
* {@inheritDoc}
*/
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 IllegalStateException( "Unable to prepare BLOB binary stream for writing", e );
}
catch ( IOException e ) {
throw new IllegalStateException( "Unable to write stream contents to BLOB", e );
}
}
/**
* Create the basic contextual CLOB reference.
*
* @return The created CLOB reference.
*/
public Clob createClob() {
return ( Clob ) lobCreationContext.execute( CREATE_CLOB_CALLBACK );
}
/**
* {@inheritDoc}
*/
public Clob createClob(String string) {
try {
Clob clob = createClob();
clob.setString( 1, string );
return clob;
}
catch ( SQLException e ) {
throw new IllegalStateException( "Unable to set CLOB string after creation", e );
}
}
/**
* {@inheritDoc}
*/
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 IllegalStateException( "Unable to prepare CLOB stream for writing", e );
}
catch ( IOException e ) {
throw new IllegalStateException( "Unable to write CLOB stream content", e );
}
}
/**
* Create the basic contextual NCLOB reference.
*
* @return The created NCLOB reference.
*/
public Clob createNClob() {
return ( Clob ) lobCreationContext.execute( CREATE_NCLOB_CALLBACK );
}
/**
* {@inheritDoc}
*/
public Clob createNClob(String string) {
try {
Clob clob = createNClob();
clob.setString( 1, string );
return clob;
}
catch ( SQLException e ) {
throw new IllegalStateException( "Unable to set NCLOB string after creation", e );
}
}
/**
* {@inheritDoc}
*/
public Clob createNClob(Reader reader, long length) {
try {
Clob clob = createNClob();
Writer writer = clob.setCharacterStream( 1 );
StreamUtils.copy( reader, writer );
writer.flush();
writer.close();
return clob;
}
catch ( SQLException e ) {
throw new IllegalStateException( "Unable to prepare NCLOB stream for writing", e );
}
catch ( IOException e ) {
throw new IllegalStateException( "Unable to write NCLOB stream content", e );
}
}
private static final Class[] CREATION_METHOD_SIG = new Class[0];
private static final Object[] CREATION_METHOD_ARGS = new Object[0];
private static final LobCreationContext.Callback CREATE_BLOB_CALLBACK;
private static final LobCreationContext.Callback CREATE_CLOB_CALLBACK;
private static final LobCreationContext.Callback CREATE_NCLOB_CALLBACK;
static {
CREATE_BLOB_CALLBACK = new CallbackImpl( getConnectionlobCreationMethod( "createBlob" ) );
CREATE_CLOB_CALLBACK = new CallbackImpl( getConnectionlobCreationMethod( "createClob" ) );
CREATE_NCLOB_CALLBACK = new CallbackImpl( getConnectionlobCreationMethod( "createNClob" ) );
}
private static class CallbackImpl implements LobCreationContext.Callback {
private final Method creationMethod;
private CallbackImpl(Method creationMethod) {
this.creationMethod = creationMethod;
}
public Object executeOnConnection(Connection connection) throws SQLException {
try {
return creationMethod.invoke( connection, CREATION_METHOD_ARGS );
}
catch ( InvocationTargetException e ) {
if ( e.getTargetException() instanceof SQLException ) {
throw ( SQLException ) e.getTargetException();
}
else {
throw new HibernateException( "Exception invoking " + creationMethod.getName(), e.getTargetException() );
}
}
catch ( AbstractMethodError e ) {
// this again is a big big error...
throw new IllegalStateException( "Useable implementation of " + creationMethod.getName() + " not found.", e );
}
catch ( IllegalAccessException e ) {
// this again is a big big error...
throw new IllegalStateException( "Illegal access attempt on JDBC method " + creationMethod.getName(), e );
}
}
}
private static Method getConnectionlobCreationMethod(String methodName) {
try {
return Connection.class.getMethod( methodName, CREATION_METHOD_SIG );
}
catch ( NoSuchMethodException e ) {
// this is a big big error if we get here and these methods are not part of the Connection interface...
throw new IllegalStateException( "JDBC driver did not implement " + methodName, e );
}
}
}

View File

@ -0,0 +1,59 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.sql.ResultSet;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class JdbcSupportImpl implements JdbcSupport {
private final boolean useContextualLobCreation;
public JdbcSupportImpl(boolean useContextualLobCreation) {
this.useContextualLobCreation = useContextualLobCreation;
}
/**
* {@inheritDoc}
*/
public LobCreator getLobCreator() {
return NonContextualLobCreator.INSTANCE;
}
public LobCreator getLobCreator(LobCreationContext lobCreationContext) {
if ( useContextualLobCreation ) {
return new ContextualLobCreator( lobCreationContext );
}
else {
return NonContextualLobCreator.INSTANCE;
}
}
public ResultSet wrap(ResultSet resultSet, ColumnNameCache columnNameCache) {
return ResultSetWrapperProxy.generateProxy( resultSet, columnNameCache );
}
}

View File

@ -0,0 +1,97 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.sql.Connection;
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Builds {@link JdbcSupport} instances based on the capabilities of the environment.
*
* @author Steve Ebersole
*/
public class JdbcSupportLoader {
private static final Logger log = LoggerFactory.getLogger( JdbcSupportLoader.class );
/**
* The public factory method for obtaining the appropriate (accoring to given JDBC {@link java.sql.Connection})
* {@link JdbcSupport}.
*
* @param jdbcConnection A JDBC {@link java.sql.Connection} which can be used to gauge the drivers level of support,
* specifically for creating LOB references.
* @return An appropriate {@link JdbcSupport} instance.
*/
public static JdbcSupport loadJdbcSupport(Connection jdbcConnection) {
return new JdbcSupportImpl( useContextualLobCreation( jdbcConnection ) );
}
private static final Class[] NO_ARG_SIG = new Class[0];
private static final Object[] NO_ARGS = new Object[0];
/**
* Basically here we are simply checking whether we can call the {@link Connection} methods for
* LOB creation added in JDBC 4. We not only check whether the {@link Connection} declares these methods,
* but also whether the actual {@link Connection} instance implements them (i.e. can be called without simply
* throwing an exception).
*
* @param jdbcConnection The connection whcih can be used in level-of-support testing.
* @return True if the connection can be used to create LOBs; false otherwise.
*/
private static boolean useContextualLobCreation(Connection jdbcConnection) {
if ( jdbcConnection == null ) {
return false;
}
try {
Class connectionClass = Connection.class;
Method createClobMethod = connectionClass.getMethod( "createClob", NO_ARG_SIG );
if ( createClobMethod.getDeclaringClass().equals( Connection.class ) ) {
// If we get here we are running in a jdk 1.6 (jdbc 4) environment...
// Further check to make sure the driver actually implements the LOB creation methods. We
// check against createClob() as indicative of all; should we check against all 3 explicitly?
try {
Object clob = createClobMethod.invoke( jdbcConnection, NO_ARGS );
try {
Method freeMethod = clob.getClass().getMethod( "free", NO_ARG_SIG );
freeMethod.invoke( clob, NO_ARGS );
}
catch ( Throwable ignore ) {
log.trace( "Unable to free CLOB created to test createClob() implementation : " + ignore );
}
return true;
}
catch ( Throwable t ) {
log.info( "createClob() method threw error : " + t );
}
}
}
catch ( NoSuchMethodException ignore ) {
}
return false;
}
}

View File

@ -0,0 +1,60 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import org.hibernate.JDBCException;
import org.hibernate.exception.SQLExceptionConverter;
/**
* Provides callback access into the context in which the LOB is to be created. Mainly this is useful
* for gaining access to the JDBC {@link Connection} for use in JDBC 4 environments.
*
* @author Steve Ebersole
*/
public interface LobCreationContext {
/**
* The callback contract for making use of the JDBC {@link Connection}.
*/
public static interface Callback {
/**
* Perform whatever actions are necessary using the provided JDBC {@link Connection}.
*
* @param connection The JDBC {@link Connection}.
* @return The created LOB.
* @throws SQLException
*/
public Object executeOnConnection(Connection connection) throws SQLException;
}
/**
* Execute the given callback, making sure it has access to a viable JDBC {@link Connection}.
*
* @param callback The callback to execute .
* @return The LOB created by the callback.
*/
public Object execute(Callback callback);
}

View File

@ -0,0 +1,34 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
/**
* Marker interface for non-contextually created java.sql.NClob instances..
* <p/>
* java.sql.NClob is a new type introduced in JDK 1.6 (JDBC 4)
*
* @author Steve Ebersole
*/
public interface NClobImplementer {
}

View File

@ -0,0 +1,105 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.sql.Clob;
import java.io.Reader;
import java.lang.reflect.Proxy;
/**
* Manages aspects of proxying java.sql.NClobs for non-contextual creation, including proxy creation and
* handling proxy invocations.
* <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
*
* @author Steve Ebersole
*/
public class NClobProxy extends ClobProxy {
public static final Class[] PROXY_INTERFACES = new Class[] { determineNClobInterface(), NClobImplementer.class };
private static Class determineNClobInterface() {
// java.sql.NClob is a simple marker interface extending java.sql.Clob. So if java.sql.NClob is not available
// on the classloader, just use java.sql.Clob
try {
return getProxyClassLoader().loadClass( "java.sql.NClob" );
}
catch ( ClassNotFoundException e ) {
return Clob.class;
}
}
protected NClobProxy(String string) {
super( string );
}
protected NClobProxy(Reader reader, long length) {
super( reader, length );
}
/**
* Generates a {@link java.sql.Clob} proxy using the string data.
*
* @param string The data to be wrapped as a {@link java.sql.Clob}.
*
* @return The generated proxy.
*/
public static Clob generateProxy(String string) {
return ( Clob ) Proxy.newProxyInstance(
getProxyClassLoader(),
PROXY_INTERFACES,
new ClobProxy( string )
);
}
/**
* Generates a {@link Clob} proxy using a character reader of given length.
*
* @param reader The character reader
* @param length The length of the character reader
*
* @return The generated proxy.
*/
public static Clob generateProxy(Reader reader, long length) {
return ( Clob ) Proxy.newProxyInstance(
getProxyClassLoader(),
PROXY_INTERFACES,
new ClobProxy( reader, length )
);
}
/**
* Determines the appropriate class loader to which the generated proxy
* should be scoped.
*
* @return The class loader appropriate for proxy construction.
*/
protected static ClassLoader getProxyClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if ( cl == null ) {
cl = NClobImplementer.class.getClassLoader();
}
return cl;
}
}

View File

@ -0,0 +1,85 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.sql.Blob;
import java.sql.Clob;
import java.io.InputStream;
import java.io.Reader;
/**
* {@link LobCreator} implementation using non-contextual or local creation, meaning that we generate the LOB
* references ourselves as opposed to delegating to the JDBC {@link java.sql.Connection}.
*
* @author Steve Ebersole
* @author Gail Badner
*/
public class NonContextualLobCreator extends AbstractLobCreator implements LobCreator {
public static final NonContextualLobCreator INSTANCE = new NonContextualLobCreator();
private NonContextualLobCreator() {
}
/**
* {@inheritDoc}
*/
public Blob createBlob(byte[] bytes) {
return BlobProxy.generateProxy( bytes );
}
/**
* {@inheritDoc}
*/
public Blob createBlob(InputStream stream, long length) {
return BlobProxy.generateProxy( stream, length );
}
/**
* {@inheritDoc}
*/
public Clob createClob(String string) {
return ClobProxy.generateProxy( string );
}
/**
* {@inheritDoc}
*/
public Clob createClob(Reader reader, long length) {
return ClobProxy.generateProxy( reader, length );
}
/**
* {@inheritDoc}
*/
public Clob createNClob(String string) {
return NClobProxy.generateProxy( string );
}
/**
* {@inheritDoc}
*/
public Clob createNClob(Reader reader, long length) {
return NClobProxy.generateProxy( reader, length );
}
}

View File

@ -22,18 +22,18 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
* *
*/ */
package org.hibernate.lob; package org.hibernate.engine.jdbc;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
/** /**
* Exposes a <tt>Reader</tt> as an <tt>InputStream</tt> * Exposes a {@link Reader} as an {@link InputStream}.
*
* @author Gavin King * @author Gavin King
*/ */
public class ReaderInputStream extends InputStream { public class ReaderInputStream extends InputStream {
private Reader reader; private Reader reader;
public ReaderInputStream(Reader reader) { public ReaderInputStream(Reader reader) {

View File

@ -0,0 +1,194 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.util.JDBCExceptionReporter;
/**
* A proxy for a ResultSet delegate, responsible for locally caching the columnName-to-columnIndex resolution that
* has been found to be inefficient in a few vendor's drivers (i.e., Oracle and Postgres).
*
* @author Steve Ebersole
* @author Gail Badner
*/
public class ResultSetWrapperProxy implements InvocationHandler {
private static final Logger log = LoggerFactory.getLogger( ResultSetWrapperProxy.class );
private static final Class[] PROXY_INTERFACES = new Class[] { ResultSet.class };
private final ResultSet rs;
private final ColumnNameCache columnNameCache;
private ResultSetWrapperProxy(ResultSet rs, ColumnNameCache columnNameCache) {
this.rs = rs;
this.columnNameCache = columnNameCache;
}
/**
* Generates a proxy wrapping the ResultSet.
*
* @param resultSet The resultSet to wrap.
* @param columnNameCache The cache storing data for converting column names to column indexes.
* @return The generated proxy.
*/
public static ResultSet generateProxy(ResultSet resultSet, ColumnNameCache columnNameCache) {
return ( ResultSet ) Proxy.newProxyInstance(
getProxyClassLoader(),
PROXY_INTERFACES,
new ResultSetWrapperProxy( resultSet, columnNameCache )
);
}
/**
* Determines the appropriate class loader to which the generated proxy
* should be scoped.
*
* @return The class loader appropriate for proxy construction.
*/
public static ClassLoader getProxyClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if ( cl == null ) {
cl = ResultSet.class.getClassLoader();
}
return cl;
}
/**
* {@inheritDoc}
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ( "findColumn".equals( method.getName() ) ) {
return new Integer( findColumn( ( String ) args[0] ) );
}
if ( isFirstArgColumnLabel( method, args ) ) {
try {
int columnIndex = findColumn( ( String ) args[0] );
return invokeMethod(
locateCorrespondingColumnIndexMethod( method ), buildColumnIndexMethodArgs( args, columnIndex )
);
}
catch ( SQLException ex ) {
StringBuffer buf = new StringBuffer()
.append( "Exception getting column index for column: [" )
.append( args[0] )
.append( "].\nReverting to using: [" )
.append( args[0] )
.append( "] as first argument for method: [" )
.append( method )
.append( "]" );
JDBCExceptionReporter.logExceptions( ex, buf.toString() );
}
catch ( NoSuchMethodException ex ) {
StringBuffer buf = new StringBuffer()
.append( "Exception switching from method: [" )
.append( method )
.append( "] to a method using the column index. Reverting to using: [" )
.append( method )
.append( "]" );
if ( log.isWarnEnabled() ) {
log.warn( buf.toString() );
}
}
}
return invokeMethod( method, args );
}
/**
* Locate the column index corresponding to the given column name via the cache.
*
* @param columnName The column name to resolve into an index.
* @return The column index corresponding to the given column name.
* @throws SQLException if the ResultSet object does not contain columnName or a database access error occurs
*/
private int findColumn(String columnName) throws SQLException {
return columnNameCache.getIndexForColumnName( columnName, rs );
}
private boolean isFirstArgColumnLabel(Method method, Object args[]) {
// method name should start with either get or update
if ( ! ( method.getName().startsWith( "get" ) || method.getName().startsWith( "update" ) ) ) {
return false;
}
// method should have arguments, and have same number as incoming arguments
if ( ! ( method.getParameterTypes().length > 0 && args.length == method.getParameterTypes().length ) ) {
return false;
}
// The first argument should be a String (the column name)
//noinspection RedundantIfStatement
if ( ! ( String.class.isInstance( args[0] ) && method.getParameterTypes()[0].equals( String.class ) ) ) {
return false;
}
return true;
}
/**
* For a given {@link ResultSet} method passed a column name, locate the corresponding method passed the same
* parameters but the column index.
*
* @param columnNameMethod The method passed the column name
* @return The corresponding method passed the column index.
* @throws NoSuchMethodException Should never happen, but...
*/
private Method locateCorrespondingColumnIndexMethod(Method columnNameMethod) throws NoSuchMethodException {
Class actualParameterTypes[] = new Class[columnNameMethod.getParameterTypes().length];
actualParameterTypes[0] = int.class;
System.arraycopy(
columnNameMethod.getParameterTypes(),
1,
actualParameterTypes,
1,
columnNameMethod.getParameterTypes().length - 1
);
return columnNameMethod.getDeclaringClass().getMethod( columnNameMethod.getName(), actualParameterTypes );
}
private Object[] buildColumnIndexMethodArgs(Object[] incomingArgs, int columnIndex) {
Object actualArgs[] = new Object[incomingArgs.length];
actualArgs[0] = new Integer( columnIndex );
System.arraycopy( incomingArgs, 1, actualArgs, 1, incomingArgs.length - 1 );
return actualArgs;
}
private Object invokeMethod(Method method, Object args[]) throws Throwable {
try {
return method.invoke( rs, args );
}
catch ( InvocationTargetException e ) {
throw e.getTargetException();
}
}
}

View File

@ -0,0 +1,112 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.sql.Blob;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.io.Serializable;
import org.hibernate.HibernateException;
/**
* Manages aspects of proxying {@link Blob Blobs} to add serializability.
*
* @author Gavin King
* @author Steve Ebersole
* @author Gail Badner
*/
public class SerializableBlobProxy implements InvocationHandler, Serializable {
private static final Class[] PROXY_INTERFACES = new Class[] { Blob.class, WrappedBlob.class, Serializable.class };
private transient final Blob blob;
/**
* Builds a serializable {@link Blob} wrapper around the given {@link Blob}.
*
* @param blob The {@link Blob} to be wrapped.
* @see
*/
private SerializableBlobProxy(Blob blob) {
this.blob = blob;
}
public Blob getWrappedBlob() {
if ( blob == null ) {
throw new IllegalStateException( "Blobs may not be accessed after serialization" );
}
else {
return blob;
}
}
/**
* {@inheritDoc}
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ( "getWrappedBlob".equals( method.getName() ) ) {
return getWrappedBlob();
}
try {
return method.invoke( getWrappedBlob(), args );
}
catch ( AbstractMethodError e ) {
throw new HibernateException( "The JDBC driver does not implement the method: " + method, e );
}
catch ( InvocationTargetException e ) {
throw e.getTargetException();
}
}
/**
* Generates a SerializableBlob proxy wrapping the provided Blob object.
*
* @param blob The Blob to wrap.
*
* @return The generated proxy.
*/
public static Blob generateProxy(Blob blob) {
return ( Blob ) Proxy.newProxyInstance(
getProxyClassLoader(),
PROXY_INTERFACES,
new SerializableBlobProxy( blob )
);
}
/**
* Determines the appropriate class loader to which the generated proxy
* should be scoped.
*
* @return The class loader appropriate for proxy construction.
*/
public static ClassLoader getProxyClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if ( cl == null ) {
cl = WrappedBlob.class.getClassLoader();
}
return cl;
}
}

View File

@ -0,0 +1,111 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.sql.Clob;
import java.io.Serializable;
import org.hibernate.HibernateException;
/**
* Manages aspects of proxying {@link Clob Clobs} to add serializability.
*
* @author Gavin King
* @author Steve Ebersole
* @author Gail Badner
*/
public class SerializableClobProxy implements InvocationHandler, Serializable {
private static final Class[] PROXY_INTERFACES = new Class[] { Clob.class, WrappedClob.class, Serializable.class };
private transient final Clob clob;
/**
* Builds a serializable {@link java.sql.Clob} wrapper around the given {@link java.sql.Clob}.
*
* @param clob The {@link java.sql.Clob} to be wrapped.
* @see #generateProxy(java.sql.Clob)
*/
protected SerializableClobProxy(Clob clob) {
this.clob = clob;
}
public Clob getWrappedClob() {
if ( clob == null ) {
throw new IllegalStateException( "Clobs may not be accessed after serialization" );
}
else {
return clob;
}
}
/**
* {@inheritDoc}
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ( "getWrappedClob".equals( method.getName() ) ) {
return getWrappedClob();
}
try {
return method.invoke( getWrappedClob(), args );
}
catch ( AbstractMethodError e ) {
throw new HibernateException( "The JDBC driver does not implement the method: " + method, e );
}
catch ( InvocationTargetException e ) {
throw e.getTargetException();
}
}
/**
* Generates a SerializableClobProxy proxy wrapping the provided Clob object.
*
* @param clob The Clob to wrap.
* @return The generated proxy.
*/
public static Clob generateProxy(Clob clob) {
return ( Clob ) Proxy.newProxyInstance(
getProxyClassLoader(),
PROXY_INTERFACES,
new SerializableClobProxy( clob )
);
}
/**
* Determines the appropriate class loader to which the generated proxy
* should be scoped.
*
* @return The class loader appropriate for proxy construction.
*/
public static ClassLoader getProxyClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if ( cl == null ) {
cl = WrappedClob.class.getClassLoader();
}
return cl;
}
}

View File

@ -0,0 +1,92 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.sql.Clob;
import java.lang.reflect.Proxy;
/**
* Manages aspects of proxying java.sql.NClobs to add serializability.
*
* @author Steve Ebersole
*/
public class SerializableNClobProxy extends SerializableClobProxy {
private static final Class NCLOB_CLASS = loadNClobClassIfAvailable();
private static Class loadNClobClassIfAvailable() {
try {
return getProxyClassLoader().loadClass( "java.sql.NClob" );
}
catch ( ClassNotFoundException e ) {
return null;
}
}
private static final Class[] PROXY_INTERFACES = new Class[] { determineNClobInterface(), WrappedClob.class };
private static Class determineNClobInterface() {
// java.sql.NClob is a simple marker interface extending java.sql.Clob. So if java.sql.NClob is not available
// on the classloader, just use java.sql.Clob
return NCLOB_CLASS == null ? Clob.class : NCLOB_CLASS;
}
public static boolean isNClob(Clob clob) {
return NCLOB_CLASS != null && NCLOB_CLASS.isInstance( clob );
}
/**
* Builds a serializable {@link java.sql.Clob} wrapper around the given {@link java.sql.Clob}.
*
* @param clob The {@link java.sql.Clob} to be wrapped.
*
* @see #generateProxy(java.sql.Clob)
*/
protected SerializableNClobProxy(Clob clob) {
super( clob );
}
/**
* Generates a SerializableClobProxy proxy wrapping the provided Clob object.
*
* @param clob The Clob to wrap.
* @return The generated proxy.
*/
public static Clob generateProxy(Clob clob) {
return ( Clob ) Proxy.newProxyInstance(
getProxyClassLoader(),
PROXY_INTERFACES,
new SerializableNClobProxy( clob )
);
}
/**
* Determines the appropriate class loader to which the generated proxy
* should be scoped.
*
* @return The class loader appropriate for proxy construction.
*/
public static ClassLoader getProxyClassLoader() {
return SerializableClobProxy.getProxyClassLoader();
}
}

View File

@ -0,0 +1,71 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
/**
* Stream copying utilities
*
* @author Steve Ebersole
*/
public class StreamUtils {
public static final int DEFAULT_CHUNK_SIZE = 1024;
public static long copy(InputStream inputStream, OutputStream outputStream) throws IOException {
return copy( inputStream, outputStream, DEFAULT_CHUNK_SIZE );
}
public static long copy(InputStream inputStream, OutputStream outputStream, int bufferSize) throws IOException {
byte[] buffer = new byte[bufferSize];
long count = 0;
int n;
while ( -1 != ( n = inputStream.read( buffer ) ) ) {
outputStream.write( buffer, 0, n );
count += n;
}
return count;
}
public static long copy(Reader reader, Writer writer) throws IOException {
return copy( reader, writer, DEFAULT_CHUNK_SIZE );
}
public static long copy(Reader reader, Writer writer, int bufferSize) throws IOException {
char[] buffer = new char[bufferSize];
long count = 0;
int n;
while ( -1 != ( n = reader.read( buffer ) ) ) {
writer.write( buffer, 0, n );
count += n;
}
return count;
}
}

View File

@ -0,0 +1,40 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.sql.Blob;
/**
* Contract for {@link Blob} wrappers.
*
* @author Steve Ebersole
*/
public interface WrappedBlob {
/**
* Retrieve the wrapped {@link Blob} reference
*
* @return The wrapped {@link Blob} reference
*/
public Blob getWrappedBlob();
}

View File

@ -0,0 +1,40 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc;
import java.sql.Clob;
/**
* Contract for {@link Clob} wrappers.
*
* @author Steve Ebersole
*/
public interface WrappedClob {
/**
* Retrieve the wrapped {@link java.sql.Blob} reference
*
* @return The wrapped {@link java.sql.Blob} reference
*/
public Clob getWrappedClob();
}

View File

@ -77,6 +77,7 @@ import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.StatefulPersistenceContext; import org.hibernate.engine.StatefulPersistenceContext;
import org.hibernate.engine.Status; import org.hibernate.engine.Status;
import org.hibernate.engine.LoadQueryInfluencers; import org.hibernate.engine.LoadQueryInfluencers;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.query.FilterQueryPlan; import org.hibernate.engine.query.FilterQueryPlan;
import org.hibernate.engine.query.HQLQueryPlan; import org.hibernate.engine.query.HQLQueryPlan;
import org.hibernate.engine.query.NativeSQLQueryPlan; import org.hibernate.engine.query.NativeSQLQueryPlan;
@ -140,7 +141,7 @@ import org.hibernate.util.StringHelper;
* @author Gavin King * @author Gavin King
*/ */
public final class SessionImpl extends AbstractSessionImpl public final class SessionImpl extends AbstractSessionImpl
implements EventSource, org.hibernate.classic.Session, JDBCContext.Context { implements EventSource, org.hibernate.classic.Session, JDBCContext.Context, LobCreationContext {
// todo : need to find a clean way to handle the "event source" role // todo : need to find a clean way to handle the "event source" role
// a seperate classs responsible for generating/dispatching events just duplicates most of the Session methods... // a seperate classs responsible for generating/dispatching events just duplicates most of the Session methods...
@ -2001,6 +2002,23 @@ public final class SessionImpl extends AbstractSessionImpl
oos.writeObject( childSessionsByEntityMode ); oos.writeObject( childSessionsByEntityMode );
} }
public Object execute(Callback callback) {
Connection connection = jdbcContext.getConnectionManager().getConnection();
try {
return callback.executeOnConnection( connection );
}
catch ( SQLException e ) {
throw JDBCExceptionHelper.convert(
getFactory().getSQLExceptionConverter(),
e,
"Error creating contextual LOB : " + e.getMessage()
);
}
finally {
jdbcContext.getConnectionManager().afterStatement();
}
}
private class CoordinatingEntityNameResolver implements EntityNameResolver { private class CoordinatingEntityNameResolver implements EntityNameResolver {
public String resolveEntityName(Object entity) { public String resolveEntityName(Object entity) {
String entityName = interceptor.getEntityName( entity ); String entityName = interceptor.getEntityName( entity );

View File

@ -1,642 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC 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.
*
* 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.jdbc;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Map;
/**
* A ResultSet delegate, responsible for locally caching the columnName-to-columnIndex
* resolution that has been found to be inefficient in a few vendor's drivers (i.e., Oracle
* and Postgres).
*
* @author Steve Ebersole
*/
public class ResultSetWrapper implements ResultSet {
private ResultSet rs;
private ColumnNameCache columnNameCache;
public ResultSetWrapper(ResultSet resultSet, ColumnNameCache columnNameCache) {
this.rs = resultSet;
this.columnNameCache = columnNameCache;
}
/*package*/ ResultSet getTarget() {
return rs;
}
// ResultSet impl ("overridden") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Overridden version to utilize local caching of the column indexes by name
* to improve performance for those drivers which are known to not support
* such caching by themselves.
* <p/>
* This implementation performs the caching based on the upper case version
* of the given column name.
*
* @param columnName The column name to resolve into an index.
* @return The column index corresponding to the given column name.
* @throws SQLException - if the ResultSet object does not contain
* columnName or a database access error occurs
*/
public int findColumn(String columnName) throws SQLException {
return columnNameCache.getIndexForColumnName( columnName, this );
}
public Array getArray(String colName) throws SQLException {
return rs.getArray( findColumn(colName) );
}
public void updateArray(String columnName, Array x) throws SQLException {
rs.updateArray( findColumn(columnName), x );
}
public InputStream getAsciiStream(String columnName) throws SQLException {
return rs.getAsciiStream( findColumn(columnName) );
}
public void updateAsciiStream(String columnName, InputStream x, int length) throws SQLException {
rs.updateAsciiStream( findColumn(columnName), x, length );
}
public BigDecimal getBigDecimal(String columnName) throws SQLException {
return rs.getBigDecimal( findColumn(columnName) );
}
public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
return rs.getBigDecimal( findColumn(columnName), scale );
}
public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
rs.updateBigDecimal( findColumn(columnName), x );
}
public InputStream getBinaryStream(String columnName) throws SQLException {
return rs.getBinaryStream( findColumn(columnName) );
}
public void updateBinaryStream(String columnName, InputStream x, int length) throws SQLException {
rs.updateBinaryStream( findColumn(columnName), x, length );
}
public Blob getBlob(String columnName) throws SQLException {
return rs.getBlob( findColumn(columnName) );
}
public void updateBlob(String columnName, Blob x) throws SQLException {
rs.updateBlob( findColumn(columnName), x );
}
public boolean getBoolean(String columnName) throws SQLException {
return rs.getBoolean( findColumn(columnName) );
}
public void updateBoolean(String columnName, boolean x) throws SQLException {
rs.updateBoolean( findColumn(columnName), x );
}
public byte getByte(String columnName) throws SQLException {
return rs.getByte( findColumn(columnName) );
}
public void updateByte(String columnName, byte x) throws SQLException {
rs.updateByte( findColumn(columnName), x );
}
public byte[] getBytes(String columnName) throws SQLException {
return rs.getBytes( findColumn(columnName) );
}
public void updateBytes(String columnName, byte[] x) throws SQLException {
rs.updateBytes( findColumn(columnName), x );
}
public Reader getCharacterStream(String columnName) throws SQLException {
return rs.getCharacterStream( findColumn(columnName) );
}
public void updateCharacterStream(String columnName, Reader x, int length) throws SQLException {
rs.updateCharacterStream( findColumn(columnName), x, length );
}
public Clob getClob(String columnName) throws SQLException {
return rs.getClob( findColumn(columnName) );
}
public void updateClob(String columnName, Clob x) throws SQLException {
rs.updateClob( findColumn(columnName), x );
}
public Date getDate(String columnName) throws SQLException {
return rs.getDate( findColumn(columnName) );
}
public Date getDate(String columnName, Calendar cal) throws SQLException {
return rs.getDate( findColumn(columnName), cal );
}
public void updateDate(String columnName, Date x) throws SQLException {
rs.updateDate( findColumn(columnName), x );
}
public double getDouble(String columnName) throws SQLException {
return rs.getDouble( findColumn(columnName) );
}
public void updateDouble(String columnName, double x) throws SQLException {
rs.updateDouble( findColumn(columnName), x );
}
public float getFloat(String columnName) throws SQLException {
return rs.getFloat( findColumn(columnName) );
}
public void updateFloat(String columnName, float x) throws SQLException {
rs.updateFloat( findColumn(columnName), x );
}
public int getInt(String columnName) throws SQLException {
return rs.getInt( findColumn(columnName) );
}
public void updateInt(String columnName, int x) throws SQLException {
rs.updateInt( findColumn(columnName), x );
}
public long getLong(String columnName) throws SQLException {
return rs.getLong( findColumn(columnName) );
}
public void updateLong(String columnName, long x) throws SQLException {
rs.updateLong( findColumn(columnName), x );
}
public Object getObject(String columnName) throws SQLException {
return rs.getObject( findColumn(columnName) );
}
public Object getObject(String columnName, Map map) throws SQLException {
return rs.getObject( findColumn(columnName), map );
}
public void updateObject(String columnName, Object x) throws SQLException {
rs.updateObject( findColumn(columnName), x );
}
public void updateObject(String columnName, Object x, int scale) throws SQLException {
rs.updateObject( findColumn(columnName), x, scale );
}
public Ref getRef(String columnName) throws SQLException {
return rs.getRef( findColumn(columnName) );
}
public void updateRef(String columnName, Ref x) throws SQLException {
rs.updateRef( findColumn(columnName), x );
}
public short getShort(String columnName) throws SQLException {
return rs.getShort( findColumn(columnName) );
}
public void updateShort(String columnName, short x) throws SQLException {
rs.updateShort( findColumn(columnName), x );
}
public String getString(String columnName) throws SQLException {
return rs.getString( findColumn(columnName) );
}
public void updateString(String columnName, String x) throws SQLException {
rs.updateString( findColumn(columnName), x );
}
public Time getTime(String columnName) throws SQLException {
return rs.getTime( findColumn(columnName) );
}
public Time getTime(String columnName, Calendar cal) throws SQLException {
return rs.getTime( findColumn(columnName), cal );
}
public void updateTime(String columnName, Time x) throws SQLException {
rs.updateTime( findColumn(columnName), x );
}
public Timestamp getTimestamp(String columnName) throws SQLException {
return rs.getTimestamp( findColumn(columnName) );
}
public void updateTimestamp(String columnName, Timestamp x) throws SQLException {
rs.updateTimestamp( findColumn(columnName), x );
}
public Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
return rs.getTimestamp( findColumn(columnName), cal );
}
public InputStream getUnicodeStream(String columnName) throws SQLException {
return rs.getUnicodeStream( findColumn(columnName) );
}
public URL getURL(String columnName) throws SQLException {
return rs.getURL( findColumn(columnName) );
}
public void updateNull(String columnName) throws SQLException {
rs.updateNull( findColumn(columnName) );
}
// ResultSet impl (delegated) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public int getConcurrency() throws SQLException {
return rs.getConcurrency();
}
public int getFetchDirection() throws SQLException {
return rs.getFetchDirection();
}
public int getFetchSize() throws SQLException {
return rs.getFetchSize();
}
public int getRow() throws SQLException {
return rs.getRow();
}
public int getType() throws SQLException {
return rs.getType();
}
public void afterLast() throws SQLException {
rs.afterLast();
}
public void beforeFirst() throws SQLException {
rs.beforeFirst();
}
public void cancelRowUpdates() throws SQLException {
rs.cancelRowUpdates();
}
public void clearWarnings() throws SQLException {
rs.clearWarnings();
}
public void close() throws SQLException {
rs.close();
}
public void deleteRow() throws SQLException {
rs.deleteRow();
}
public void insertRow() throws SQLException {
rs.insertRow();
}
public void moveToCurrentRow() throws SQLException {
rs.moveToCurrentRow();
}
public void moveToInsertRow() throws SQLException {
rs.moveToInsertRow();
}
public void refreshRow() throws SQLException {
rs.refreshRow();
}
public void updateRow() throws SQLException {
rs.updateRow();
}
public boolean first() throws SQLException {
return rs.first();
}
public boolean isAfterLast() throws SQLException {
return rs.isAfterLast();
}
public boolean isBeforeFirst() throws SQLException {
return rs.isBeforeFirst();
}
public boolean isFirst() throws SQLException {
return rs.isFirst();
}
public boolean isLast() throws SQLException {
return rs.isLast();
}
public boolean last() throws SQLException {
return rs.last();
}
public boolean next() throws SQLException {
return rs.next();
}
public boolean previous() throws SQLException {
return rs.previous();
}
public boolean rowDeleted() throws SQLException {
return rs.rowDeleted();
}
public boolean rowInserted() throws SQLException {
return rs.rowInserted();
}
public boolean rowUpdated() throws SQLException {
return rs.rowUpdated();
}
public boolean wasNull() throws SQLException {
return rs.wasNull();
}
public byte getByte(int columnIndex) throws SQLException {
return rs.getByte(columnIndex);
}
public double getDouble(int columnIndex) throws SQLException {
return rs.getDouble(columnIndex);
}
public float getFloat(int columnIndex) throws SQLException {
return rs.getFloat(columnIndex);
}
public int getInt(int columnIndex) throws SQLException {
return rs.getInt(columnIndex);
}
public long getLong(int columnIndex) throws SQLException {
return rs.getLong(columnIndex);
}
public short getShort(int columnIndex) throws SQLException {
return rs.getShort(columnIndex);
}
public void setFetchDirection(int direction) throws SQLException {
rs.setFetchDirection(direction);
}
public void setFetchSize(int rows) throws SQLException {
rs.setFetchSize(rows);
}
public void updateNull(int columnIndex) throws SQLException {
rs.updateNull(columnIndex);
}
public boolean absolute(int row) throws SQLException {
return rs.absolute(row);
}
public boolean getBoolean(int columnIndex) throws SQLException {
return rs.getBoolean(columnIndex);
}
public boolean relative(int rows) throws SQLException {
return rs.relative(rows);
}
public byte[] getBytes(int columnIndex) throws SQLException {
return rs.getBytes(columnIndex);
}
public void updateByte(int columnIndex, byte x) throws SQLException {
rs.updateByte(columnIndex, x);
}
public void updateDouble(int columnIndex, double x) throws SQLException {
rs.updateDouble(columnIndex, x);
}
public void updateFloat(int columnIndex, float x) throws SQLException {
rs.updateFloat(columnIndex, x);
}
public void updateInt(int columnIndex, int x) throws SQLException {
rs.updateInt(columnIndex, x);
}
public void updateLong(int columnIndex, long x) throws SQLException {
rs.updateLong(columnIndex, x);
}
public void updateShort(int columnIndex, short x) throws SQLException {
rs.updateShort(columnIndex, x);
}
public void updateBoolean(int columnIndex, boolean x) throws SQLException {
rs.updateBoolean(columnIndex, x);
}
public void updateBytes(int columnIndex, byte[] x) throws SQLException {
rs.updateBytes(columnIndex, x);
}
public InputStream getAsciiStream(int columnIndex) throws SQLException {
return rs.getAsciiStream(columnIndex);
}
public InputStream getBinaryStream(int columnIndex) throws SQLException {
return rs.getBinaryStream(columnIndex);
}
public InputStream getUnicodeStream(int columnIndex) throws SQLException {
return rs.getUnicodeStream(columnIndex);
}
public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException {
rs.updateAsciiStream(columnIndex, x, length);
}
public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException {
rs.updateBinaryStream(columnIndex, x, length);
}
public Reader getCharacterStream(int columnIndex) throws SQLException {
return rs.getCharacterStream(columnIndex);
}
public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException {
rs.updateCharacterStream(columnIndex, x, length);
}
public Object getObject(int columnIndex) throws SQLException {
return rs.getObject(columnIndex);
}
public void updateObject(int columnIndex, Object x) throws SQLException {
rs.updateObject(columnIndex, x);
}
public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
rs.updateObject(columnIndex, x, scale);
}
public String getCursorName() throws SQLException {
return rs.getCursorName();
}
public String getString(int columnIndex) throws SQLException {
return rs.getString(columnIndex);
}
public void updateString(int columnIndex, String x) throws SQLException {
rs.updateString(columnIndex, x);
}
public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
return rs.getBigDecimal(columnIndex);
}
public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
return rs.getBigDecimal(columnIndex, scale);
}
public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
rs.updateBigDecimal(columnIndex, x);
}
public URL getURL(int columnIndex) throws SQLException {
return rs.getURL(columnIndex);
}
public Array getArray(int columnIndex) throws SQLException {
return rs.getArray(columnIndex);
}
public void updateArray(int columnIndex, Array x) throws SQLException {
rs.updateArray(columnIndex, x);
}
public Blob getBlob(int columnIndex) throws SQLException {
return rs.getBlob(columnIndex);
}
public void updateBlob(int columnIndex, Blob x) throws SQLException {
rs.updateBlob(columnIndex, x);
}
public Clob getClob(int columnIndex) throws SQLException {
return rs.getClob(columnIndex);
}
public void updateClob(int columnIndex, Clob x) throws SQLException {
rs.updateClob(columnIndex, x);
}
public Date getDate(int columnIndex) throws SQLException {
return rs.getDate(columnIndex);
}
public void updateDate(int columnIndex, Date x) throws SQLException {
rs.updateDate(columnIndex, x);
}
public Ref getRef(int columnIndex) throws SQLException {
return rs.getRef(columnIndex);
}
public void updateRef(int columnIndex, Ref x) throws SQLException {
rs.updateRef(columnIndex, x);
}
public ResultSetMetaData getMetaData() throws SQLException {
return rs.getMetaData();
}
public SQLWarning getWarnings() throws SQLException {
return rs.getWarnings();
}
public Statement getStatement() throws SQLException {
return rs.getStatement();
}
public Time getTime(int columnIndex) throws SQLException {
return rs.getTime(columnIndex);
}
public void updateTime(int columnIndex, Time x) throws SQLException {
rs.updateTime(columnIndex, x);
}
public Timestamp getTimestamp(int columnIndex) throws SQLException {
return rs.getTimestamp(columnIndex);
}
public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
rs.updateTimestamp(columnIndex, x);
}
public Object getObject(int columnIndex, Map map) throws SQLException {
return rs.getObject( columnIndex, map );
}
public Date getDate(int columnIndex, Calendar cal) throws SQLException {
return rs.getDate(columnIndex, cal);
}
public Time getTime(int columnIndex, Calendar cal) throws SQLException {
return rs.getTime(columnIndex, cal);
}
public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
return rs.getTimestamp(columnIndex, cal);
}
}

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * Hibernate, Relational Persistence for Idiomatic Java
* *
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* indicated by the @author tags or express copyright attribution * third-party contributors as indicated by either @author tags or express
* statements applied by the authors. All third-party contributions are * copyright attribution statements applied by the authors. All
* distributed under license by Red Hat Middleware LLC. * third-party contributions are distributed under license by Red Hat Inc.
* *
* This copyrighted material is made available to anyone wishing to use, modify, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,7 +20,6 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.loader; package org.hibernate.loader;
@ -63,6 +62,7 @@ import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.SubselectFetch; import org.hibernate.engine.SubselectFetch;
import org.hibernate.engine.TwoPhaseLoad; import org.hibernate.engine.TwoPhaseLoad;
import org.hibernate.engine.TypedValue; import org.hibernate.engine.TypedValue;
import org.hibernate.engine.jdbc.ColumnNameCache;
import org.hibernate.event.EventSource; import org.hibernate.event.EventSource;
import org.hibernate.event.PostLoadEvent; import org.hibernate.event.PostLoadEvent;
import org.hibernate.event.PreLoadEvent; import org.hibernate.event.PreLoadEvent;
@ -70,8 +70,6 @@ import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.hql.HolderInstantiator; import org.hibernate.hql.HolderInstantiator;
import org.hibernate.impl.FetchingScrollableResultsImpl; import org.hibernate.impl.FetchingScrollableResultsImpl;
import org.hibernate.impl.ScrollableResultsImpl; import org.hibernate.impl.ScrollableResultsImpl;
import org.hibernate.jdbc.ColumnNameCache;
import org.hibernate.jdbc.ResultSetWrapper;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.Loadable;
@ -1839,7 +1837,9 @@ public abstract class Loader {
if ( session.getFactory().getSettings().isWrapResultSetsEnabled() ) { if ( session.getFactory().getSettings().isWrapResultSetsEnabled() ) {
try { try {
log.debug("Wrapping result set [" + rs + "]"); log.debug("Wrapping result set [" + rs + "]");
return new ResultSetWrapper( rs, retreiveColumnNameToIndexCache( rs ) ); return session.getFactory()
.getSettings()
.getJdbcSupport().wrap( rs, retreiveColumnNameToIndexCache( rs ) );
} }
catch(SQLException e) { catch(SQLException e) {
log.info("Error wrapping result set", e); log.info("Error wrapping result set", e);

View File

@ -1,136 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC 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.
*
* 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.lob;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.SQLException;
/**
* A dummy implementation of <tt>java.sql.Blob</tt> that
* may be used to insert new data into a BLOB.
* @author Gavin King
*/
public class BlobImpl implements Blob {
private InputStream stream;
private int length;
private boolean needsReset = false;
public BlobImpl(byte[] bytes) {
this.stream = new ByteArrayInputStream(bytes);
this.length = bytes.length;
}
public BlobImpl(InputStream stream, int length) {
this.stream = stream;
this.length = length;
}
/**
* @see java.sql.Blob#length()
*/
public long length() throws SQLException {
return length;
}
/**
* @see java.sql.Blob#truncate(long)
*/
public void truncate(long pos) throws SQLException {
excep();
}
/**
* @see java.sql.Blob#getBytes(long, int)
*/
public byte[] getBytes(long pos, int len) throws SQLException {
excep(); return null;
}
/**
* @see java.sql.Blob#setBytes(long, byte[])
*/
public int setBytes(long pos, byte[] bytes) throws SQLException {
excep(); return 0;
}
/**
* @see java.sql.Blob#setBytes(long, byte[], int, int)
*/
public int setBytes(long pos, byte[] bytes, int i, int j)
throws SQLException {
excep(); return 0;
}
/**
* @see java.sql.Blob#position(byte[], long)
*/
public long position(byte[] bytes, long pos) throws SQLException {
excep(); return 0;
}
/**
* @see java.sql.Blob#getBinaryStream()
*/
public InputStream getBinaryStream() throws SQLException {
try {
if (needsReset) stream.reset();
}
catch (IOException ioe) {
throw new SQLException("could not reset reader");
}
needsReset = true;
return stream;
}
/**
* @see java.sql.Blob#setBinaryStream(long)
*/
public OutputStream setBinaryStream(long pos) throws SQLException {
excep(); return null;
}
/**
* @see java.sql.Blob#position(Blob, long)
*/
public long position(Blob blob, long pos) throws SQLException {
excep(); return 0;
}
private static void excep() {
throw new UnsupportedOperationException("Blob may not be manipulated from creating session");
}
}

View File

@ -1,160 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC 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.
*
* 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.lob;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.sql.Clob;
import java.sql.SQLException;
/**
* A dummy implementation of <tt>java.sql.Clob</tt> that
* may be used to insert new data into a CLOB.
* @author Gavin King
*/
public class ClobImpl implements Clob {
private Reader reader;
private int length;
private boolean needsReset = false;
public ClobImpl(String string) {
reader = new StringReader(string);
length = string.length();
}
public ClobImpl(Reader reader, int length) {
this.reader = reader;
this.length = length;
}
/**
* @see java.sql.Clob#length()
*/
public long length() throws SQLException {
return length;
}
/**
* @see java.sql.Clob#truncate(long)
*/
public void truncate(long pos) throws SQLException {
excep();
}
/**
* @see java.sql.Clob#getAsciiStream()
*/
public InputStream getAsciiStream() throws SQLException {
try {
if (needsReset) reader.reset();
}
catch (IOException ioe) {
throw new SQLException("could not reset reader");
}
needsReset = true;
return new ReaderInputStream(reader);
}
/**
* @see java.sql.Clob#setAsciiStream(long)
*/
public OutputStream setAsciiStream(long pos) throws SQLException {
excep(); return null;
}
/**
* @see java.sql.Clob#getCharacterStream()
*/
public Reader getCharacterStream() throws SQLException {
try {
if (needsReset) reader.reset();
}
catch (IOException ioe) {
throw new SQLException("could not reset reader");
}
needsReset = true;
return reader;
}
/**
* @see java.sql.Clob#setCharacterStream(long)
*/
public Writer setCharacterStream(long pos) throws SQLException {
excep(); return null;
}
/**
* @see java.sql.Clob#getSubString(long, int)
*/
public String getSubString(long pos, int len) throws SQLException {
excep(); return null;
}
/**
* @see java.sql.Clob#setString(long, String)
*/
public int setString(long pos, String string) throws SQLException {
excep(); return 0;
}
/**
* @see java.sql.Clob#setString(long, String, int, int)
*/
public int setString(long pos, String string, int i, int j)
throws SQLException {
excep(); return 0;
}
/**
* @see java.sql.Clob#position(String, long)
*/
public long position(String string, long pos) throws SQLException {
excep(); return 0;
}
/**
* @see java.sql.Clob#position(Clob, long)
*/
public long position(Clob colb, long pos) throws SQLException {
excep(); return 0;
}
private static void excep() {
throw new UnsupportedOperationException("Blob may not be manipulated from creating session");
}
}

View File

@ -1,89 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC 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.
*
* 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.lob;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.sql.Blob;
import java.sql.SQLException;
/**
* @author Gavin King
*/
public class SerializableBlob implements Serializable, Blob {
private transient final Blob blob;
public SerializableBlob(Blob blob) {
this.blob = blob;
}
public Blob getWrappedBlob() {
if ( blob==null ) {
throw new IllegalStateException("Blobs may not be accessed after serialization");
}
else {
return blob;
}
}
public long length() throws SQLException {
return getWrappedBlob().length();
}
public byte[] getBytes(long pos, int length) throws SQLException {
return getWrappedBlob().getBytes(pos, length);
}
public InputStream getBinaryStream() throws SQLException {
return getWrappedBlob().getBinaryStream();
}
public long position(byte[] pattern, long start) throws SQLException {
return getWrappedBlob().position(pattern, start);
}
public long position(Blob pattern, long start) throws SQLException {
return getWrappedBlob().position(pattern, start);
}
public int setBytes(long pos, byte[] bytes) throws SQLException {
return getWrappedBlob().setBytes(pos, bytes);
}
public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException {
return getWrappedBlob().setBytes(pos, bytes, offset, len);
}
public OutputStream setBinaryStream(long pos) throws SQLException {
return getWrappedBlob().setBinaryStream(pos);
}
public void truncate(long len) throws SQLException {
getWrappedBlob().truncate(len);
}
}

View File

@ -1,99 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC 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.
*
* 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.lob;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Serializable;
import java.io.Writer;
import java.sql.Clob;
import java.sql.SQLException;
/**
* @author Gavin King
*/
public class SerializableClob implements Serializable, Clob {
private transient final Clob clob;
public SerializableClob(Clob blob) {
this.clob = blob;
}
public Clob getWrappedClob() {
if ( clob==null ) {
throw new IllegalStateException("Clobs may not be accessed after serialization");
}
else {
return clob;
}
}
public long length() throws SQLException {
return getWrappedClob().length();
}
public String getSubString(long pos, int length) throws SQLException {
return getWrappedClob().getSubString(pos, length);
}
public Reader getCharacterStream() throws SQLException {
return getWrappedClob().getCharacterStream();
}
public InputStream getAsciiStream() throws SQLException {
return getWrappedClob().getAsciiStream();
}
public long position(String searchstr, long start) throws SQLException {
return getWrappedClob().position(searchstr, start);
}
public long position(Clob searchstr, long start) throws SQLException {
return getWrappedClob().position(searchstr, start);
}
public int setString(long pos, String str) throws SQLException {
return getWrappedClob().setString(pos, str);
}
public int setString(long pos, String str, int offset, int len) throws SQLException {
return getWrappedClob().setString(pos, str, offset, len);
}
public OutputStream setAsciiStream(long pos) throws SQLException {
return getWrappedClob().setAsciiStream(pos);
}
public Writer setCharacterStream(long pos) throws SQLException {
return getWrappedClob().setCharacterStream(pos);
}
public void truncate(long len) throws SQLException {
getWrappedClob().truncate(len);
}
}

View File

@ -1,34 +0,0 @@
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ Copyright (c) 2008, Red Hat Middleware LLC 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.
~
~ 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
~
-->
<html>
<head></head>
<body>
<p>
This package defines dummy and wrapper implementations
of <tt>java.sql.Clob</tt> and <tt>java.sql.Blob</tt>.
</p>
</body>
</html>

View File

@ -36,11 +36,14 @@ import org.dom4j.Node;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.Hibernate;
import org.hibernate.engine.Mapping; import org.hibernate.engine.Mapping;
import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor; import org.hibernate.engine.SessionImplementor;
import org.hibernate.lob.BlobImpl; import org.hibernate.engine.jdbc.BlobImplementer;
import org.hibernate.lob.SerializableBlob; import org.hibernate.engine.jdbc.WrappedBlob;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.util.ArrayHelper; import org.hibernate.util.ArrayHelper;
/** /**
@ -48,135 +51,223 @@ import org.hibernate.util.ArrayHelper;
* @author Gavin King * @author Gavin King
*/ */
public class BlobType extends AbstractType { public class BlobType extends AbstractType {
/**
* {@inheritDoc}
*/
public void nullSafeSet(
PreparedStatement st,
Object value,
int index,
boolean[] settable,
SessionImplementor session) throws HibernateException, SQLException {
if ( settable[0] ) {
set( st, value, index, session );
}
}
public void set(PreparedStatement st, Object value, int index, SessionImplementor session) /**
throws HibernateException, SQLException { * {@inheritDoc}
*/
public void nullSafeSet(
PreparedStatement st,
Object value,
int index,
SessionImplementor session) throws HibernateException, SQLException {
set( st, value, index, session );
}
if (value==null) { public void set(
st.setNull(index, Types.BLOB); PreparedStatement st,
Object value,
int index,
SessionImplementor session) throws HibernateException, SQLException {
if ( value == null ) {
st.setNull( index, Types.BLOB );
return;
}
Blob blob = ( Blob ) value;
if ( WrappedBlob.class.isInstance( blob ) ) {
blob = ( (WrappedBlob) value ).getWrappedBlob();
}
final boolean useInputStream = session.getFactory().getDialect().useInputStreamToInsertBlob()
&& BlobImplementer.class.isInstance( blob );
if ( useInputStream ) {
st.setBinaryStream( index, blob.getBinaryStream(), (int) blob.length() );
} }
else { else {
st.setBlob( index, blob );
if (value instanceof SerializableBlob) {
value = ( (SerializableBlob) value ).getWrappedBlob();
}
final boolean useInputStream = session.getFactory().getDialect().useInputStreamToInsertBlob() &&
(value instanceof BlobImpl);
if ( useInputStream ) {
BlobImpl blob = (BlobImpl) value;
st.setBinaryStream( index, blob.getBinaryStream(), (int) blob.length() );
}
else {
st.setBlob(index, (Blob) value);
}
} }
} }
public Object get(ResultSet rs, String name) throws HibernateException, SQLException { /**
Blob value = rs.getBlob(name); * {@inheritDoc}
return rs.wasNull() ? null : new SerializableBlob(value); */
public Object nullSafeGet(
ResultSet rs,
String name,
SessionImplementor session,
Object owner) throws HibernateException, SQLException {
return get( rs, name, Hibernate.getLobCreator( session ) );
} }
/**
* {@inheritDoc}
*/
public Object nullSafeGet(
ResultSet rs,
String[] names,
SessionImplementor session,
Object owner) throws HibernateException, SQLException {
return get( rs, names[0], Hibernate.getLobCreator( session ) );
}
/**
* A method to extract the BLOB value from a result set.
*
* @param rs The result set
* @param name The name of the column containing the BLOB
*
* @return The BLOB
*
* @throws SQLException Indicates a problem accessing the result set
*
* @deprecated Use {@link #get(ResultSet,String,LobCreator)} instead
*/
public Object get(ResultSet rs, String name) throws SQLException {
return get( rs, name, NonContextualLobCreator.INSTANCE );
}
public Object get(ResultSet rs, String name, LobCreator lobCreator) throws SQLException {
Blob value = rs.getBlob( name );
return rs.wasNull() ? null : lobCreator.wrap( value );
}
/**
* {@inheritDoc}
*/
public Class getReturnedClass() { public Class getReturnedClass() {
return Blob.class; return Blob.class;
} }
/**
* {@inheritDoc}
*/
public boolean isEqual(Object x, Object y, EntityMode entityMode) { public boolean isEqual(Object x, Object y, EntityMode entityMode) {
return x == y; return x == y;
} }
/**
* {@inheritDoc}
*/
public int getHashCode(Object x, EntityMode entityMode) { public int getHashCode(Object x, EntityMode entityMode) {
return System.identityHashCode(x); return System.identityHashCode(x);
} }
/**
* {@inheritDoc}
*/
public int compare(Object x, Object y, EntityMode entityMode) { public int compare(Object x, Object y, EntityMode entityMode) {
return 0; //lobs cannot be compared return 0; //lobs cannot be compared
} }
/**
* {@inheritDoc}
*/
public String getName() { public String getName() {
return "blob"; return "blob";
} }
/**
* {@inheritDoc}
*/
public Serializable disassemble(Object value, SessionImplementor session, Object owner) public Serializable disassemble(Object value, SessionImplementor session, Object owner)
throws HibernateException { throws UnsupportedOperationException {
throw new UnsupportedOperationException("Blobs are not cacheable"); throw new UnsupportedOperationException("Blobs are not cacheable");
} }
/**
* {@inheritDoc}
*/
public Object deepCopy(Object value, EntityMode entityMode, SessionFactoryImplementor factory) { public Object deepCopy(Object value, EntityMode entityMode, SessionFactoryImplementor factory) {
return value; return value;
} }
/**
* {@inheritDoc}
*/
public Object fromXMLNode(Node xml, Mapping factory) { public Object fromXMLNode(Node xml, Mapping factory) {
throw new UnsupportedOperationException("todo"); throw new UnsupportedOperationException("todo");
} }
/**
* {@inheritDoc}
*/
public int getColumnSpan(Mapping mapping) { public int getColumnSpan(Mapping mapping) {
return 1; return 1;
} }
/**
* {@inheritDoc}
*/
public boolean isMutable() { public boolean isMutable() {
return false; return false;
} }
public Object nullSafeGet(ResultSet rs, String name, /**
SessionImplementor session, Object owner) * {@inheritDoc}
throws HibernateException, SQLException { */
return get(rs, name); public Object replace(
} Object original,
Object target,
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session,
SessionImplementor session, Object owner) Object owner,
throws HibernateException, SQLException { Map copyCache) throws HibernateException {
return get( rs, names[0] );
}
public void nullSafeSet(PreparedStatement st, Object value, int index,
boolean[] settable, SessionImplementor session)
throws HibernateException, SQLException {
if ( settable[0] ) set(st, value, index, session);
}
public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException {
set(st, value, index, session);
}
public Object replace(Object original, Object target,
SessionImplementor session, Object owner, Map copyCache)
throws HibernateException {
//Blobs are ignored by merge() //Blobs are ignored by merge()
return target; return target;
} }
/**
* {@inheritDoc}
*/
public int[] sqlTypes(Mapping mapping) throws MappingException { public int[] sqlTypes(Mapping mapping) throws MappingException {
return new int[] { Types.BLOB }; return new int[] { Types.BLOB };
} }
/**
* {@inheritDoc}
*/
public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) { public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) {
throw new UnsupportedOperationException("todo"); throw new UnsupportedOperationException("todo");
} }
public String toLoggableString(Object value, SessionFactoryImplementor factory) /**
throws HibernateException { * {@inheritDoc}
*/
public String toLoggableString(Object value, SessionFactoryImplementor factory) throws HibernateException {
return value==null ? "null" : value.toString(); return value==null ? "null" : value.toString();
} }
/**
* {@inheritDoc}
*/
public boolean[] toColumnNullness(Object value, Mapping mapping) { public boolean[] toColumnNullness(Object value, Mapping mapping) {
return value==null ? ArrayHelper.FALSE : ArrayHelper.TRUE; return value==null ? ArrayHelper.FALSE : ArrayHelper.TRUE;
} }
public boolean isDirty(Object old, Object current, boolean[] checkable, SessionImplementor session) throws HibernateException { /**
* {@inheritDoc}
*/
public boolean isDirty(
Object old,
Object current,
boolean[] checkable,
SessionImplementor session) throws HibernateException {
return checkable[0] && isDirty(old, current, session); return checkable[0] && isDirty(old, current, session);
} }
} }

View File

@ -40,8 +40,10 @@ import org.hibernate.MappingException;
import org.hibernate.engine.Mapping; import org.hibernate.engine.Mapping;
import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor; import org.hibernate.engine.SessionImplementor;
import org.hibernate.lob.ClobImpl; import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.lob.SerializableClob; import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.engine.jdbc.WrappedClob;
import org.hibernate.engine.jdbc.ClobImplementer;
import org.hibernate.util.ArrayHelper; import org.hibernate.util.ArrayHelper;
/** /**
@ -50,36 +52,87 @@ import org.hibernate.util.ArrayHelper;
*/ */
public class ClobType extends AbstractType { public class ClobType extends AbstractType {
public void set(PreparedStatement st, Object value, int index, SessionImplementor session) public void nullSafeSet(
throws HibernateException, SQLException { PreparedStatement st,
Object value,
if (value==null) { int index,
st.setNull(index, Types.CLOB); boolean[] settable,
SessionImplementor session) throws SQLException {
if ( settable[0] ) {
set( st, value, index, session );
} }
else {
if (value instanceof SerializableClob) {
value = ( (SerializableClob) value ).getWrappedClob();
}
final boolean useReader = session.getFactory().getDialect().useInputStreamToInsertBlob() &&
(value instanceof ClobImpl);
if ( useReader ) {
ClobImpl clob = (ClobImpl) value;
st.setCharacterStream( index, clob.getCharacterStream(), (int) clob.length() );
}
else {
st.setClob(index, (Clob) value);
}
}
} }
public Object get(ResultSet rs, String name) throws HibernateException, SQLException { public void nullSafeSet(
Clob value = rs.getClob(name); PreparedStatement st,
return rs.wasNull() ? null : new SerializableClob(value); Object value,
int index,
SessionImplementor session) throws SQLException {
set( st, value, index, session );
}
public void set(
PreparedStatement st,
Object value,
int index,
SessionImplementor session) throws SQLException {
if ( value == null ) {
st.setNull( index, Types.CLOB );
return;
}
Clob clob = ( Clob ) value;
if ( WrappedClob.class.isInstance( clob ) ) {
clob = ( (WrappedClob) value ).getWrappedClob();
}
final boolean useInputStream = session.getFactory().getDialect().useInputStreamToInsertBlob()
&& ClobImplementer.class.isInstance( clob );
if ( useInputStream ) {
st.setCharacterStream( index, clob.getCharacterStream(), (int) clob.length() );
}
else {
st.setClob( index, clob );
}
}
public Object nullSafeGet(
ResultSet rs,
String name,
SessionImplementor session,
Object owner) throws SQLException {
return get( rs, name, Hibernate.getLobCreator( session ) );
}
public Object nullSafeGet(
ResultSet rs,
String[] names,
SessionImplementor session,
Object owner) throws SQLException {
return get( rs, names[0], Hibernate.getLobCreator( session ) );
}
/**
* A method to extract the CLOB value from a result set.
*
* @param rs The result set
* @param name The name of the column containing the CLOB
*
* @return The CLOB
*
* @throws SQLException Indicates a problem accessing the result set
*
* @deprecated Use {@link #get(ResultSet,String,LobCreator)} instead
*/
public Object get(ResultSet rs, String name) throws SQLException {
return get( rs, name, NonContextualLobCreator.INSTANCE );
}
public Clob get(ResultSet rs, String name, LobCreator lobCreator) throws SQLException {
Clob value = rs.getClob( name );
return rs.wasNull() ? null : lobCreator.wrap( value );
} }
public Class getReturnedClass() { public Class getReturnedClass() {
@ -123,29 +176,6 @@ public class ClobType extends AbstractType {
return false; return false;
} }
public Object nullSafeGet(ResultSet rs, String name,
SessionImplementor session, Object owner)
throws HibernateException, SQLException {
return get(rs, name);
}
public Object nullSafeGet(ResultSet rs, String[] names,
SessionImplementor session, Object owner)
throws HibernateException, SQLException {
return get( rs, names[0] );
}
public void nullSafeSet(PreparedStatement st, Object value, int index,
boolean[] settable, SessionImplementor session)
throws HibernateException, SQLException {
if ( settable[0] ) set(st, value, index, session);
}
public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException {
set(st, value, index, session);
}
public Object replace(Object original, Object target, public Object replace(Object original, Object target,
SessionImplementor session, Object owner, Map copyCache) SessionImplementor session, Object owner, Map copyCache)
throws HibernateException { throws HibernateException {

61
jdbc3-testing/pom.xml Normal file
View File

@ -0,0 +1,61 @@
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
~ third-party contributors as indicated by either @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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-parent</artifactId>
<version>3.5.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>hibernate-jdbc3-testing</artifactId>
<packaging>jar</packaging>
<name>JDBC3-JdbcSupport Testing</name>
<description>Test support of JDBC3 through JdbcSupport</description>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>hibernate-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.4-701.jdbc4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,74 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc.jdbc3;
import java.sql.SQLException;
import java.sql.Blob;
import java.sql.Clob;
import junit.framework.TestCase;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.JdbcSupportLoader;
import org.hibernate.engine.jdbc.BlobImplementer;
import org.hibernate.engine.jdbc.WrappedBlob;
import org.hibernate.engine.jdbc.WrappedClob;
import org.hibernate.engine.jdbc.ClobImplementer;
import org.hibernate.engine.jdbc.NClobImplementer;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class JdbcSupportTest extends TestCase {
public void testLobCreator() throws ClassNotFoundException, SQLException {
final LobCreationContext lobCreationContext = new LobCreationContext() {
public Object execute(Callback callback) {
fail( "Unexpeted call to getConnection" );
return null;
}
};
LobCreator lobCreator = JdbcSupportLoader.loadJdbcSupport( null ).getLobCreator( lobCreationContext );
Blob blob = lobCreator.createBlob( new byte[] {} );
assertTrue( blob instanceof BlobImplementer );
blob = lobCreator.wrap( blob );
assertTrue( blob instanceof WrappedBlob );
Clob clob = lobCreator.createClob( "Hi" );
assertTrue( clob instanceof ClobImplementer );
clob = lobCreator.wrap( clob );
assertTrue( clob instanceof WrappedClob );
Clob nclob = lobCreator.createNClob( "Hi" );
assertTrue( nclob instanceof NClobImplementer );
nclob = lobCreator.wrap( nclob );
assertTrue( nclob instanceof WrappedClob );
}
}

View File

@ -0,0 +1,30 @@
#
# Hibernate, Relational Persistence for Idiomatic Java
#
# Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
# third-party contributors as indicated by either @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
#
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.rootLogger=info, stdout

94
jdbc4-testing/pom.xml Normal file
View File

@ -0,0 +1,94 @@
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
~ third-party contributors as indicated by either @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
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-parent</artifactId>
<version>3.5.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<properties>
<!-- TODO : move this to local settings.xml -->
<jdbc4_jdk>/opt/java/jdk-1.6</jdbc4_jdk>
</properties>
<artifactId>hibernate-jdbc4-testing</artifactId>
<name>JDBC4-JdbcSupport Testing</name>
<description>Test support of JDBC4 through JdbcSupport</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<verbose>true</verbose>
<fork>true</fork>
<executable>${jdbc4_jdk}/bin/javac</executable>
<compilerVersion>1.6</compilerVersion>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<jvm>${jdbc4_jdk}/bin/java</jvm>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>hibernate-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.4-701.jdbc4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.1.0.7.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,276 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
* third-party contributors as indicated by either @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.engine.jdbc.jdbc4;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.NClob;
import junit.framework.TestCase;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.JdbcSupportLoader;
import org.hibernate.engine.jdbc.ContextualLobCreator;
import org.hibernate.engine.jdbc.BlobImplementer;
import org.hibernate.engine.jdbc.ClobImplementer;
import org.hibernate.engine.jdbc.NClobImplementer;
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.engine.jdbc.WrappedBlob;
import org.hibernate.engine.jdbc.WrappedClob;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class JdbcSupportTest extends TestCase {
private interface Envionment {
public String getDriver();
public String getUrl();
public String getUser();
public String getPass();
public void verifyCreator(LobCreator lobCreator);
public void verifyBlob(Blob blob);
public void verifyClob(Clob clob);
public void verifyNClob(Clob nclob);
}
private abstract class ContextualEnvironment implements Envionment {
public void verifyCreator(LobCreator lobCreator) {
assertTrue( lobCreator instanceof ContextualLobCreator );
}
public void verifyBlob(Blob blob) {
assertFalse( blob instanceof BlobImplementer );
}
public void verifyClob(Clob clob) {
assertFalse( clob instanceof ClobImplementer );
}
public void verifyNClob(Clob nclob) {
assertFalse( nclob instanceof NClobImplementer );
}
}
private abstract class NonContextualEnvironment implements Envionment {
public void verifyCreator(LobCreator lobCreator) {
assertTrue( lobCreator instanceof NonContextualLobCreator );
}
public void verifyBlob(Blob blob) {
assertTrue( blob instanceof BlobImplementer );
}
public void verifyClob(Clob clob) {
assertTrue( clob instanceof ClobImplementer );
}
public void verifyNClob(Clob nclob) {
assertTrue( nclob instanceof NClobImplementer );
}
}
private Envionment POSTGRESQL = new NonContextualEnvironment() {
public String getDriver() {
return "org.postgresql.Driver";
}
public String getUrl() {
return "jdbc:postgresql://vmg03.mw.lab.eng.bos.redhat.com:5432:platformae";
}
public String getUser() {
return "sebersole";
}
public String getPass() {
return "sebersole";
}
};
private Envionment MYSQL = new ContextualEnvironment() {
public String getDriver() {
return "com.mysql.jdbc.Driver";
}
public String getUrl() {
return "jdbc:mysql://vmg02.mw.lab.eng.bos.redhat.com/sebersole";
}
public String getUser() {
return "sebersole";
}
public String getPass() {
return "sebersole";
}
};
private Envionment ORACLE9i = new ContextualEnvironment() {
public String getDriver() {
return "oracle.jdbc.driver.OracleDriver";
}
public String getUrl() {
return "jdbc:oracle:thin:@dev20.qa.atl.jboss.com:1521:qa";
}
public String getUser() {
return "sebersole";
}
public String getPass() {
return "sebersole";
}
};
private Envionment ORACLE10g = new ContextualEnvironment() {
public String getDriver() {
return "oracle.jdbc.driver.OracleDriver";
}
public String getUrl() {
return "jdbc:oracle:thin:@vmg05.mw.lab.eng.bos.redhat.com:1521:qaora10";
}
public String getUser() {
return "sebersole";
}
public String getPass() {
return "sebersole";
}
};
private Envionment ORACLE11g = new ContextualEnvironment() {
public String getDriver() {
return "oracle.jdbc.driver.OracleDriver";
}
public String getUrl() {
return "jdbc:oracle:thin:@dev04.qa.atl2.redhat.com:1521:qaora11";
}
public String getUser() {
return "sebersole";
}
public String getPass() {
return "sebersole";
}
};
private Envionment ORACLE_RAC = new ContextualEnvironment() {
public String getDriver() {
return "oracle.jdbc.driver.OracleDriver";
}
public String getUrl() {
return "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(LOAD_BALANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=vmg24-vip.mw.lab.eng.bos.redhat.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=vmg25-vip.mw.lab.eng.bos.redhat.com)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=qarac.jboss))";
}
public String getUser() {
return "sebersole";
}
public String getPass() {
return "sebersole";
}
};
private Envionment envionment = ORACLE11g;
protected void setUp() throws Exception {
Class.forName( envionment.getDriver() );
}
public void testConnectedLobCreator() throws SQLException {
final Connection connection = DriverManager.getConnection( envionment.getUrl(), envionment.getUser(), envionment.getPass() );
final LobCreationContext lobCreationContext = new LobCreationContext() {
public Object execute(Callback callback) {
try {
return callback.executeOnConnection( connection );
}
catch ( SQLException e ) {
throw new RuntimeException( "Unexpected sql exception", e );
}
}
};
LobCreator lobCreator = JdbcSupportLoader.loadJdbcSupport( connection ).getLobCreator( lobCreationContext );
envionment.verifyCreator( lobCreator );
Blob blob = lobCreator.createBlob( new byte[] {} );
envionment.verifyBlob( blob );
blob = lobCreator.wrap( blob );
assertTrue( blob instanceof WrappedBlob );
Clob clob = lobCreator.createClob( "Hi" );
envionment.verifyClob( clob );
clob = lobCreator.wrap( clob );
assertTrue( clob instanceof WrappedClob );
Clob nclob = lobCreator.createNClob( "Hi" );
envionment.verifyNClob( nclob );
assertTrue( NClob.class.isInstance( nclob ) );
nclob = lobCreator.wrap( nclob );
assertTrue( nclob instanceof WrappedClob );
blob.free();
clob.free();
nclob.free();
connection.close();
}
public void testLegacyLobCreator() throws SQLException {
LobCreator lobCreator = JdbcSupportLoader.loadJdbcSupport( null ).getLobCreator();
Blob blob = lobCreator.createBlob( new byte[] {} );
assertTrue( blob instanceof BlobImplementer );
blob = lobCreator.wrap( blob );
assertTrue( blob instanceof WrappedBlob );
Clob clob = lobCreator.createClob( "Hi" );
assertTrue( clob instanceof ClobImplementer );
clob = lobCreator.wrap( clob );
assertTrue( clob instanceof WrappedClob );
Clob nclob = lobCreator.createNClob( "Hi" );
assertTrue( nclob instanceof NClobImplementer );
assertTrue( NClob.class.isInstance( nclob ) );
nclob = lobCreator.wrap( nclob );
assertTrue( nclob instanceof WrappedClob );
blob.free();
clob.free();
nclob.free();
}
}

View File

@ -0,0 +1,7 @@
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.rootLogger=info, stdout

View File

@ -118,10 +118,6 @@
<extensions>true</extensions> <extensions>true</extensions>
</plugin> </plugin>
<plugin> <plugin>
<!-- require at least JDK 1.5 to run the build -->
<!-- ... -->
<!-- we need at least Maven 2.0.8 because of a bug fix affecting our antlr usage -->
<!-- 2.0.8 not released at this time, so I instead say anything greater that 2.0.7 -->
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<executions> <executions>
@ -135,9 +131,12 @@
<configuration> <configuration>
<rules> <rules>
<requireJavaVersion> <requireJavaVersion>
<version>[1.5,)</version> <!-- require JDK 1.5 to run the build -->
<version>[1.5,1.6)</version>
</requireJavaVersion> </requireJavaVersion>
<requireMavenVersion> <requireMavenVersion>
<!-- we need at least Maven 2.0.8 because of a bug fix affecting our antlr usage -->
<!-- 2.0.8 not released at this time, so I instead say anything greater that 2.0.7 -->
<version>(2.0.7,)</version> <version>(2.0.7,)</version>
</requireMavenVersion> </requireMavenVersion>
</rules> </rules>

View File

@ -32,9 +32,10 @@
<module>jmx</module> <module>jmx</module>
<module>testing</module> <module>testing</module>
<module>testsuite</module> <module>testsuite</module>
<module>jdbc3-testing</module>
<module>jdbc4-testing</module>
<module>tutorials</module> <module>tutorials</module>
<module>hibernate-maven-plugin</module> <!--
<!--
Need to scope bytecode providers first... Need to scope bytecode providers first...
<module>bytecode-cglib</module> <module>bytecode-cglib</module>
<module>bytecode-javassist</module> <module>bytecode-javassist</module>