Author: gbadner
Date: 2008-10-29 01:38:54 -0400 (Wed, 29 Oct 2008)
New Revision: 15430
Added:
core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateExceptionConverterJDBC4.java
core/branches/Branch_3_2/src/org/hibernate/exception/TransactionRollbackException.java
core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapperProxy.java
core/branches/Branch_3_2/src/org/hibernate/lob/BlobImplProxy.java
core/branches/Branch_3_2/src/org/hibernate/lob/ClobImplProxy.java
core/branches/Branch_3_2/src/org/hibernate/lob/LobCreator.java
core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorFactory.java
core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC3.java
core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC4.java
core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlobProxy.java
core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClobProxy.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobFromLobCreatorTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobFromLobCreatorTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorDefaultTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3ConnRelOnCloseTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3Test.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4ConnRelOnCloseTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4Test.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorDefaultTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3ConnRelOnCloseTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3Test.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4ConnRelOnCloseTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4Test.java
Removed:
core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapper.java
Modified:
core/branches/Branch_3_2/etc/log4j.properties
core/branches/Branch_3_2/src/org/hibernate/Hibernate.java
core/branches/Branch_3_2/src/org/hibernate/cfg/Environment.java
core/branches/Branch_3_2/src/org/hibernate/cfg/Settings.java
core/branches/Branch_3_2/src/org/hibernate/cfg/SettingsFactory.java
core/branches/Branch_3_2/src/org/hibernate/dialect/Dialect.java
core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateConverter.java
core/branches/Branch_3_2/src/org/hibernate/jdbc/ColumnNameCache.java
core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java
core/branches/Branch_3_2/src/org/hibernate/lob/BlobImpl.java
core/branches/Branch_3_2/src/org/hibernate/lob/ClobImpl.java
core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlob.java
core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClob.java
core/branches/Branch_3_2/src/org/hibernate/type/BlobType.java
core/branches/Branch_3_2/src/org/hibernate/type/ClobType.java
core/branches/Branch_3_2/test/org/hibernate/test/AllTests.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobTest.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/LobHolder.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/MaterializedBlobType.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableData.java
core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableTypeTest.java
Log:
HHH-2412 : Make Hibernate compilable with JDK 1.6
Modified: core/branches/Branch_3_2/etc/log4j.properties
===================================================================
--- core/branches/Branch_3_2/etc/log4j.properties 2008-10-28 21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/etc/log4j.properties 2008-10-29 05:38:54 UTC (rev 15430)
@@ -21,11 +21,11 @@
#log4j.logger.org.hibernate.hql.ast.AST=debug
### log just the SQL
-#log4j.logger.org.hibernate.SQL=debug
+log4j.logger.org.hibernate.SQL=debug
### log JDBC bind parameters ###
-log4j.logger.org.hibernate.type=info
-#log4j.logger.org.hibernate.type=debug
+#log4j.logger.org.hibernate.type=info
+log4j.logger.org.hibernate.type=debug
### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=debug
Modified: core/branches/Branch_3_2/src/org/hibernate/Hibernate.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/Hibernate.java 2008-10-28 21:47:32 UTC (rev
15429)
+++ core/branches/Branch_3_2/src/org/hibernate/Hibernate.java 2008-10-29 05:38:54 UTC (rev
15430)
@@ -14,10 +14,8 @@
import org.hibernate.engine.HibernateIterator;
import org.hibernate.intercept.FieldInterceptionHelper;
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.lob.LobCreator;
+import org.hibernate.lob.LobCreatorFactory;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.type.AnyType;
@@ -348,13 +346,30 @@
}
/**
+ * If the setting for Environment#USE_CONNECTION_FOR_LOB_CREATION is true, then the
+ * returned LobCreator will use the Connection to create LOBs. If it is false, then
+ * the returned LobCreator will not use the Connection to create LOBs.
+ *
+ * If the property is not set, then the returned LobCreator will use the connection to
+ * create LOBs only if the JVM and JDBC driver support this JDBC4 functionality.
+ *
+ * (@see Environment#USE_CONNECTION_FOR_LOB_CREATION)
+ *
+ * @param session The session.
+ * @return the LobCreator
+ */
+ public static LobCreator getLobCreator(Session session) {
+ return LobCreatorFactory.createLobCreator( session );
+ }
+
+ /**
* Create a new <tt>Blob</tt>. The returned object will be initially
immutable.
*
* @param bytes a byte array
* @return the Blob
*/
public static Blob createBlob(byte[] bytes) {
- return new SerializableBlob( new BlobImpl( bytes ) );
+ return LobCreatorFactory.createLobCreator().createBlob( bytes );
}
/**
@@ -364,8 +379,8 @@
* @param length the number of bytes in the stream
* @return the Blob
*/
- public static Blob createBlob(InputStream stream, int length) {
- return new SerializableBlob( new BlobImpl( stream, length ) );
+ public static Blob createBlob(InputStream stream, int length) throws HibernateException,
IOException {
+ return LobCreatorFactory.createLobCreator().createBlob( stream, length );
}
/**
@@ -375,8 +390,8 @@
* @return the Blob
* @throws IOException
*/
- public static Blob createBlob(InputStream stream) throws IOException {
- return new SerializableBlob( new BlobImpl( stream, stream.available() ) );
+ public static Blob createBlob(InputStream stream) throws HibernateException, IOException
{
+ return LobCreatorFactory.createLobCreator().createBlob( stream, stream.available() );
}
/**
@@ -384,8 +399,8 @@
*
* @param string a <tt>String</tt>
*/
- public static Clob createClob(String string) {
- return new SerializableClob( new ClobImpl( string ) );
+ public static Clob createClob(String string) throws HibernateException {
+ return LobCreatorFactory.createLobCreator().createClob( string );
}
/**
@@ -394,8 +409,8 @@
* @param reader a character stream
* @param length the number of characters in the stream
*/
- public static Clob createClob(Reader reader, int length) {
- return new SerializableClob( new ClobImpl( reader, length ) );
+ public static Clob createClob(Reader reader, int length) throws HibernateException,
IOException {
+ return LobCreatorFactory.createLobCreator().createClob( reader, length );
}
/**
Modified: core/branches/Branch_3_2/src/org/hibernate/cfg/Environment.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/cfg/Environment.java 2008-10-28 21:47:32
UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/cfg/Environment.java 2008-10-29 05:38:54
UTC (rev 15430)
@@ -111,11 +111,16 @@
* this property when using user supplied connections)</td>
* </tr>
* <tr>
- * <td><tt>hibernate.jdbc.use_getGeneratedKeys</tt></td>
+ * <td><tt>hibernate.jdbc.use_get_generated_keys</tt></td>
* <td>enable use of JDBC3 PreparedStatement.getGeneratedKeys() to retrieve
* natively generated keys after insert. Requires JDBC3+ driver and JRE1.4+</td>
* </tr>
* <tr>
+ *
<td><tt>hibernate.jdbc.use_connection_for_lob_creation</tt></td>
+ * <td>enable use of JDBC4 Connection.createBlob() and Connection.createClob()
to
+ * create Blobs and Clobs. Requires JDBC4+ driver and JRE1.6+</td>
+ * </tr>
+ * <tr>
* <td><tt>hibernate.hbm2ddl.auto</tt></td>
* <td>enable auto DDL export</td>
* </tr>
@@ -262,6 +267,13 @@
*/
public static final String USE_GET_GENERATED_KEYS =
"hibernate.jdbc.use_get_generated_keys";
/**
+ * Tells the JDBC driver to attempt to create Blobs and Clobs using JDBC 4.0
+ * Connection.createBlob() and Connection.createClob(), respectively.
+ * Performance may be better if this property is set to true and the underlying JDBC
driver
+ * supports these Connection methods.
+ */
+ public static final String USE_CONNECTION_FOR_LOB_CREATION =
"hibernate.jdbc.use_connection_for_lob_creation";
+ /**
* Gives the JDBC driver a hint as to the number of rows that should be fetched from the
database
* when more rows are needed. If <tt>0</tt>, JDBC driver default settings
will be used.
*/
@@ -478,6 +490,7 @@
private static final boolean JVM_HAS_TIMESTAMP_BUG;
private static final boolean JVM_HAS_JDK14_TIMESTAMP;
private static final boolean JVM_SUPPORTS_GET_GENERATED_KEYS;
+ private static final boolean JVM_SUPPORTS_JDBC4;
private static final Properties GLOBAL_PROPERTIES;
private static final HashMap ISOLATION_LEVELS = new HashMap();
@@ -578,6 +591,18 @@
JVM_SUPPORTS_GET_GENERATED_KEYS = getGeneratedKeysSupport;
if (!JVM_SUPPORTS_GET_GENERATED_KEYS) log.info("JVM does not support
Statement.getGeneratedKeys()");
+ boolean jvmSupportsJDBC4;
+ try {
+ Connection.class.getMethod("createBlob", null);
+ Connection.class.getMethod("createClob", null);
+ jvmSupportsJDBC4 = true;
+ }
+ catch (NoSuchMethodException nsme) {
+ jvmSupportsJDBC4 = false;
+ }
+ JVM_SUPPORTS_JDBC4 = jvmSupportsJDBC4;
+ if (!JVM_SUPPORTS_JDBC4 ) log.info("JVM does not support JDBC4");
+
boolean linkedHashSupport;
try {
Class.forName("java.util.LinkedHashSet");
@@ -633,6 +658,10 @@
return JVM_SUPPORTS_GET_GENERATED_KEYS;
}
+ public static boolean jvmSupportsJDBC4() {
+ return JVM_SUPPORTS_JDBC4;
+ }
+
/**
* Should we use streams to bind binary types to JDBC IN parameters.
* Property <tt>hibernate.jdbc.use_streams_for_binary</tt>.
Modified: core/branches/Branch_3_2/src/org/hibernate/cfg/Settings.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/cfg/Settings.java 2008-10-28 21:47:32 UTC
(rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/cfg/Settings.java 2008-10-29 05:38:54 UTC
(rev 15430)
@@ -32,6 +32,7 @@
private int defaultBatchFetchSize;
private boolean scrollableResultSetsEnabled;
private boolean getGeneratedKeysEnabled;
+ private boolean useConnectionForLobCreationEnabled;
private String defaultSchemaName;
private String defaultCatalogName;
private Integer jdbcFetchSize;
@@ -124,6 +125,10 @@
return getGeneratedKeysEnabled;
}
+ public boolean isUseConnectionForLobCreationEnabled() {
+ return useConnectionForLobCreationEnabled;
+ }
+
public boolean isMinimalPutsEnabled() {
return minimalPutsEnabled;
}
@@ -319,6 +324,10 @@
getGeneratedKeysEnabled = b;
}
+ void setUseConnectionForLobCreationEnabled(boolean b) {
+ useConnectionForLobCreationEnabled = b;
+ }
+
void setJdbcFetchSize(Integer integer) {
jdbcFetchSize = integer;
}
Modified: core/branches/Branch_3_2/src/org/hibernate/cfg/SettingsFactory.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/cfg/SettingsFactory.java 2008-10-28
21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/cfg/SettingsFactory.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -71,6 +71,7 @@
boolean metaSupportsBatchUpdates = false;
boolean metaReportsDDLCausesTxnCommit = false;
boolean metaReportsDDLInTxnSupported = true;
+ boolean driverConnectionHasLobCreationMethods = false;
// 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value.
// The need for it is intended to be alleviated with 3.3 developement, thus it is
@@ -108,7 +109,31 @@
}
}
+ if ( Environment.jvmSupportsJDBC4() ) {
+ try {
+ // this block doesn't actually use the DatabaseMetaData, but it does use the
+ // driver Connection Class to determine if methods are present.
+ Class c = conn.getClass();
+ if ( Connection.class.equals( c.getMethod( "createBlob", null
).getDeclaringClass() ) ||
+ Connection.class.equals( c.getMethod( "createClob", null
).getDeclaringClass() ) ) {
+ driverConnectionHasLobCreationMethods = false;
+ }
+ else {
+ // the driver's Connection class has all three methods;
+ // can't tell if the driver actually supports these methods w/o calling
them,
+ // but don't want to actually create a LOB here.
+ driverConnectionHasLobCreationMethods = true;
+ }
+ }
+ catch (AbstractMethodError ame) {
+ driverConnectionHasLobCreationMethods = false;
+ }
+ catch (Exception e) {
+ driverConnectionHasLobCreationMethods = false;
+ }
+ }
}
+
finally {
connections.closeConnection(conn);
}
@@ -170,6 +195,10 @@
log.info("JDBC3 getGeneratedKeys(): " + enabledDisabled(useGetGeneratedKeys)
);
settings.setGetGeneratedKeysEnabled(useGetGeneratedKeys);
+ boolean useConnectionForLobCreation =
PropertiesHelper.getBoolean(Environment.USE_CONNECTION_FOR_LOB_CREATION, properties,
driverConnectionHasLobCreationMethods);
+ log.info("JDBC4 Connection.createBlob() and Connection.createClob(): " +
enabledDisabled(useConnectionForLobCreation) );
+ settings.setUseConnectionForLobCreationEnabled(useConnectionForLobCreation);
+
Integer statementFetchSize =
PropertiesHelper.getInteger(Environment.STATEMENT_FETCH_SIZE, properties);
if (statementFetchSize!=null) log.info("JDBC result set fetch size: " +
statementFetchSize);
settings.setJdbcFetchSize(statementFetchSize);
Modified: core/branches/Branch_3_2/src/org/hibernate/dialect/Dialect.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/dialect/Dialect.java 2008-10-28 21:47:32
UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/dialect/Dialect.java 2008-10-29 05:38:54
UTC (rev 15430)
@@ -1,4 +1,27 @@
//$Id$
+/*
+ * 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.dialect;
import java.sql.CallableStatement;
@@ -29,6 +52,7 @@
import org.hibernate.exception.SQLExceptionConverter;
import org.hibernate.exception.SQLStateConverter;
import org.hibernate.exception.ViolatedConstraintNameExtracter;
+import org.hibernate.exception.SQLStateExceptionConverterJDBC4;
import org.hibernate.id.IdentityGenerator;
import org.hibernate.id.SequenceGenerator;
import org.hibernate.id.TableHiLoGenerator;
@@ -1181,9 +1205,14 @@
*/
public SQLExceptionConverter buildSQLExceptionConverter() {
// The default SQLExceptionConverter for all dialects is based on SQLState
- // since SQLErrorCode is extremely vendor-specific. Specific Dialects
+ // since SQLErrorCode is extremely vendor-specific. If JDBC4 is supported,
+ // then the default SQLExceptionConverter will convert based on JDBC4
+ // SQLException if the SQLState is not recognized. Specific Dialects
// may override to return whatever is most appropriate for that vendor.
- return new SQLStateConverter( getViolatedConstraintNameExtracter() );
+ return ( Environment.jvmSupportsJDBC4() ?
+ new SQLStateExceptionConverterJDBC4( getViolatedConstraintNameExtracter() ) :
+ new SQLStateConverter( getViolatedConstraintNameExtracter() )
+ );
}
private static final ViolatedConstraintNameExtracter EXTRACTER = new
ViolatedConstraintNameExtracter() {
Modified: core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateConverter.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateConverter.java 2008-10-28
21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateConverter.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -24,6 +24,7 @@
private static final Set DATA_CATEGORIES = new HashSet();
private static final Set INTEGRITY_VIOLATION_CATEGORIES = new HashSet();
private static final Set CONNECTION_CATEGORIES = new HashSet();
+ private static final Set TRANSACTION_ROLLBACK_CATEGORIES = new HashSet();
static {
SQL_GRAMMAR_CATEGORIES.add( "07" );
@@ -42,12 +43,19 @@
INTEGRITY_VIOLATION_CATEGORIES.add( "44" );
CONNECTION_CATEGORIES.add( "08" );
+ CONNECTION_CATEGORIES.add( "28" );
+
+ TRANSACTION_ROLLBACK_CATEGORIES.add( "40" );
}
public SQLStateConverter(ViolatedConstraintNameExtracter extracter) {
this.extracter = extracter;
}
+ protected String getViolatedConstraintName(SQLException sqlException) {
+ return extracter.extractConstraintName( sqlException );
+ }
+
/**
* Convert the given SQLException into Hibernate's JDBCException hierarchy.
*
@@ -67,7 +75,7 @@
return new SQLGrammarException( message, sqlException, sql );
}
else if ( INTEGRITY_VIOLATION_CATEGORIES.contains( sqlStateClassCode ) ) {
- String constraintName = extracter.extractConstraintName( sqlException );
+ String constraintName = getViolatedConstraintName( sqlException );
return new ConstraintViolationException( message, sqlException, sql, constraintName
);
}
else if ( CONNECTION_CATEGORIES.contains( sqlStateClassCode ) ) {
@@ -76,6 +84,9 @@
else if ( DATA_CATEGORIES.contains( sqlStateClassCode ) ) {
return new DataException( message, sqlException, sql );
}
+ else if ( TRANSACTION_ROLLBACK_CATEGORIES.contains( sqlStateClassCode ) ) {
+ return new TransactionRollbackException( message, sqlException, sql );
+ }
}
if ( "40001".equals( sqlState ) ) {
Added:
core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateExceptionConverterJDBC4.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateExceptionConverterJDBC4.java
(rev 0)
+++
core/branches/Branch_3_2/src/org/hibernate/exception/SQLStateExceptionConverterJDBC4.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,87 @@
+// $Id: $
+/*
+ * 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.exception;
+
+import org.hibernate.JDBCException;
+
+import java.sql.SQLException;
+
+/**
+ * A SQLExceptionConverter implementation which performs converion based on
+ * the underlying SQLState. Interpretation of a SQL error based on SQLState
+ * is not nearly as accurate as using the ErrorCode (which is, however, vendor-
+ * specific). Use of a ErrorCode-based converter should be preferred approach
+ * for converting/interpreting SQLExceptions.
+ *
+ * @author Gail Badner
+ */
+public class SQLStateExceptionConverterJDBC4 extends SQLStateConverter {
+
+ public SQLStateExceptionConverterJDBC4(ViolatedConstraintNameExtracter extracter) {
+ super( extracter );
+ }
+
+ /**
+ * Convert the given SQLException into Hibernate's JDBCException hierarchy.
+ *
+ * @param sqlException The SQLException to be converted.
+ * @param message An optional error message.
+ * @param sql Optionally, the sql being performed when the exception occurred.
+ * @return The resulting JDBCException.
+ */
+ public JDBCException convert(SQLException sqlException, String message, String sql) {
+ JDBCException jdbcException = super.convert( sqlException, message, sql );
+ if ( !( jdbcException instanceof GenericJDBCException) ) {
+ return jdbcException;
+ }
+
+ try {
+ if ( Class.forName( "java.sql.SQLIntegrityConstraintViolationException"
).isInstance( sqlException ) ) {
+ String constraintName = getViolatedConstraintName( sqlException );
+ return new ConstraintViolationException( message, sqlException, sql, constraintName
);
+ }
+ else if ( Class.forName( "java.sql.SQLTransactionRollbackException"
).isInstance( sqlException ) ) {
+ return new TransactionRollbackException( message, sqlException, sql );
+ }
+ else if ( Class.forName( "java.sql.SQLClientInfoException" ).isInstance(
sqlException ) ||
+ Class.forName( "java.sql.SQLInvalidAuthorizationSpecException"
).isInstance( sqlException ) ||
+ Class.forName( "java.sql.SQLNonTransientConnectionException" ).isInstance(
sqlException ) ||
+ Class.forName( "java.sql.SQLTransientConnectionException" ).isInstance(
sqlException ) ) {
+ return new JDBCConnectionException( message, sqlException, sql );
+ }
+ else if ( Class.forName( "java.sql.SQLSyntaxErrorException" ).isInstance(
sqlException ) ) {
+ return new SQLGrammarException( message, sqlException, sql );
+ }
+ else if ( Class.forName( "java.sql.SQLDataException" ).isInstance(
sqlException ) ||
+ Class.forName( "javax.sql.rowset.serial.SerialException" ).isInstance(
sqlException ) ) {
+ return new DataException( message, sqlException, sql );
+ }
+ }
+ catch ( ClassNotFoundException e ) {
+ // log because either config is messed up or there's a typo in a class name
+ }
+ return jdbcException;
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_2/src/org/hibernate/exception/TransactionRollbackException.java
===================================================================
---
core/branches/Branch_3_2/src/org/hibernate/exception/TransactionRollbackException.java
(rev 0)
+++
core/branches/Branch_3_2/src/org/hibernate/exception/TransactionRollbackException.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,59 @@
+// $Id: $
+/*
+ * 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.exception;
+
+import org.hibernate.JDBCException;
+
+import java.sql.SQLException;
+
+/**
+ * Implementation of JDBCException that indicates that the current statement
+ * was automatically rolled back by the database becuase of deadlock or other
+ * transaction serialization failures.
+ *
+ * @author Gail Badner
+ */
+public class TransactionRollbackException extends JDBCException {
+ /**
+ * Constructor for TransactionRollbackException.
+ *
+ * @param message Optional message.
+ * @param root The underlying exception.
+ */
+ public TransactionRollbackException(String message, SQLException root) {
+ super( message, root );
+ }
+
+ /**
+ * Constructor for TransactionRollbackException.
+ *
+ * @param message Optional message.
+ * @param root The underlying exception.
+ * @param sql the SQL statement involved in the exception.
+ */
+ public TransactionRollbackException(String message, SQLException root, String sql) {
+ super( message, root, sql );
+ }
+}
\ No newline at end of file
Modified: core/branches/Branch_3_2/src/org/hibernate/jdbc/ColumnNameCache.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/jdbc/ColumnNameCache.java 2008-10-28
21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/jdbc/ColumnNameCache.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -1,7 +1,31 @@
// $Id$
+/*
+ * 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.sql.SQLException;
+import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;
@@ -19,13 +43,13 @@
this.columnNameToIndexCache = new HashMap( columnCount );
}
- public int getIndexForColumnName(String columnName, ResultSetWrapper rs)throws
SQLException {
+ public int getIndexForColumnName(String columnName, ResultSet rs) throws SQLException {
Integer cached = ( Integer ) columnNameToIndexCache.get( columnName );
if ( cached != null ) {
return cached.intValue();
}
else {
- int index = rs.getTarget().findColumn( columnName );
+ int index = rs.findColumn( columnName );
columnNameToIndexCache.put( columnName, new Integer(index) );
return index;
}
Deleted: core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapper.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapper.java 2008-10-28
21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapper.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -1,619 +0,0 @@
-// $Id$
-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);
- }
-}
-
Added: core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapperProxy.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapperProxy.java
(rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/jdbc/ResultSetWrapperProxy.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,170 @@
+//$Id: $
+/*
+ * 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.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.InvocationTargetException;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+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 Gail Badner
+ */
+public class ResultSetWrapperProxy implements InvocationHandler {
+
+ private static final Class[] PROXY_INTERFACES = new Class[] { ResultSet.class };
+ private static final Log log = LogFactory.getLog( ResultSetWrapperProxy.class );
+
+ private final ResultSet rs;
+ private 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 )
+ );
+ }
+
+ private ResultSetWrapperProxy(ResultSet resultSet, ColumnNameCache columnNameCache) {
+ this.rs = resultSet;
+ this.columnNameCache = columnNameCache;
+ }
+
+ /**
+ * 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 java.sql.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, rs );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if ( isFirstArgColumnLabel( method, args ) ) {
+ try {
+ int columnIndex = findColumn( ( String ) args[0] );
+ return invokeMethod( getMethodUsingColumnIndex( method ), getArgsUsingColumnIndex(
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 );
+ }
+
+ private boolean isFirstArgColumnLabel(Method method, Object args[]) {
+ return method.getParameterTypes().length > 0 &&
+ method.getParameterTypes()[ 0 ].equals( String.class ) &&
+ args.length == method.getParameterTypes().length &&
+ String.class.isInstance( args[ 0 ] ) &&
+ ( method.getName().startsWith( "get" ) || method.getName().startsWith(
"update" ) );
+ }
+
+ private Method getMethodUsingColumnIndex(Method method) throws NoSuchMethodException {
+ Class actualParameterTypes[] = new Class[ method.getParameterTypes().length ];
+ actualParameterTypes[0] = int.class;
+ System.arraycopy( method.getParameterTypes(), 1, actualParameterTypes, 1,
method.getParameterTypes().length - 1 );
+ return method.getDeclaringClass().getMethod( method.getName(), actualParameterTypes );
+ }
+
+ private Object[] getArgsUsingColumnIndex( Object[] args, int columnIndex ) {
+ Object actualArgs[] = new Object[ args.length ];
+ actualArgs[0] = new Integer( columnIndex );
+ System.arraycopy( args, 1, actualArgs, 1, args.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();
+ }
+ }
+
+ /**
+ * 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;
+ }
+}
\ No newline at end of file
Modified: core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java 2008-10-28 21:47:32 UTC
(rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/loader/Loader.java 2008-10-29 05:38:54 UTC
(rev 15430)
@@ -48,7 +48,7 @@
import org.hibernate.impl.FetchingScrollableResultsImpl;
import org.hibernate.impl.ScrollableResultsImpl;
import org.hibernate.jdbc.ColumnNameCache;
-import org.hibernate.jdbc.ResultSetWrapper;
+import org.hibernate.jdbc.ResultSetWrapperProxy;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable;
@@ -1814,7 +1814,7 @@
if ( session.getFactory().getSettings().isWrapResultSetsEnabled() ) {
try {
log.debug("Wrapping result set [" + rs + "]");
- return new ResultSetWrapper( rs, retreiveColumnNameToIndexCache( rs ) );
+ return ResultSetWrapperProxy.generateProxy( rs, retreiveColumnNameToIndexCache( rs )
);
}
catch(SQLException e) {
log.info("Error wrapping result set", e);
Modified: core/branches/Branch_3_2/src/org/hibernate/lob/BlobImpl.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/BlobImpl.java 2008-10-28 21:47:32 UTC
(rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/BlobImpl.java 2008-10-29 05:38:54 UTC
(rev 15430)
@@ -1,113 +1,34 @@
//$Id$
+/*
+ * 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");
- }
-
-}
-
-
-
-
-
-
+public interface BlobImpl extends Blob {
+}
\ No newline at end of file
Added: core/branches/Branch_3_2/src/org/hibernate/lob/BlobImplProxy.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/BlobImplProxy.java
(rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/BlobImplProxy.java 2008-10-29 05:38:54
UTC (rev 15430)
@@ -0,0 +1,148 @@
+//$Id: $
+/*
+ * 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.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;
+
+/**
+ * A proxy for a dummy implementation of <tt>java.sql.Blob</tt> that
+ * is used to insert new data into a Blob when the Connection is not used
+ * for creating new Blobs.
+ *
+ * This implementation provides minimal functionality for creating a
+ * new Blob. The only operations that are supported are {@link #length()}
+ * and {@link #getBinaryStream()}. All other operations will throw
+ * UnsupportedOperationException.
+ *
+ * The proxy extends BlobImpl so that it can be distinguished from a Blob.
+ *
+ * @author Gail Badner
+ */
+public class BlobImplProxy implements InvocationHandler {
+
+ private static final Class[] PROXY_INTERFACES = new Class[] { BlobImpl.class };
+
+ private InputStream stream;
+ private int length;
+ private boolean needsReset = false;
+
+ /**
+ * 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 BlobImplProxy( 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, int length) {
+ return ( Blob ) Proxy.newProxyInstance(
+ getProxyClassLoader(),
+ PROXY_INTERFACES,
+ new BlobImplProxy( stream, length )
+ );
+ }
+
+ private BlobImplProxy(byte[] bytes) {
+ this.stream = new ByteArrayInputStream(bytes);
+ this.length = bytes.length;
+ }
+
+ private BlobImplProxy(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#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;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedOperationException if any methods other than {@link #length()}
+ * or {@link #getBinaryStream} are invoked.
+ */
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if ( "length".equals( method.getName() ) ) {
+ return new Long( length() );
+ }
+ if ( "getBinaryStream".equals( method.getName() ) &&
method.getParameterTypes().length == 0) {
+ return getBinaryStream();
+ }
+ throw new UnsupportedOperationException("Blob may not be manipulated from creating
session");
+ }
+
+ /**
+ * 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 = BlobImpl.class.getClassLoader();
+ }
+ return cl;
+ }
+}
\ No newline at end of file
Modified: core/branches/Branch_3_2/src/org/hibernate/lob/ClobImpl.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/ClobImpl.java 2008-10-28 21:47:32 UTC
(rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/ClobImpl.java 2008-10-29 05:38:54 UTC
(rev 15430)
@@ -1,137 +1,34 @@
//$Id$
+/*
+ * 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");
- }
-
-}
-
-
-
-
-
-
+public interface ClobImpl extends Clob {
+}
\ No newline at end of file
Added: core/branches/Branch_3_2/src/org/hibernate/lob/ClobImplProxy.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/ClobImplProxy.java
(rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/ClobImplProxy.java 2008-10-29 05:38:54
UTC (rev 15430)
@@ -0,0 +1,165 @@
+//$Id: $
+/*
+ * 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.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.SQLException;
+import java.sql.Clob;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+/**
+ * A proxy for a dummy implementation of <tt>java.sql.Clob</tt> that
+ * is used to insert new data into a Clob when the Connection is not used
+ * for creating new Clobs.
+ *
+ * This implementation provides minimal functionality for creating a
+ * new Clob. The only operations that are supported are {@link #length()},
+ * {@link #getAsciiStream()}, and {@link #getCharacterStream()}. All other
+ * operations will throw UnsupportedOperationException.
+ *
+ * The proxy extends ClobImpl so that it can be distinguished from a Clob.
+ *
+ * @author Gail Badner
+ */
+public class ClobImplProxy implements InvocationHandler {
+
+ private static final Class[] PROXY_INTERFACES = new Class[] { ClobImpl.class };
+
+ private Reader reader;
+ private int length;
+ private boolean needsReset = false;
+
+ /**
+ * Generates a BlobImpl proxy using a String.
+ *
+ * @param string The data to be created as a Clob.
+ * @return The generated proxy.
+ */
+ public static Clob generateProxy(String string) {
+ return ( Clob ) Proxy.newProxyInstance(
+ getProxyClassLoader(),
+ PROXY_INTERFACES,
+ new ClobImplProxy( string )
+ );
+ }
+
+ /**
+ * Generates a ClobImpl proxy using a given number of characters from a Reader.
+ *
+ * @param reader The Reader for character data to be created as a Clob.
+ * @param length The number of characters from Reader to be written to the Clob.
+ * @return The generated proxy.
+ */
+ public static Clob generateProxy(Reader reader, int length) {
+ return ( Clob ) Proxy.newProxyInstance(
+ getProxyClassLoader(),
+ PROXY_INTERFACES,
+ new ClobImplProxy( reader, length )
+ );
+ }
+
+ private ClobImplProxy(String string) {
+ reader = new StringReader(string);
+ length = string.length();
+ }
+
+ private ClobImplProxy(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#getAsciiStream()
+ */
+ public InputStream getAsciiStream() throws SQLException {
+ reset();
+ return new ReaderInputStream(reader);
+ }
+
+ /**
+ * @see java.sql.Clob#getCharacterStream()
+ */
+ public Reader getCharacterStream() throws SQLException {
+ reset();
+ return reader;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws UnsupportedOperationException if any methods other than {@link #length()},
+ * {@link #getAsciiStream()}, or {@link #getCharacterStream()} are invoked.
+ */
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if ( "length".equals( method.getName() ) ) {
+ return new Long( length() );
+ }
+ if ( "getAsciiStream".equals( method.getName() ) ) {
+ return getAsciiStream();
+ }
+ if ( "getCharacterStream".equals( method.getName() ) ) {
+ return getCharacterStream();
+ }
+ throw new UnsupportedOperationException("Clob may not be manipulated from creating
session");
+ }
+
+ /**
+ * 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 = ClobImpl.class.getClassLoader();
+ }
+ return cl;
+ }
+
+
+ private void reset() throws SQLException {
+ try {
+ if (needsReset) reader.reset();
+ }
+ catch (IOException ioe) {
+ throw new SQLException("could not reset reader");
+ }
+ needsReset = true;
+ }
+}
\ No newline at end of file
Added: core/branches/Branch_3_2/src/org/hibernate/lob/LobCreator.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/LobCreator.java
(rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/LobCreator.java 2008-10-29 05:38:54 UTC
(rev 15430)
@@ -0,0 +1,96 @@
+//$Id: $
+/*
+ * 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.sql.Clob;
+import java.sql.Blob;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.IOException;
+
+import org.hibernate.HibernateException;
+
+/**
+ * This interface defines the API for creating Blobs and Clobs.
+ *
+ * @author Gail Badner
+ */
+public interface LobCreator {
+
+ /**
+ * Returns a Blob object representing a SQL BLOB created from the given array of bytes.
+ *
+ * @param bytes The array of bytes to be written to this BLOB object.
+ * @return the created Blob
+ * @throws HibernateException if the Blob could not be created
+ */
+ Blob createBlob(byte[] bytes) throws HibernateException;
+
+ /**
+ * Returns a Blob object representing a SQL BLOB created from the given number of bytes
+ * from an InputStream.
+ *
+ * @param is The input stream of bytes to be written to this BLOB object.
+ * @param length The number of bytes from stream to be written to this BLOB object.
+ * @return the created Blob
+ * @throws HibernateException if the Blob could not be created
+ * @throws IOException if an I/O error occurs
+ */
+ Blob createBlob(InputStream is, int length) throws HibernateException, IOException;
+
+
+ /**
+ * Returns a Blob object representing a SQL BLOB created from the available
(is.available())
+ * number of bytes from an InputStream.
+ *
+ * @param is The input stream of bytes to be written to this BLOB object.
+ * @return the created Blob
+ * @throws HibernateException if the Blob could not be created
+ * @throws IOException if an I/O error occurs
+ */
+ Blob createBlob(InputStream is) throws HibernateException, IOException;
+
+ /**
+ * Returns a Clob object representing a SQL CLOB created from the given String.
+ *
+ * @param string The String to be written to this CLOB object
+ * @throws HibernateException if the Clob could not be created
+ * @throws HibernateException
+ */
+ Clob createClob(String string) throws HibernateException;
+
+ /**
+ * Returns a Clob object representing a SQL CLOB created from the given number of
+ * characters from a character stream.
+ *
+ * @param reader The character stream to be written to this CLOB object.
+ * @param length The number of characters from reader to be written to this CLOB
object.
+ * @return the created Clob
+ * @throws HibernateException if the Clob could not be created
+ * @throws IOException if an I/O error occurs
+ */
+ Clob createClob(Reader reader, int length) throws HibernateException, IOException;
+}
\ No newline at end of file
Added: core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorFactory.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorFactory.java
(rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorFactory.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,75 @@
+//$Id: $
+/*
+ * 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 org.hibernate.Session;
+import org.hibernate.AssertionFailure;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+/**
+ * A factory for creating an instance of the appropriate LobCreator implementation.
+ *
+ * @author Gail Badner
+ */
+public class LobCreatorFactory {
+
+ /**
+ * Creates an instance of a LobCreator that does not use the Connection to create LOBs.
+ * The returned LobCreator is appropriate for JVM and/or JDBC drivers that support
JDBC3,
+ * but not JDBC4.
+ *
+ * @return the LobCreator
+ */
+ public static LobCreator createLobCreator() {
+ return new LobCreatorImplJDBC3();
+ }
+
+ /**
+ * If the setting for Environment#USE_CONNECTION_FOR_LOB_CREATION is true, then the
+ * returned LobCreator will use the Connection to create LOBs. If it is false, then
+ * the returned LobCreator will not use the Connection to create LOBs.
+ *
+ * If the property is not set, then the returned LobCreator will use the connection to
+ * create LOBs only if the JVM and JDBC driver support this JDBC4 functionality.
+ *
+ * (@see Environment#USE_CONNECTION_FOR_LOB_CREATION)
+ *
+ * @param session The session.
+ * @return the LobCreator
+ */
+ public static LobCreator createLobCreator(Session session) {
+ if ( session == null ) {
+ throw new AssertionFailure("session is null; use
LobCreatorFactory.createLobCreator() instead.");
+ }
+ SessionFactoryImplementor sfi = ( SessionFactoryImplementor )
session.getSessionFactory();
+ if ( sfi.getSettings().isUseConnectionForLobCreationEnabled() ) {
+ return new LobCreatorImplJDBC4( session );
+ }
+ else {
+ return new LobCreatorImplJDBC3();
+ }
+ }
+}
\ No newline at end of file
Added: core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC3.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC3.java
(rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC3.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,79 @@
+//$Id: $
+/*
+ * 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.sql.Blob;
+import java.sql.Clob;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.IOException;
+
+/**
+ * A LobCreator implementation that can be used with JVMs and JDBC drivers that support
JDBC3.
+ *
+ * @author Gail Badner
+ */
+public class LobCreatorImplJDBC3 implements LobCreator {
+
+ /* package */
+ LobCreatorImplJDBC3() {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Blob createBlob(byte[] bytes) {
+ return SerializableBlobProxy.generateProxy( BlobImplProxy.generateProxy( bytes ) );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Blob createBlob(InputStream is, int length) {
+ return SerializableBlobProxy.generateProxy( BlobImplProxy.generateProxy( is, length )
);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Blob createBlob(InputStream is) throws IOException {
+ return SerializableBlobProxy.generateProxy( BlobImplProxy.generateProxy( is,
is.available() ) );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Clob createClob(String string) {
+ return SerializableClobProxy.generateProxy( ClobImplProxy.generateProxy( string ) );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Clob createClob(Reader reader, int length) {
+ return SerializableClobProxy.generateProxy( ClobImplProxy.generateProxy( reader, length
) );
+ }
+}
Added: core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC4.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC4.java
(rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/LobCreatorImplJDBC4.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,195 @@
+// $Id: $
+/*
+ * 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.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+import org.hibernate.Session;
+import org.hibernate.HibernateException;
+import org.hibernate.cfg.Environment;
+import org.hibernate.exception.JDBCExceptionHelper;
+import org.hibernate.engine.SessionImplementor;
+
+/**
+ * A LobCreator implementation that can be used with JVMs and JDBC drivers that support
JDBC4.
+ *
+ * @author Gail Badner
+ */
+public class LobCreatorImplJDBC4 implements LobCreator {
+ private final SessionImplementor session;
+
+ /* package */
+ LobCreatorImplJDBC4(Session session) {
+ this.session = ( SessionImplementor ) session;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Blob createBlob(byte[] bytes) throws HibernateException {
+ Blob blob = createBlob();
+ try {
+ blob.setBytes( 1, bytes );
+ }
+ catch ( SQLException e ) {
+ throw JDBCExceptionHelper.convert(
+ session.getFactory().getSQLExceptionConverter(),
+ e,
+ "Exception invoking adding data to a Blob."
+ );
+ }
+ return blob;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Blob createBlob(InputStream is, int length) throws HibernateException,
IOException {
+ Blob blob = createBlob();
+ try {
+ OutputStream os = blob.setBinaryStream(1);
+ byte[] data = new byte[1];
+ for ( int i = 0; i < length && is.read( data ) != -1; i++ ) {
+ os.write( data );
+ }
+ os.flush();
+ os.close();
+ return blob;
+ }
+ catch ( SQLException e ) {
+ throw JDBCExceptionHelper.convert(
+ session.getFactory().getSQLExceptionConverter(),
+ e,
+ "Exception getting OutputStream to add data to a Blob."
+ );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Blob createBlob(InputStream is) throws HibernateException, IOException {
+ return createBlob( is, is.available() );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Clob createClob(String string) throws HibernateException {
+ Clob clob = createClob();
+ try {
+ clob.setString( 1, string );
+ return clob;
+ }
+ catch ( SQLException e ) {
+ throw JDBCExceptionHelper.convert(
+ session.getFactory().getSQLExceptionConverter(),
+ e,
+ "Exception adding a String to a Clob."
+ );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Clob createClob(Reader reader, int length) throws HibernateException, IOException
{
+ Clob clob = createClob();
+ try {
+ Writer writer = clob.setCharacterStream( 1 );
+ char[] data = new char[1];
+ for ( int i = 0; i < length && reader.read( data ) != -1; i++ ) {
+ writer.write( data );
+ }
+ writer.flush();
+ writer.close();
+ return clob;
+ }
+ catch ( SQLException e ) {
+ throw JDBCExceptionHelper.convert(
+ session.getFactory().getSQLExceptionConverter(),
+ e,
+ "Exception getting OutputStream to add data to a Clob."
+ );
+ }
+ }
+
+ private Blob createBlob() {
+ final String CREATE_BLOB_METHOD_NAME = "createBlob";
+ return ( Blob ) invokeConnectionMethod( CREATE_BLOB_METHOD_NAME );
+ }
+
+ private Clob createClob() {
+ final String CREATE_CLOB_METHOD_NAME = "createClob";
+ return ( Clob ) invokeConnectionMethod( CREATE_CLOB_METHOD_NAME );
+ }
+
+ private Object invokeConnectionMethod(String methodName) throws HibernateException {
+ Connection connection =
session.getJDBCContext().getConnectionManager().getConnection();
+ final Object emptyArray[] = { };
+ try {
+ Method method = Connection.class.getMethod( methodName, new Class[0] );
+ Object object = method.invoke( connection, emptyArray );
+ session.getJDBCContext().getConnectionManager().afterStatement();
+ return object;
+ }
+ catch ( NoSuchMethodException e ) {
+ throw new HibernateException( getMethodString( connection, methodName ) + " not
supported. Set " + Environment.USE_CONNECTION_FOR_LOB_CREATION + " to
false.", e );
+ }
+ catch ( AbstractMethodError e ) {
+ throw new HibernateException( "Implementation of " + getMethodString(
connection, methodName ) + " not found. Set " +
Environment.USE_CONNECTION_FOR_LOB_CREATION + " to false.", e );
+ }
+ catch ( InvocationTargetException e ) {
+ if ( e.getTargetException() instanceof SQLException ) {
+ throw JDBCExceptionHelper.convert(
+ session.getFactory().getSQLExceptionConverter(),
+ ( SQLException ) e.getTargetException(),
+ "Exception invoking " + getMethodString( connection, methodName )
+ );
+ }
+ throw new HibernateException( "Exception invoking " + getMethodString(
connection, methodName ), e.getTargetException() );
+ }
+ catch ( IllegalAccessException e ) {
+ throw new HibernateException( "Cannot access " + getMethodString(
connection, methodName ), e );
+ }
+ }
+
+ private String getMethodString(Connection connection, String methodName) {
+ return new StringBuffer()
+ .append( connection.getClass().getName() )
+ .append('.')
+ .append( methodName )
+ .append( "()" ).toString();
+ }
+}
Modified: core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlob.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlob.java 2008-10-28
21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlob.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -1,66 +1,35 @@
//$Id$
+/*
+ * 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);
- }
-
-}
+public interface SerializableBlob extends Serializable, Blob {
+ public Blob getWrappedBlob();
+}
\ No newline at end of file
Added: core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlobProxy.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlobProxy.java
(rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/SerializableBlobProxy.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,104 @@
+// $Id: $
+/*
+ * 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.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.InvocationTargetException;
+import java.sql.Blob;
+import org.hibernate.HibernateException;
+
+/**
+ * A proxy for SerializableBlob objects which delegates all Blob methods to
+ * a wrapped Blob.
+ *
+ * @author Gail Badner
+ */
+public class SerializableBlobProxy implements InvocationHandler {
+
+ private static final Class[] PROXY_INTERFACES = new Class[] { SerializableBlob.class };
+
+ private transient final Blob blob;
+
+ /**
+ * 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 )
+ );
+ }
+
+ 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();
+ }
+ }
+
+ /**
+ * 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 = SerializableBlob.class.getClassLoader();
+ }
+ return cl;
+ }
+}
Modified: core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClob.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClob.java 2008-10-28
21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClob.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -1,76 +1,36 @@
//$Id$
+/*
+ * 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 {
+public interface SerializableClob extends 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);
- }
-
+ public Clob getWrappedClob();
}
Added: core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClobProxy.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClobProxy.java
(rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/lob/SerializableClobProxy.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,105 @@
+// $Id: $
+/*
+ * 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.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Clob;
+
+import org.hibernate.HibernateException;
+
+/**
+ * A proxy for SerializableClob objects which delegates all Clob methods to
+ * a wrapped Clob.
+ *
+ * @author Gail Badner
+ */
+public class SerializableClobProxy implements InvocationHandler {
+
+ private static final Class[] PROXY_INTERFACES = new Class[] { SerializableClob.class };
+
+ private transient final Clob clob;
+
+ /**
+ * Generates a SerializableClob 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 )
+ );
+ }
+
+ private 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();
+ }
+ }
+
+ /**
+ * 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 = Clob.class.getClassLoader();
+ }
+ return cl;
+ }
+}
Modified: core/branches/Branch_3_2/src/org/hibernate/type/BlobType.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/type/BlobType.java 2008-10-28 21:47:32 UTC
(rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/type/BlobType.java 2008-10-29 05:38:54 UTC
(rev 15430)
@@ -1,4 +1,28 @@
//$Id$
+/*
+ * 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.type;
import java.io.Serializable;
@@ -18,6 +42,7 @@
import org.hibernate.engine.SessionImplementor;
import org.hibernate.lob.BlobImpl;
import org.hibernate.lob.SerializableBlob;
+import org.hibernate.lob.SerializableBlobProxy;
import org.hibernate.util.ArrayHelper;
/**
@@ -55,7 +80,7 @@
public Object get(ResultSet rs, String name) throws HibernateException, SQLException {
Blob value = rs.getBlob(name);
- return rs.wasNull() ? null : new SerializableBlob(value);
+ return rs.wasNull() ? null : SerializableBlobProxy.generateProxy(value);
}
public Class getReturnedClass() {
Modified: core/branches/Branch_3_2/src/org/hibernate/type/ClobType.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/type/ClobType.java 2008-10-28 21:47:32 UTC
(rev 15429)
+++ core/branches/Branch_3_2/src/org/hibernate/type/ClobType.java 2008-10-29 05:38:54 UTC
(rev 15430)
@@ -1,4 +1,28 @@
//$Id$
+/*
+ * 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.type;
import java.io.Serializable;
@@ -19,6 +43,7 @@
import org.hibernate.engine.SessionImplementor;
import org.hibernate.lob.ClobImpl;
import org.hibernate.lob.SerializableClob;
+import org.hibernate.lob.SerializableClobProxy;
import org.hibernate.util.ArrayHelper;
/**
@@ -56,7 +81,7 @@
public Object get(ResultSet rs, String name) throws HibernateException, SQLException {
Clob value = rs.getClob(name);
- return rs.wasNull() ? null : new SerializableClob(value);
+ return rs.wasNull() ? null : SerializableClobProxy.generateProxy(value);
}
public Class getReturnedClass() {
Modified: core/branches/Branch_3_2/test/org/hibernate/test/AllTests.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/AllTests.java 2008-10-28 21:47:32 UTC
(rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/AllTests.java 2008-10-29 05:38:54 UTC
(rev 15430)
@@ -146,7 +146,17 @@
import org.hibernate.test.legacy.SQLLoaderTest;
import org.hibernate.test.legacy.StatisticsTest;
import org.hibernate.test.lob.BlobTest;
+import org.hibernate.test.lob.BlobFromLobCreatorDefaultTest;
+import org.hibernate.test.lob.BlobFromLobCreatorJDBC3ConnRelOnCloseTest;
+import org.hibernate.test.lob.BlobFromLobCreatorJDBC3Test;
+import org.hibernate.test.lob.BlobFromLobCreatorJDBC4ConnRelOnCloseTest;
+import org.hibernate.test.lob.BlobFromLobCreatorJDBC4Test;
import org.hibernate.test.lob.ClobTest;
+import org.hibernate.test.lob.ClobFromLobCreatorDefaultTest;
+import org.hibernate.test.lob.ClobFromLobCreatorJDBC3ConnRelOnCloseTest;
+import org.hibernate.test.lob.ClobFromLobCreatorJDBC3Test;
+import org.hibernate.test.lob.ClobFromLobCreatorJDBC4ConnRelOnCloseTest;
+import org.hibernate.test.lob.ClobFromLobCreatorJDBC4Test;
import org.hibernate.test.lob.SerializableTypeTest;
import org.hibernate.test.manytomany.ManyToManyTest;
import
org.hibernate.test.manytomanyassociationclass.compositeid.ManyToManyAssociationClassCompositeIdTest;
@@ -471,7 +481,17 @@
suite.addTest( AnyTypeTest.suite() );
suite.addTest( SerializableTypeTest.suite() );
suite.addTest( BlobTest.suite() );
+ suite.addTest( BlobFromLobCreatorDefaultTest.suite() );
+ suite.addTest( BlobFromLobCreatorJDBC3ConnRelOnCloseTest.suite() );
+ suite.addTest( BlobFromLobCreatorJDBC3Test.suite() );
+ suite.addTest( BlobFromLobCreatorJDBC4ConnRelOnCloseTest.suite() );
+ suite.addTest( BlobFromLobCreatorJDBC4Test.suite() );
suite.addTest( ClobTest.suite() );
+ suite.addTest( ClobFromLobCreatorDefaultTest.suite() );
+ suite.addTest( ClobFromLobCreatorJDBC3ConnRelOnCloseTest.suite() );
+ suite.addTest( ClobFromLobCreatorJDBC3Test.suite() );
+ suite.addTest( ClobFromLobCreatorJDBC4ConnRelOnCloseTest.suite() );
+ suite.addTest( ClobFromLobCreatorJDBC4Test.suite() );
suite.addTest( IdentifierPropertyReferencesTest.suite() );
suite.addTest( DeleteTransientEntityTest.suite() );
suite.addTest( UserCollectionTypeTest.suite() );
@@ -629,4 +649,4 @@
}
}
}
-}
\ No newline at end of file
+}
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobFromLobCreatorTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobFromLobCreatorTest.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobFromLobCreatorTest.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,161 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import java.sql.Blob;
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.io.IOException;
+import java.io.ByteArrayInputStream;
+
+import org.hibernate.Hibernate;
+import org.hibernate.Session;
+import org.hibernate.AssertionFailure;
+import org.hibernate.HibernateException;
+import org.hibernate.SessionException;
+import org.hibernate.lob.LobCreator;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.dialect.Dialect;
+
+/**
+ * This class extends AbstractBlobTest to provide additional tests when
+ * using a LobCreator to create LOB locators.
+ *
+ * @author Gail Badner
+ */
+public abstract class AbstractBlobFromLobCreatorTest extends AbstractBlobTest {
+
+ public AbstractBlobFromLobCreatorTest(String name) {
+ super( name );
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure( cfg );
+ if ( getUseConnectionForLobCreationPropertyValue() == null ) {
+ cfg.setProperty( Environment.USE_CONNECTION_FOR_LOB_CREATION, "" );
+ }
+ else {
+ cfg.setProperty(
+ Environment.USE_CONNECTION_FOR_LOB_CREATION,
+ String.valueOf( getUseConnectionForLobCreationPropertyValue().booleanValue() )
+ );
+ }
+ }
+
+ public boolean appliesTo(Dialect dialect) {
+ if ( ! dialect.supportsExpectedLobUsagePattern() ) {
+ reportSkip( "database/driver does not support expected LOB usage pattern",
"LOB support" );
+ return false;
+ }
+ return true;
+ }
+
+ protected abstract Boolean getUseConnectionForLobCreationPropertyValue();
+
+ protected Blob createBlobLocator(Session s, byte[] bytes) {
+ return Hibernate.getLobCreator( s ).createBlob( bytes );
+ }
+
+ protected Blob createBlobLocatorFromStream(Session s, byte[] bytes) throws IOException
{
+ return Hibernate.getLobCreator( s ).createBlob( new ByteArrayInputStream( bytes ) );
+ }
+
+ protected Blob createBlobLocatorFromStreamUsingLength(Session s, byte[] bytes) throws
IOException {
+ return Hibernate.getLobCreator( s ).createBlob( new ByteArrayInputStream( bytes ),
bytes.length );
+ }
+
+ protected abstract Class getExpectedLobCreatorClass() throws SQLException ;
+
+ public void testUseConnectionForLobCreationEnabledSetting() throws SQLException {
+ Boolean propVal = getUseConnectionForLobCreationPropertyValue();
+ if ( propVal == null ) {
+ if ( jvmAndDriverSupportUseConnectionForLobCreation() !=
isUseConnectionForLobCreationEnabled() ) {
+ throw new AssertionFailure( "JVM and JDBC driver support is inconsistent with
setting for using Connection to create LOBs." );
+
+ }
+ }
+ else {
+ if ( propVal.booleanValue() != isUseConnectionForLobCreationEnabled() ) {
+ throw new AssertionFailure( "Non-null
Environment.USE_CONNECTION_FOR_LOB_CREATION value is inconstent with setting." );
+ }
+ }
+ }
+
+ public void testCorrectLobCreator() throws Exception {
+ Session s = openSession();
+ LobCreator lobCreator = Hibernate.getLobCreator( s );
+ assertEquals( getExpectedLobCreatorClass(), lobCreator.getClass() );
+ s.close();
+ }
+
+ public void testGetLobCreatorWithNullSession() {
+ try {
+ Hibernate.getLobCreator( null );
+ fail( "should have failed with null session" );
+ }
+ catch ( AssertionFailure ex ) {
+ // expected
+ }
+ }
+
+ public void testCreateBlobLocatorAfterSessionClose() throws Throwable {
+ Session s = openSession();
+ s.close();
+ byte[] bytes = buildRecursively( BLOB_SIZE, true );
+ try {
+ createBlobLocator( s, bytes );
+ if ( isUseConnectionForLobCreationEnabled() ) {
+ fail( "should have failed w/ SessionException" );
+ }
+ }
+ catch ( SessionException e ) {
+ if ( ! isUseConnectionForLobCreationEnabled() ) {
+ fail( "should not have failed w/ SessionException" );
+ }
+ }
+ }
+
+ protected boolean isUseConnectionForLobCreationEnabled() {
+ return ( ( SessionFactoryImplementor ) getSessions()
).getSettings().isUseConnectionForLobCreationEnabled();
+ }
+
+ protected boolean jvmAndDriverSupportUseConnectionForLobCreation() throws SQLException
{
+ if ( ! Environment.jvmSupportsJDBC4() ) {
+ return false;
+ }
+ Class c = ( ( SessionFactoryImplementor ) getSessions()
).getConnectionProvider().getConnection().getClass();
+ try {
+ return !( Connection.class.equals( c.getMethod( "createBlob", new Class[0]
).getDeclaringClass() ) ||
+ Connection.class.equals( c.getMethod( "createClob", new Class[0]
).getDeclaringClass() ) );
+ }
+ catch ( NoSuchMethodException e ) {
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobTest.java
(rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractBlobTest.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,490 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import java.sql.Blob;
+import java.sql.SQLException;
+import java.io.IOException;
+
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.LockMode;
+import org.hibernate.Session;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
+import org.hibernate.util.ArrayHelper;
+
+/**
+ * Test various access scenarios for eager and lazy materialization
+ * of BLOB data, as well as bounded and unbounded materialization
+ * and mutation.
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractBlobTest extends DatabaseSpecificFunctionalTestCase {
+ public static final int BLOB_SIZE = 10000;
+
+ public AbstractBlobTest(String name) {
+ super( name );
+ }
+
+ public String[] getMappings() {
+ return new String[] { "lob/LobMappings.hbm.xml" };
+ }
+
+ public boolean appliesTo(Dialect dialect) {
+ if ( ! dialect.supportsExpectedLobUsagePattern() ) {
+ reportSkip( "database/driver does not support expected LOB usage pattern",
"LOB support" );
+ return false;
+ }
+ return true;
+ }
+
+ protected abstract Blob createBlobLocator(Session s, byte[] bytes);
+
+ protected abstract Blob createBlobLocatorFromStream(Session s, byte[] bytes) throws
IOException;
+
+ protected abstract Blob createBlobLocatorFromStreamUsingLength(Session s, byte[] bytes)
throws IOException ;
+
+ protected boolean skipLobLocatorTests() throws SQLException {
+ return false;
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure( cfg );
+ // set connection pool size to 0 so that tests will always use a clean connection;
+ // this ensures that the test does not use LOB data left on the connection from
+ // prior to being returned to the connection pool.
+ cfg.setProperty( Environment.POOL_SIZE, "0" );
+ // ConnectionReleaseMode.AFTER_TRANSACTION is the default for non-JTA connection.
+ // The Connection used for the unit tests is non-JTA. This setting for
+ // Environment.RELEASE_CONNECTIONS is just to make it explicit for these tests.
+ cfg.setProperty( Environment.RELEASE_CONNECTIONS, "after_transaction" );
+ }
+
+ public void testBoundedMaterializedBlobAccess() {
+ byte[] original = buildRecursively( BLOB_SIZE, true );
+ byte[] changed = buildRecursively( BLOB_SIZE, false );
+
+ Session s = openSession();
+ s.beginTransaction();
+ LobHolder entity = new LobHolder();
+ entity.setMaterializedBlob( original );
+ s.save( entity );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( BLOB_SIZE, entity.getMaterializedBlob().length );
+ assertEquals( original, entity.getMaterializedBlob() );
+ entity.setMaterializedBlob( changed );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( BLOB_SIZE, entity.getMaterializedBlob().length );
+ assertEquals( changed, entity.getMaterializedBlob() );
+ s.delete( entity );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testBoundedBlobLocatorAccess() throws Throwable {
+ if ( skipLobLocatorTests() ) {
+ return;
+ }
+
+ byte[] original = buildRecursively( BLOB_SIZE, true );
+ byte[] changed = buildRecursively( BLOB_SIZE, false );
+
+ Session s = openSession();
+ s.beginTransaction();
+ LobHolder entity = new LobHolder();
+ entity.setBlobLocator( createBlobLocator( s, original ) );
+ s.save( entity );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( original, extractData( entity.getBlobLocator() ) );
+ s.getTransaction().commit();
+ s.close();
+
+ // test mutation via setting the new blob data...
+ if ( supportsLobValueChangePropogation() ) {
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ entity.getBlobLocator().truncate( 1 );
+ entity.getBlobLocator().setBytes( 1, changed );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ assertNotNull( entity.getBlobLocator() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( changed, extractData( entity.getBlobLocator() ) );
+ entity.getBlobLocator().truncate( 1 );
+ entity.getBlobLocator().setBytes( 1, original );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ // test mutation via supplying a new blob locator instance...
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ assertNotNull( entity.getBlobLocator() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( original, extractData( entity.getBlobLocator() ) );
+ entity.setBlobLocator( createBlobLocator( s, changed ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( changed, extractData( entity.getBlobLocator() ) );
+ s.delete( entity );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testBoundedBlobLocatorAccessFromStream() throws Throwable {
+ if ( skipLobLocatorTests() ) {
+ return;
+ }
+
+ byte[] original = buildRecursively( BLOB_SIZE, true );
+ byte[] changed = buildRecursively( BLOB_SIZE, false );
+
+ Session s = openSession();
+ s.beginTransaction();
+ LobHolder entity = new LobHolder();
+ entity.setBlobLocator( createBlobLocatorFromStream( s, original ) );
+ s.save( entity );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( original, extractData( entity.getBlobLocator() ) );
+ s.getTransaction().commit();
+ s.close();
+
+ // test mutation via setting the new blob data...
+ if ( supportsLobValueChangePropogation() ) {
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ entity.getBlobLocator().truncate( 1 );
+ entity.getBlobLocator().setBytes( 1, changed );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ assertNotNull( entity.getBlobLocator() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( changed, extractData( entity.getBlobLocator() ) );
+ entity.getBlobLocator().truncate( 1 );
+ entity.getBlobLocator().setBytes( 1, original );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ // test mutation via supplying a new blob locator instance...
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ assertNotNull( entity.getBlobLocator() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( original, extractData( entity.getBlobLocator() ) );
+ entity.setBlobLocator( createBlobLocatorFromStream( s, changed ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( changed, extractData( entity.getBlobLocator() ) );
+ s.delete( entity );
+ s.getTransaction().commit();
+ s.close();
+
+ }
+
+ public void testBoundedBlobLocatorAccessFromStreamUsingLength() throws Throwable {
+ if ( skipLobLocatorTests() ) {
+ return;
+ }
+
+ byte[] original = buildRecursively( BLOB_SIZE, true );
+ byte[] changed = buildRecursively( BLOB_SIZE, false );
+
+ Session s = openSession();
+ s.beginTransaction();
+ LobHolder entity = new LobHolder();
+ entity.setBlobLocator( createBlobLocatorFromStreamUsingLength( s, original ) );
+ s.save( entity );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( original, extractData( entity.getBlobLocator() ) );
+ s.getTransaction().commit();
+ s.close();
+
+ // test mutation via setting the new blob data...
+ if ( supportsLobValueChangePropogation() ) {
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ entity.getBlobLocator().truncate( 1 );
+ entity.getBlobLocator().setBytes( 1, changed );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ assertNotNull( entity.getBlobLocator() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( changed, extractData( entity.getBlobLocator() ) );
+ entity.getBlobLocator().truncate( 1 );
+ entity.getBlobLocator().setBytes( 1, original );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ // test mutation via supplying a new blob locator instance...
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ assertNotNull( entity.getBlobLocator() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( original, extractData( entity.getBlobLocator() ) );
+ entity.setBlobLocator( createBlobLocatorFromStreamUsingLength( s, changed ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( changed, extractData( entity.getBlobLocator() ) );
+ s.delete( entity );
+ s.getTransaction().commit();
+ s.close();
+
+ }
+
+ public void testUnboundedBlobLocatorAccess() throws Throwable {
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+
+ // Note: unbounded mutation of the underlying lob data is completely
+ // unsupported; most databases would not allow such a construct anyway.
+ // Thus here we are only testing materialization...
+
+ byte[] original = buildRecursively( BLOB_SIZE, true );
+
+ Session s = openSession();
+ s.beginTransaction();
+ LobHolder entity = new LobHolder();
+ entity.setBlobLocator( createBlobLocator( s, original ) );
+ s.save( entity );
+ s.getTransaction().commit();
+ s.close();
+
+ // load the entity with the blob locator, and close the session/transaction;
+ // at that point it is unbounded...
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ s.getTransaction().commit();
+ s.close();
+
+ assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
+ assertEquals( original, extractData( entity.getBlobLocator() ) );
+
+ s = openSession();
+ s.beginTransaction();
+ s.delete( entity );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testCreateAndAccessLobLocatorInSessionNoTransaction() throws Throwable {
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ byte[] bytes = buildRecursively( BLOB_SIZE, true );
+ Blob blob = createBlobLocator( s, bytes );
+ assertEquals( BLOB_SIZE, blob.length() );
+ assertEquals( bytes, extractData( blob ) );
+ s.close();
+ }
+
+ public void testCreateAndAccessLobLocatorInTransaction() throws Throwable {
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ byte bytes[] = buildRecursively( BLOB_SIZE, true );
+ Blob blob = createBlobLocator( s, bytes );
+ assertEquals( BLOB_SIZE, blob.length() );
+ assertEquals( bytes, extractData( blob ) );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testCreateLobLocatorInTransactionAccessOutOfTransaction() throws Throwable
{
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ byte bytes[] = buildRecursively( BLOB_SIZE, true );
+ Blob blob = createBlobLocator( s, bytes );
+ s.getTransaction().commit();
+ assertEquals( BLOB_SIZE, blob.length() );
+ assertEquals( bytes, extractData( blob ) );
+ s.close();
+ }
+
+ public void testCreateLobLocatorInTransactionAccessInNextTransaction() throws Throwable
{
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ byte bytes[] = buildRecursively( BLOB_SIZE, true );
+ Blob blob = createBlobLocator( s, bytes );
+ s.getTransaction().commit();
+ s.getTransaction().begin();
+ assertEquals( BLOB_SIZE, blob.length() );
+ assertEquals( bytes, extractData( blob ) );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testCreateLobLocatorInTransactionAccessAfterSessionClose() throws Throwable
{
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ byte bytes[] = buildRecursively( BLOB_SIZE, true );
+ Blob blob = createBlobLocator( s, bytes );
+ s.getTransaction().commit();
+ s.close();
+ assertEquals( BLOB_SIZE, blob.length() );
+ assertEquals( bytes, extractData( blob ) );
+ }
+
+ public void testCreateLobLocatorInTransactionAccessInNextSession() throws Throwable {
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ byte bytes[] = buildRecursively( BLOB_SIZE, true );
+ Blob blob = createBlobLocator( s, bytes );
+ s.getTransaction().commit();
+ s.close();
+ s = openSession();
+ assertEquals( BLOB_SIZE, blob.length() );
+ assertEquals( bytes, extractData( blob ) );
+ s.close();
+ }
+
+ public void testCreateLobLocatorInTransactionAccessInNextSessionTransaction() throws
Throwable {
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ byte bytes[] = buildRecursively( BLOB_SIZE, true );
+ Blob blob = createBlobLocator( s, bytes );
+ s.getTransaction().commit();
+ s.close();
+ s = openSession();
+ s.getTransaction().begin();
+ assertEquals( BLOB_SIZE, blob.length() );
+ assertEquals( bytes, extractData( blob ) );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ protected byte[] extractData(Blob blob) throws Throwable {
+ byte bytesRead[] = new byte[ ( int ) blob.length() ];
+ blob.getBinaryStream().read( bytesRead );
+ return bytesRead;
+ }
+
+ protected byte[] buildRecursively(int size, boolean on) {
+ byte[] data = new byte[size];
+ data[0] = mask( on );
+ for ( int i = 0; i < size; i++ ) {
+ data[i] = mask( on );
+ on = !on;
+ }
+ return data;
+ }
+
+ private byte mask(boolean on) {
+ return on ? ( byte ) 1 : ( byte ) 0;
+ }
+
+ public static void assertEquals(byte[] val1, byte[] val2) {
+ if ( !ArrayHelper.isEquals( val1, val2 ) ) {
+ throw new AssertionFailedError( "byte arrays did not match" );
+ }
+ }
+}
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobFromLobCreatorTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobFromLobCreatorTest.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobFromLobCreatorTest.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,156 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.sql.Clob;
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.hibernate.Hibernate;
+import org.hibernate.Session;
+import org.hibernate.AssertionFailure;
+import org.hibernate.SessionException;
+import org.hibernate.lob.LobCreator;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.dialect.Dialect;
+
+/**
+ * This class extends AbstractClobTest to provide additional tests when
+ * using a LobCreator to create LOB locators.
+ *
+ * @author Gail Badner
+ */
+public abstract class AbstractClobFromLobCreatorTest extends AbstractClobTest {
+
+ public AbstractClobFromLobCreatorTest(String name) {
+ super( name );
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure( cfg );
+ if ( getUseConnectionForLobCreationPropertyValue() == null ) {
+ cfg.setProperty( Environment.USE_CONNECTION_FOR_LOB_CREATION, "" );
+ }
+ else {
+ cfg.setProperty(
+ Environment.USE_CONNECTION_FOR_LOB_CREATION,
+ String.valueOf( getUseConnectionForLobCreationPropertyValue().booleanValue() )
+ );
+ }
+ }
+
+ public boolean appliesTo(Dialect dialect) {
+ if ( ! dialect.supportsExpectedLobUsagePattern() ) {
+ reportSkip( "database/driver does not support expected LOB usage pattern",
"LOB support" );
+ return false;
+ }
+ return true;
+ }
+
+ protected abstract Boolean getUseConnectionForLobCreationPropertyValue();
+
+ protected Clob createClobLocator(Session s, String str) {
+ return Hibernate.getLobCreator( s ).createClob( str );
+ }
+
+ protected Clob createClobLocatorFromStreamUsingLength(Session s, String str) throws
IOException {
+ return Hibernate.getLobCreator( s ).createClob( new StringReader( str ), str.length()
);
+ }
+
+ protected abstract Class getExpectedLobCreatorClass() throws SQLException ;
+
+ public void testUseConnectionForLobCreationEnabledSetting() throws SQLException {
+ Boolean propVal = getUseConnectionForLobCreationPropertyValue();
+ if ( propVal == null ) {
+ if ( jvmAndDriverSupportUseConnectionForLobCreation() !=
isUseConnectionForLobCreationEnabled() ) {
+ throw new AssertionFailure( "JVM and JDBC driver support is inconsistent with
setting for using Connection to create LOBs." );
+
+ }
+ }
+ else {
+ if ( propVal.booleanValue() != isUseConnectionForLobCreationEnabled() ) {
+ throw new AssertionFailure( "Non-null
Environment.USE_CONNECTION_FOR_LOB_CREATION value is inconstent with setting." );
+ }
+ }
+ }
+
+ public void testCorrectLobCreator() throws Exception {
+ Session s = openSession();
+ LobCreator lobCreator = Hibernate.getLobCreator( s );
+ assertEquals( getExpectedLobCreatorClass(), lobCreator.getClass() );
+ s.close();
+ }
+
+ public void testGetLobCreatorWithNullSession() {
+ try {
+ Hibernate.getLobCreator( null );
+ fail( "should have failed with null session" );
+ }
+ catch ( AssertionFailure ex ) {
+ // expected
+ }
+ }
+
+ public void testCreateClobLocatorAfterSessionClose() throws Throwable {
+ Session s = openSession();
+ s.close();
+ String str = buildRecursively( CLOB_SIZE, 'x');
+ try {
+ createClobLocator( s, str );
+ if ( isUseConnectionForLobCreationEnabled() ) {
+ fail( "should have failed w/ SessionException" );
+ }
+ }
+ catch ( SessionException e ) {
+ if ( ! isUseConnectionForLobCreationEnabled() ) {
+ fail( "should not have failed w/ SessionException" );
+ }
+ }
+ }
+
+ protected boolean isUseConnectionForLobCreationEnabled() {
+ return ( ( SessionFactoryImplementor ) getSessions()
).getSettings().isUseConnectionForLobCreationEnabled();
+ }
+
+ protected boolean jvmAndDriverSupportUseConnectionForLobCreation() throws SQLException
{
+ if ( ! Environment.jvmSupportsJDBC4() ) {
+ return false;
+ }
+ Class c = ( ( SessionFactoryImplementor ) getSessions()
).getConnectionProvider().getConnection().getClass();
+ try {
+ return !( Connection.class.equals( c.getMethod( "createBlob", new Class[0]
).getDeclaringClass() ) ||
+ Connection.class.equals( c.getMethod( "createClob", new Class[0]
).getDeclaringClass() ) );
+ }
+ catch ( NoSuchMethodException e ) {
+ return false;
+ }
+ }
+
+}
\ No newline at end of file
Added: core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobTest.java
(rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/AbstractClobTest.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,410 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import java.sql.SQLException;
+import java.sql.Clob;
+import java.io.IOException;
+
+import org.hibernate.LockMode;
+import org.hibernate.Session;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.H2Dialect;
+import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
+
+/**
+ * Test various access scenarios for eager and lazy materialization
+ * of CLOB data, as well as bounded and unbounded materialization
+ * and mutation.
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractClobTest extends DatabaseSpecificFunctionalTestCase {
+ public static final int CLOB_SIZE = 10000;
+
+ public AbstractClobTest(String name) {
+ super( name );
+ }
+
+ public String[] getMappings() {
+ return new String[] { "lob/LobMappings.hbm.xml" };
+ }
+
+ public boolean appliesTo(Dialect dialect) {
+ if ( ! dialect.supportsExpectedLobUsagePattern() ) {
+ reportSkip( "database/driver does not support expected LOB usage pattern",
"LOB support" );
+ return false;
+ }
+ return true;
+ }
+
+ protected abstract Clob createClobLocator(Session s, String str);
+
+ protected abstract Clob createClobLocatorFromStreamUsingLength(Session s, String str )
throws IOException ;
+
+ protected boolean skipLobLocatorTests() throws SQLException {
+ return false;
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure( cfg );
+ // set connection pool size to 0 so that tests will always use a clean connection;
+ // this ensures that the test does not use LOB data left on the connection from
+ // prior to being returned to the connection pool.
+ cfg.setProperty( Environment.POOL_SIZE, "0" );
+ // ConnectionReleaseMode.AFTER_TRANSACTION is the default for non-JTA connection.
+ // The Connection used for the unit tests is non-JTA. This setting for
+ // Environment.RELEASE_CONNECTIONS is just to make it explicit for these tests.
+ cfg.setProperty( Environment.RELEASE_CONNECTIONS, "after_transaction" );
+ }
+
+ public void testBoundedMaterializedClobAccess() {
+ String original = buildRecursively( CLOB_SIZE, 'x' );
+ String changed = buildRecursively( CLOB_SIZE, 'y' );
+
+ Session s = openSession();
+ s.beginTransaction();
+ LobHolder entity = new LobHolder();
+ entity.setMaterializedClob( original );
+ s.save( entity );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( CLOB_SIZE, entity.getMaterializedClob().length() );
+ assertEquals( original, entity.getMaterializedClob() );
+ entity.setMaterializedClob( changed );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( CLOB_SIZE, entity.getMaterializedClob().length() );
+ assertEquals( changed, entity.getMaterializedClob() );
+ s.delete( entity );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testBoundedClobLocatorAccess() throws Throwable {
+ if ( skipLobLocatorTests() ) {
+ return;
+ }
+
+ String original = buildRecursively( CLOB_SIZE, 'x');
+ String changed = buildRecursively( CLOB_SIZE, 'y' );
+
+ Session s = openSession();
+ s.beginTransaction();
+ LobHolder entity = new LobHolder();
+ entity.setClobLocator( createClobLocator( s, original ) );
+ s.save( entity );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+ assertEquals( original, extractData( entity.getClobLocator() ) );
+ s.getTransaction().commit();
+ s.close();
+
+ // test mutation via setting the new clob data...
+ if ( supportsLobValueChangePropogation() ) {
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ entity.getClobLocator().truncate( 1 );
+ entity.getClobLocator().setString( 1, changed );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ assertNotNull( entity.getClobLocator() );
+ assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+ assertEquals( changed, extractData( entity.getClobLocator() ) );
+ entity.getClobLocator().truncate( 1 );
+ entity.getClobLocator().setString( 1, original );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ // test mutation via supplying a new clob locator instance...
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ assertNotNull( entity.getClobLocator() );
+ assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+ assertEquals( original, extractData( entity.getClobLocator() ) );
+ entity.setClobLocator( createClobLocator( s, changed ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+ assertEquals( changed, extractData( entity.getClobLocator() ) );
+ s.delete( entity );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testBoundedClobLocatorAccessFromStreamUsingLength() throws Throwable {
+ if ( skipLobLocatorTests() ) {
+ return;
+ }
+
+ String original = buildRecursively( CLOB_SIZE, 'x');
+ String changed = buildRecursively( CLOB_SIZE, 'y' );
+
+ Session s = openSession();
+ s.beginTransaction();
+ LobHolder entity = new LobHolder();
+ entity.setClobLocator( createClobLocatorFromStreamUsingLength( s, original ) );
+ s.save( entity );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+ assertEquals( original, extractData( entity.getClobLocator() ) );
+ s.getTransaction().commit();
+ s.close();
+
+ // test mutation via setting the new clob data...
+ if ( supportsLobValueChangePropogation() ) {
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ entity.getClobLocator().truncate( 1 );
+ entity.getClobLocator().setString( 1, changed );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ assertNotNull( entity.getClobLocator() );
+ assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+ assertEquals( changed, extractData( entity.getClobLocator() ) );
+ entity.getClobLocator().truncate( 1 );
+ entity.getClobLocator().setString( 1, original );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ // test mutation via supplying a new clob locator instance...
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
+ assertNotNull( entity.getClobLocator() );
+ assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+ assertEquals( original, extractData( entity.getClobLocator() ) );
+ entity.setClobLocator( createClobLocatorFromStreamUsingLength( s, changed ) );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+ assertEquals( changed, extractData( entity.getClobLocator() ) );
+ s.delete( entity );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testUnboundedClobLocatorAccess() throws Throwable {
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+
+ // Note: unbounded mutation of the underlying lob data is completely
+ // unsupported; most databases would not allow such a construct anyway.
+ // Thus here we are only testing materialization...
+
+ String original = buildRecursively( CLOB_SIZE, 'x' );
+
+ Session s = openSession();
+ s.beginTransaction();
+ LobHolder entity = new LobHolder();
+ entity.setClobLocator( createClobLocator( s, original ) );
+ s.save( entity );
+ s.getTransaction().commit();
+ s.close();
+
+ // load the entity with the clob locator, and close the session/transaction;
+ // at that point it is unbounded...
+ s = openSession();
+ s.beginTransaction();
+ entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
+ s.getTransaction().commit();
+ s.close();
+
+ assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
+ assertEquals( original, extractData( entity.getClobLocator() ) );
+
+ s = openSession();
+ s.beginTransaction();
+ s.delete( entity );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testCreateAndAccessLobLocatorInSessionNoTransaction() throws Throwable {
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ String str = buildRecursively( CLOB_SIZE, 'x' );
+ Clob clob = createClobLocator( s, str );
+ assertEquals( CLOB_SIZE, clob.length() );
+ assertEquals( str, extractData( clob ) );
+ s.close();
+ }
+
+ public void testCreateAndAccessLobLocatorInTransaction() throws Throwable {
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ String str = buildRecursively( CLOB_SIZE, 'x' );
+ Clob clob = createClobLocator( s, str );
+ assertEquals( CLOB_SIZE, clob.length() );
+ assertEquals( str, extractData( clob ) );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testCreateLobLocatorInTransactionAccessOutOfTransaction() throws Throwable
{
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ String str = buildRecursively( CLOB_SIZE, 'x' );
+ Clob clob = createClobLocator( s, str );
+ s.getTransaction().commit();
+ assertEquals( CLOB_SIZE, clob.length() );
+ assertEquals( str, extractData( clob ) );
+ s.close();
+ }
+
+ public void testCreateLobLocatorInTransactionAccessInNextTransaction() throws Throwable
{
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ String str = buildRecursively( CLOB_SIZE, 'x' );
+ Clob clob = createClobLocator( s, str );
+ s.getTransaction().commit();
+ s.getTransaction().begin();
+ assertEquals( CLOB_SIZE, clob.length() );
+ assertEquals( str, extractData( clob ) );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ public void testCreateLobLocatorInTransactionAccessAfterSessionClose() throws Throwable
{
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ String str = buildRecursively( CLOB_SIZE, 'x' );
+ Clob clob = createClobLocator( s, str );
+ s.getTransaction().commit();
+ s.close();
+ assertEquals( CLOB_SIZE, clob.length() );
+ assertEquals( str, extractData( clob ) );
+ }
+
+ public void testCreateLobLocatorInTransactionAccessInNextSession() throws Throwable {
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ String str = buildRecursively( CLOB_SIZE, 'x' );
+ Clob clob = createClobLocator( s, str );
+ s.getTransaction().commit();
+ s.close();
+ s = openSession();
+ assertEquals( CLOB_SIZE, clob.length() );
+ assertEquals( str, extractData( clob ) );
+ s.close();
+ }
+
+ public void testCreateLobLocatorInTransactionAccessInNextSessionTransaction() throws
Throwable {
+ if ( skipLobLocatorTests() || ! supportsUnboundedLobLocatorMaterialization() ) {
+ return;
+ }
+ Session s = openSession();
+ s.getTransaction().begin();
+ String str = buildRecursively( CLOB_SIZE, 'x' );
+ Clob clob = createClobLocator( s, str );
+ s.getTransaction().commit();
+ s.close();
+ s = openSession();
+ s.getTransaction().begin();
+ assertEquals( CLOB_SIZE, clob.length() );
+ assertEquals( str, extractData( clob ) );
+ s.getTransaction().commit();
+ s.close();
+ }
+
+ protected String extractData(Clob clob) throws Throwable {
+ if ( getDialect() instanceof H2Dialect ) {
+ return clob.getSubString( 1, ( int ) clob.length() );
+ }
+ else {
+ char[] data = new char[ (int) clob.length() ];
+ clob.getCharacterStream().read( data );
+ return new String( data );
+ }
+ }
+
+ protected String buildRecursively(int size, char baseChar) {
+ StringBuffer buff = new StringBuffer();
+ for( int i = 0; i < size; i++ ) {
+ buff.append( baseChar );
+ }
+ return buff.toString();
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorDefaultTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorDefaultTest.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorDefaultTest.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,65 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import java.sql.SQLException;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC4;
+import org.hibernate.lob.LobCreatorImplJDBC3;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends AbstractBlobFromLobCreatorTest to provide logic to
+ * determine if the correct LobCreator impl is used when
+ * Environment.USE_CONNECTION_FOR_LOB_CREATION is not set. The actual impl
+ * will depend on whether the JVM and driver support creating LOBs using
+ * the connection.
+ *
+ * @author Gail Badner
+ */
+public class BlobFromLobCreatorDefaultTest extends AbstractBlobFromLobCreatorTest {
+
+ public BlobFromLobCreatorDefaultTest(String name) {
+ super( name );
+ }
+
+ protected Boolean getUseConnectionForLobCreationPropertyValue() {
+ return null;
+ }
+
+ protected Class getExpectedLobCreatorClass() throws SQLException {
+ return ( jvmAndDriverSupportUseConnectionForLobCreation() ?
+ LobCreatorImplJDBC4.class :
+ LobCreatorImplJDBC3.class
+ );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite( BlobFromLobCreatorDefaultTest.class );
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3ConnRelOnCloseTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3ConnRelOnCloseTest.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3ConnRelOnCloseTest.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,54 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+
+/**
+ * This class extends BlobFromLobCreatorJDBC3Test to run tests
+ * using connection release mode "on_close".
+ *
+ * @author Gail Badner
+ */
+public class BlobFromLobCreatorJDBC3ConnRelOnCloseTest extends
BlobFromLobCreatorJDBC3Test {
+
+ public BlobFromLobCreatorJDBC3ConnRelOnCloseTest(String name) {
+ super( name );
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure( cfg );
+ cfg.setProperty( Environment.RELEASE_CONNECTIONS, "on_close" );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite(
BlobFromLobCreatorJDBC3ConnRelOnCloseTest.class );
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3Test.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3Test.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC3Test.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,59 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC3;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends AbstractBlobFromLobCreatorTest to determine if the
+ * correct LobCreator impl is used when Environment.USE_CONNECTION_FOR_LOB_CREATION
+ * is set to false. The actual impl should be the JDBC3 LobCreator, even when
+ * the JVM and JDBC driver support JDBC4. The JDBC3 LobCreator does not use the
+ * Connection to create LOBs.
+ *
+ * @author Gail Badner
+ */
+public class BlobFromLobCreatorJDBC3Test extends AbstractBlobFromLobCreatorTest {
+
+ public BlobFromLobCreatorJDBC3Test(String name) {
+ super( name );
+ }
+
+ protected Boolean getUseConnectionForLobCreationPropertyValue() {
+ return Boolean.FALSE;
+ }
+
+ protected Class getExpectedLobCreatorClass() {
+ return LobCreatorImplJDBC3.class;
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite( BlobFromLobCreatorJDBC3Test.class );
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4ConnRelOnCloseTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4ConnRelOnCloseTest.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4ConnRelOnCloseTest.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,54 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends BlobFromLobCreatorJDBC4Test to run tests
+ * using connection release mode "on_close".
+ *
+ * @author Gail Badner
+ */
+public class BlobFromLobCreatorJDBC4ConnRelOnCloseTest extends
BlobFromLobCreatorJDBC4Test {
+
+ public BlobFromLobCreatorJDBC4ConnRelOnCloseTest(String name) {
+ super( name );
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure( cfg );
+ cfg.setProperty( Environment.RELEASE_CONNECTIONS, "on_close" );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite(
BlobFromLobCreatorJDBC4ConnRelOnCloseTest.class );
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4Test.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4Test.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobFromLobCreatorJDBC4Test.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,112 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import java.sql.SQLException;
+import java.sql.Blob;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC4;
+import org.hibernate.cfg.Environment;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.Session;
+import org.hibernate.HibernateException;
+
+/**
+ * This class extends AbstractBlobFromLobCreatorTest to determine if the
+ * correct LobCreator impl is used when Environment.USE_CONNECTION_FOR_LOB_CREATION
+ * is set to true. The actual impl should be the JDBC4 LobCreator, even when
+ * the JVM and/or JDBC driver do not support JDBC4. The JDBC4 LobCreator uses the
+ * Connection to create LOBs.
+ *
+ * @author Gail Badner
+ */
+public class BlobFromLobCreatorJDBC4Test extends AbstractBlobFromLobCreatorTest {
+
+ public BlobFromLobCreatorJDBC4Test(String name) {
+ super( name );
+ }
+
+ protected Boolean getUseConnectionForLobCreationPropertyValue() {
+ return Boolean.TRUE;
+ }
+
+ protected Class getExpectedLobCreatorClass() {
+ return LobCreatorImplJDBC4.class;
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite( BlobFromLobCreatorJDBC4Test.class );
+ }
+
+ protected boolean skipLobLocatorTests() throws SQLException {
+ if ( ! Environment.jvmSupportsJDBC4() ) {
+ reportSkip( "JVM does not support creating LOBs using the connection",
"LOB support" );
+ return true;
+ }
+ if ( ! jvmAndDriverSupportUseConnectionForLobCreation() ) {
+ reportSkip( "Driver does not support creating LOBs using the connection",
"LOB support" );
+ return true;
+ }
+ return false;
+ }
+
+ public void testCreateBlobLocatorSupport() throws Throwable {
+ Session s = openSession();
+ s.getTransaction().begin();
+ byte[] bytes = buildRecursively( BLOB_SIZE, true );
+ try {
+ Blob blob = createBlobLocator( s, bytes );
+ if ( ! Environment.jvmSupportsJDBC4() ) {
+ fail( "should have thrown NoSuchMethodException" );
+ }
+ else if ( ! jvmAndDriverSupportUseConnectionForLobCreation() ) {
+ fail( "should have thrown AbstractMethodException" );
+ }
+ assertEquals( bytes, extractData( blob ) );
+ s.getTransaction().commit();
+ }
+ catch( HibernateException e ) {
+ s.getTransaction().rollback();
+ if ( e.getCause() instanceof NoSuchMethodException ) {
+ assertTrue( ! Environment.jvmSupportsJDBC4() &&
+ isUseConnectionForLobCreationEnabled() );
+ }
+ else if ( e.getCause() instanceof AbstractMethodError ) {
+ assertTrue( Environment.jvmSupportsJDBC4() &&
+ ! jvmAndDriverSupportUseConnectionForLobCreation() &&
+ isUseConnectionForLobCreationEnabled() );
+ }
+ else {
+ throw e;
+ }
+ }
+ finally {
+ s.close();
+ }
+ }
+}
\ No newline at end of file
Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobTest.java 2008-10-28 21:47:32
UTC (rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/BlobTest.java 2008-10-29 05:38:54
UTC (rev 15430)
@@ -1,200 +1,67 @@
+//$Id: $
+/*
+ * 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.test.lob;
import java.sql.Blob;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
-import junit.framework.AssertionFailedError;
import junit.framework.Test;
import org.hibernate.Hibernate;
-import org.hibernate.LockMode;
import org.hibernate.Session;
-import org.hibernate.dialect.Dialect;
-import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
-import org.hibernate.util.ArrayHelper;
/**
- * {@inheritDoc}
+ * This class extends AbstractBlobTest so that LOBs are created using the
+ * Hibernate.createBlob() APIs. These APIs do not use the connection to
+ * create LOBs.
*
* @author Steve Ebersole
*/
-public class BlobTest extends DatabaseSpecificFunctionalTestCase {
- private static final int BLOB_SIZE = 10000;
+public class BlobTest extends AbstractBlobTest {
public BlobTest(String name) {
super( name );
}
- public String[] getMappings() {
- return new String[] { "lob/LobMappings.hbm.xml" };
- }
-
public static Test suite() {
return new FunctionalTestClassTestSuite( BlobTest.class );
}
- public boolean appliesTo(Dialect dialect) {
- if ( ! dialect.supportsExpectedLobUsagePattern() ) {
- reportSkip( "database/driver does not support expected LOB usage pattern",
"LOB support" );
- return false;
- }
- return true;
+ protected Blob createBlobLocator(Session s, byte[] bytes) {
+ return Hibernate.createBlob( bytes );
}
- public void testBoundedMaterializedBlobAccess() {
- byte[] original = buildRecursively( BLOB_SIZE, true );
- byte[] changed = buildRecursively( BLOB_SIZE, false );
-
- Session s = openSession();
- s.beginTransaction();
- LobHolder entity = new LobHolder();
- entity.setMaterializedBlob( original );
- s.save( entity );
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
- assertEquals( BLOB_SIZE, entity.getMaterializedBlob().length );
- assertEquals( original, entity.getMaterializedBlob() );
- entity.setMaterializedBlob( changed );
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
- assertEquals( BLOB_SIZE, entity.getMaterializedBlob().length );
- assertEquals( changed, entity.getMaterializedBlob() );
- s.delete( entity );
- s.getTransaction().commit();
- s.close();
+ protected Blob createBlobLocatorFromStream(Session s, byte[] bytes) throws IOException
{
+ return Hibernate.createBlob( new ByteArrayInputStream( bytes ) );
}
- public void testBoundedBlobLocatorAccess() throws Throwable {
- byte[] original = buildRecursively( BLOB_SIZE, true );
- byte[] changed = buildRecursively( BLOB_SIZE, false );
-
- Session s = openSession();
- s.beginTransaction();
- LobHolder entity = new LobHolder();
- entity.setBlobLocator( Hibernate.createBlob( original ) );
- s.save( entity );
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
- assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
- assertEquals( original, extractData( entity.getBlobLocator() ) );
- s.getTransaction().commit();
- s.close();
-
- // test mutation via setting the new clob data...
- if ( supportsLobValueChangePropogation() ) {
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
- entity.getBlobLocator().truncate( 1 );
- entity.getBlobLocator().setBytes( 1, changed );
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
- assertNotNull( entity.getBlobLocator() );
- assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
- assertEquals( changed, extractData( entity.getBlobLocator() ) );
- entity.getBlobLocator().truncate( 1 );
- entity.getBlobLocator().setBytes( 1, original );
- s.getTransaction().commit();
- s.close();
- }
-
- // test mutation via supplying a new clob locator instance...
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
- assertNotNull( entity.getBlobLocator() );
- assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
- assertEquals( original, extractData( entity.getBlobLocator() ) );
- entity.setBlobLocator( Hibernate.createBlob( changed ) );
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
- assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
- assertEquals( changed, extractData( entity.getBlobLocator() ) );
- s.delete( entity );
- s.getTransaction().commit();
- s.close();
-
+ protected Blob createBlobLocatorFromStreamUsingLength(Session s, byte[] bytes) throws
IOException {
+ return Hibernate.createBlob( new ByteArrayInputStream( bytes ), bytes.length );
}
-
- public void testUnboundedBlobLocatorAccess() throws Throwable {
- if ( ! supportsUnboundedLobLocatorMaterialization() ) {
- return;
- }
-
- // Note: unbounded mutation of the underlying lob data is completely
- // unsupported; most databases would not allow such a construct anyway.
- // Thus here we are only testing materialization...
-
- byte[] original = buildRecursively( BLOB_SIZE, true );
-
- Session s = openSession();
- s.beginTransaction();
- LobHolder entity = new LobHolder();
- entity.setBlobLocator( Hibernate.createBlob( original ) );
- s.save( entity );
- s.getTransaction().commit();
- s.close();
-
- // load the entity with the clob locator, and close the session/transaction;
- // at that point it is unbounded...
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
- s.getTransaction().commit();
- s.close();
-
- assertEquals( BLOB_SIZE, entity.getBlobLocator().length() );
- assertEquals( original, extractData( entity.getBlobLocator() ) );
-
- s = openSession();
- s.beginTransaction();
- s.delete( entity );
- s.getTransaction().commit();
- s.close();
- }
-
- private byte[] extractData(Blob blob) throws Throwable {
- return blob.getBytes( 1, ( int ) blob.length() );
- }
-
-
- private byte[] buildRecursively(int size, boolean on) {
- byte[] data = new byte[size];
- data[0] = mask( on );
- for ( int i = 0; i < size; i++ ) {
- data[i] = mask( on );
- on = !on;
- }
- return data;
- }
-
- private byte mask(boolean on) {
- return on ? ( byte ) 1 : ( byte ) 0;
- }
-
- public static void assertEquals(byte[] val1, byte[] val2) {
- if ( !ArrayHelper.isEquals( val1, val2 ) ) {
- throw new AssertionFailedError( "byte arrays did not match" );
- }
- }
}
+
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorDefaultTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorDefaultTest.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorDefaultTest.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,65 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import java.sql.SQLException;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC4;
+import org.hibernate.lob.LobCreatorImplJDBC3;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends AbstractClobFromLobCreatorTest to provide logic to
+ * determine if the correct LobCreator impl is used when
+ * Environment.USE_CONNECTION_FOR_LOB_CREATION is not set. The actual impl
+ * will depend on whether the JVM and driver support creating LOBs using
+ * the connection.
+ *
+ * @author Gail Badner
+ */
+public class ClobFromLobCreatorDefaultTest extends AbstractClobFromLobCreatorTest {
+
+ public ClobFromLobCreatorDefaultTest(String name) {
+ super( name );
+ }
+
+ protected Boolean getUseConnectionForLobCreationPropertyValue() {
+ return null;
+ }
+
+ protected Class getExpectedLobCreatorClass() throws SQLException {
+ return ( jvmAndDriverSupportUseConnectionForLobCreation() ?
+ LobCreatorImplJDBC4.class :
+ LobCreatorImplJDBC3.class
+ );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite( ClobFromLobCreatorDefaultTest.class );
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3ConnRelOnCloseTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3ConnRelOnCloseTest.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3ConnRelOnCloseTest.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,54 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+
+/**
+ * This class extends ClobFromLobCreatorJDBC3Test to run tests
+ * using connection release mode "on_close".
+ *
+ * @author Gail Badner
+ */
+public class ClobFromLobCreatorJDBC3ConnRelOnCloseTest extends
ClobFromLobCreatorJDBC3Test {
+
+ public ClobFromLobCreatorJDBC3ConnRelOnCloseTest(String name) {
+ super( name );
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure( cfg );
+ cfg.setProperty( Environment.RELEASE_CONNECTIONS, "on_close" );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite(
ClobFromLobCreatorJDBC3ConnRelOnCloseTest.class );
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3Test.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3Test.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC3Test.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,59 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC3;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends AbstractClobFromLobCreatorTest to determine if the
+ * correct LobCreator impl is used when Environment.USE_CONNECTION_FOR_LOB_CREATION
+ * is set to false. The actual impl should be the JDBC3 LobCreator, even when
+ * the JVM and JDBC driver support JDBC4. The JDBC3 LobCreator does not use the
+ * Connection to create LOBs.
+ *
+ * @author Gail Badner
+ */
+public class ClobFromLobCreatorJDBC3Test extends AbstractClobFromLobCreatorTest {
+
+ public ClobFromLobCreatorJDBC3Test(String name) {
+ super( name );
+ }
+
+ protected Boolean getUseConnectionForLobCreationPropertyValue() {
+ return Boolean.FALSE;
+ }
+
+ protected Class getExpectedLobCreatorClass() {
+ return LobCreatorImplJDBC3.class;
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite( ClobFromLobCreatorJDBC3Test.class );
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4ConnRelOnCloseTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4ConnRelOnCloseTest.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4ConnRelOnCloseTest.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,54 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import junit.framework.Test;
+
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * This class extends ClobFromLobCreatorJDBC4Test to run tests
+ * using connection release mode "on_close".
+ *
+ * @author Gail Badner
+ */
+public class ClobFromLobCreatorJDBC4ConnRelOnCloseTest extends
ClobFromLobCreatorJDBC4Test {
+
+ public ClobFromLobCreatorJDBC4ConnRelOnCloseTest(String name) {
+ super( name );
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure( cfg );
+ cfg.setProperty( Environment.RELEASE_CONNECTIONS, "on_close" );
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite(
ClobFromLobCreatorJDBC4ConnRelOnCloseTest.class );
+ }
+}
\ No newline at end of file
Added:
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4Test.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4Test.java
(rev 0)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobFromLobCreatorJDBC4Test.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -0,0 +1,112 @@
+//$Id: $
+/*
+ * 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.test.lob;
+
+import java.sql.SQLException;
+import java.sql.Clob;
+
+import junit.framework.Test;
+
+import org.hibernate.lob.LobCreatorImplJDBC4;
+import org.hibernate.cfg.Environment;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+import org.hibernate.Session;
+import org.hibernate.HibernateException;
+
+/**
+ * This class extends AbstractClobFromLobCreatorTest to determine if the
+ * correct LobCreator impl is used when Environment.USE_CONNECTION_FOR_LOB_CREATION
+ * is set to true. The actual impl should be the JDBC4 LobCreator, even when
+ * the JVM and/or JDBC driver do not support JDBC4. The JDBC4 LobCreator uses the
+ * Connection to create LOBs.
+ *
+ * @author Gail Badner
+ */
+public class ClobFromLobCreatorJDBC4Test extends AbstractClobFromLobCreatorTest {
+
+ public ClobFromLobCreatorJDBC4Test(String name) {
+ super( name );
+ }
+
+ protected Boolean getUseConnectionForLobCreationPropertyValue() {
+ return Boolean.TRUE;
+ }
+
+ protected Class getExpectedLobCreatorClass() {
+ return LobCreatorImplJDBC4.class;
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite( ClobFromLobCreatorJDBC4Test.class );
+ }
+
+ protected boolean skipLobLocatorTests() throws SQLException {
+ if ( ! Environment.jvmSupportsJDBC4() ) {
+ reportSkip( "JVM does not support creating LOBs using the connection",
"LOB support" );
+ return true;
+ }
+ if ( ! jvmAndDriverSupportUseConnectionForLobCreation() ) {
+ reportSkip( "Driver does not support creating LOBs using the connection",
"LOB support" );
+ return true;
+ }
+ return false;
+ }
+
+ public void testCreateClobLocatorSupport() throws Throwable {
+ Session s = openSession();
+ s.getTransaction().begin();
+ String str = buildRecursively( CLOB_SIZE, 'x' );
+ try {
+ Clob clob = createClobLocator( s, str );
+ if ( ! Environment.jvmSupportsJDBC4() ) {
+ fail( "should have thrown NoSuchMethodException" );
+ }
+ else if ( ! jvmAndDriverSupportUseConnectionForLobCreation() ) {
+ fail( "should have thrown AbstractMethodException" );
+ }
+ assertEquals( str, extractData( clob ) );
+ s.getTransaction().commit();
+ }
+ catch( HibernateException e ) {
+ s.getTransaction().rollback();
+ if ( e.getCause() instanceof NoSuchMethodException ) {
+ assertTrue( ! Environment.jvmSupportsJDBC4() &&
+ isUseConnectionForLobCreationEnabled() );
+ }
+ else if ( e.getCause() instanceof AbstractMethodError ) {
+ assertTrue( Environment.jvmSupportsJDBC4() &&
+ ! jvmAndDriverSupportUseConnectionForLobCreation() &&
+ isUseConnectionForLobCreationEnabled() );
+ }
+ else {
+ throw e;
+ }
+ }
+ finally {
+ s.close();
+ }
+ }
+}
\ No newline at end of file
Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobTest.java 2008-10-28 21:47:32
UTC (rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/ClobTest.java 2008-10-29 05:38:54
UTC (rev 15430)
@@ -1,196 +1,62 @@
+//$Id: $
+/*
+ * 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.test.lob;
import java.sql.Clob;
+import java.io.IOException;
+import java.io.StringReader;
import junit.framework.Test;
import org.hibernate.Hibernate;
-import org.hibernate.LockMode;
import org.hibernate.Session;
-import org.hibernate.dialect.Dialect;
-import org.hibernate.dialect.H2Dialect;
-import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase;
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
/**
- * Test various access scenarios for eager and lazy materialization
- * of CLOB data, as well as bounded and unbounded materialization
- * and mutation.
+ * This class extends AbstractClobTest so that LOBs are created using the
+ * Hibernate.createClob() APIs. These APIs do not use the connection to
+ * create LOBs.
*
* @author Steve Ebersole
*/
-public class ClobTest extends DatabaseSpecificFunctionalTestCase {
- private static final int CLOB_SIZE = 10000;
+public class ClobTest extends AbstractClobTest {
public ClobTest(String name) {
super( name );
}
- public String[] getMappings() {
- return new String[] { "lob/LobMappings.hbm.xml" };
- }
-
public static Test suite() {
return new FunctionalTestClassTestSuite( ClobTest.class );
}
- public boolean appliesTo(Dialect dialect) {
- if ( ! dialect.supportsExpectedLobUsagePattern() ) {
- reportSkip( "database/driver does not support expected LOB usage pattern",
"LOB support" );
- return false;
- }
- return true;
+ protected Clob createClobLocator(Session s, String str) {
+ return Hibernate.createClob( str );
}
- public void testBoundedMaterializedClobAccess() {
- String original = buildRecursively( CLOB_SIZE, 'x' );
- String changed = buildRecursively( CLOB_SIZE, 'y' );
-
- Session s = openSession();
- s.beginTransaction();
- LobHolder entity = new LobHolder();
- entity.setMaterializedClob( original );
- s.save( entity );
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
- assertEquals( CLOB_SIZE, entity.getMaterializedClob().length() );
- assertEquals( original, entity.getMaterializedClob() );
- entity.setMaterializedClob( changed );
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
- assertEquals( CLOB_SIZE, entity.getMaterializedClob().length() );
- assertEquals( changed, entity.getMaterializedClob() );
- s.delete( entity );
- s.getTransaction().commit();
- s.close();
+ protected Clob createClobLocatorFromStreamUsingLength(Session s, String str) throws
IOException {
+ return Hibernate.createClob( new StringReader( str ), str.length() );
}
-
- public void testBoundedClobLocatorAccess() throws Throwable {
- String original = buildRecursively( CLOB_SIZE, 'x' );
- String changed = buildRecursively( CLOB_SIZE, 'y' );
-
- Session s = openSession();
- s.beginTransaction();
- LobHolder entity = new LobHolder();
- entity.setClobLocator( Hibernate.createClob( original ) );
- s.save( entity );
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
- assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
- assertEquals( original, extractData( entity.getClobLocator() ) );
- s.getTransaction().commit();
- s.close();
-
- // test mutation via setting the new clob data...
- if ( supportsLobValueChangePropogation() ) {
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
- entity.getClobLocator().truncate( 1 );
- entity.getClobLocator().setString( 1, changed );
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
- assertNotNull( entity.getClobLocator() );
- assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
- assertEquals( changed, extractData( entity.getClobLocator() ) );
- entity.getClobLocator().truncate( 1 );
- entity.getClobLocator().setString( 1, original );
- s.getTransaction().commit();
- s.close();
- }
-
- // test mutation via supplying a new clob locator instance...
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId(), LockMode.UPGRADE );
- assertNotNull( entity.getClobLocator() );
- assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
- assertEquals( original, extractData( entity.getClobLocator() ) );
- entity.setClobLocator( Hibernate.createClob( changed ) );
- s.getTransaction().commit();
- s.close();
-
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
- assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
- assertEquals( changed, extractData( entity.getClobLocator() ) );
- s.delete( entity );
- s.getTransaction().commit();
- s.close();
-
- }
-
- public void testUnboundedClobLocatorAccess() throws Throwable {
- if ( ! supportsUnboundedLobLocatorMaterialization() ) {
- return;
- }
-
- // Note: unbounded mutation of the underlying lob data is completely
- // unsupported; most databases would not allow such a construct anyway.
- // Thus here we are only testing materialization...
-
- String original = buildRecursively( CLOB_SIZE, 'x' );
-
- Session s = openSession();
- s.beginTransaction();
- LobHolder entity = new LobHolder();
- entity.setClobLocator( Hibernate.createClob( original ) );
- s.save( entity );
- s.getTransaction().commit();
- s.close();
-
- // load the entity with the clob locator, and close the session/transaction;
- // at that point it is unbounded...
- s = openSession();
- s.beginTransaction();
- entity = ( LobHolder ) s.get( LobHolder.class, entity.getId() );
- s.getTransaction().commit();
- s.close();
-
- assertEquals( CLOB_SIZE, entity.getClobLocator().length() );
- assertEquals( original, extractData( entity.getClobLocator() ) );
-
- s = openSession();
- s.beginTransaction();
- s.delete( entity );
- s.getTransaction().commit();
- s.close();
- }
-
- private String extractData(Clob clob) throws Throwable {
- if ( getDialect() instanceof H2Dialect ) {
- return clob.getSubString( 1, ( int ) clob.length() );
- }
- else {
- char[] data = new char[ (int) clob.length() ];
- clob.getCharacterStream().read( data );
- return new String( data );
- }
- }
-
-
- private String buildRecursively(int size, char baseChar) {
- StringBuffer buff = new StringBuffer();
- for( int i = 0; i < size; i++ ) {
- buff.append( baseChar );
- }
- return buff.toString();
- }
-}
+}
\ No newline at end of file
Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/LobHolder.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/LobHolder.java 2008-10-28
21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/LobHolder.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -1,3 +1,28 @@
+//$Id: $
+/*
+ * 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.test.lob;
import java.io.Serializable;
Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/MaterializedBlobType.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/lob/MaterializedBlobType.java 2008-10-28
21:47:32 UTC (rev 15429)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/MaterializedBlobType.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -1,3 +1,28 @@
+//$Id: $
+/*
+ * 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.test.lob;
import java.sql.Types;
Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableData.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableData.java 2008-10-28
21:47:32 UTC (rev 15429)
+++ core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableData.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -1,4 +1,28 @@
-// $Id$
+//$Id$
+/*
+ * 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.test.lob;
import java.io.Serializable;
Modified: core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableTypeTest.java
===================================================================
---
core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableTypeTest.java 2008-10-28
21:47:32 UTC (rev 15429)
+++
core/branches/Branch_3_2/test/org/hibernate/test/lob/SerializableTypeTest.java 2008-10-29
05:38:54 UTC (rev 15430)
@@ -1,4 +1,28 @@
-// $Id$
+//$Id$
+/*
+ * 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.test.lob;
import junit.framework.Test;