From 5ee21b3aa81158c5904cfbb9a5859bc399912194 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Fri, 1 May 2009 23:21:00 +0000 Subject: [PATCH] HHH-3892 : Improve support for mapping SQL LONGVARCHAR and CLOB to Java String, SQL LONGVARBINARY and BLOB to Java byte[] git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@16501 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- .../main/java/org/hibernate/Hibernate.java | 15 +++ .../org/hibernate/dialect/DB2Dialect.java | 2 + .../org/hibernate/dialect/HSQLDialect.java | 2 + .../org/hibernate/dialect/MySQL5Dialect.java | 1 + .../org/hibernate/dialect/MySQLDialect.java | 5 +- .../hibernate/dialect/Oracle8iDialect.java | 3 + .../hibernate/dialect/PostgreSQLDialect.java | 2 + .../hibernate/dialect/SQLServerDialect.java | 2 + .../hibernate/dialect/SybaseASE15Dialect.java | 4 + .../type/AbstractLongBinaryType.java | 46 ++++++++ .../type/AbstractLongStringType.java | 94 +++++++++++++++ .../java/org/hibernate/type/ImageType.java | 44 +++++++ .../hibernate/type/MaterializedBlobType.java | 44 +++++++ .../hibernate/type/MaterializedClobType.java | 42 +++++++ .../java/org/hibernate/type/TextType.java | 69 +---------- .../java/org/hibernate/type/TypeFactory.java | 3 + .../{BlobTest.java => BlobLocatorTest.java} | 66 +++++------ .../{ClobTest.java => ClobLocatorTest.java} | 68 +++++------ .../hibernate/test/lob/ImageMappings.hbm.xml | 16 +++ .../org/hibernate/test/lob/ImageTest.java | 51 ++++++++ .../org/hibernate/test/lob/LobHolder.java | 39 ------- .../hibernate/test/lob/LobMappings.hbm.xml | 8 +- .../test/lob/LongByteArrayHolder.java | 54 +++++++++ .../hibernate/test/lob/LongByteArrayTest.java | 110 ++++++++++++++++++ .../hibernate/test/lob/LongStringHolder.java | 53 +++++++++ .../hibernate/test/lob/LongStringTest.java | 99 ++++++++++++++++ .../test/lob/MaterializedBlobMappings.hbm.xml | 16 +++ .../test/lob/MaterializedBlobTest.java | 60 ++++++++++ .../test/lob/MaterializedBlobType.java | 33 ------ .../test/lob/MaterializedClobMappings.hbm.xml | 16 +++ .../test/lob/MaterializedClobTest.java | 60 ++++++++++ .../test/lob/SerializableHolder.java | 56 +++++++++ .../test/lob/SerializableMappings.hbm.xml | 16 +++ .../test/lob/SerializableTypeTest.java | 43 +++++-- .../hibernate/test/lob/TextMappings.hbm.xml | 16 +++ .../java/org/hibernate/test/lob/TextTest.java | 51 ++++++++ 36 files changed, 1083 insertions(+), 226 deletions(-) create mode 100644 core/src/main/java/org/hibernate/type/AbstractLongBinaryType.java create mode 100644 core/src/main/java/org/hibernate/type/AbstractLongStringType.java create mode 100644 core/src/main/java/org/hibernate/type/ImageType.java create mode 100644 core/src/main/java/org/hibernate/type/MaterializedBlobType.java create mode 100644 core/src/main/java/org/hibernate/type/MaterializedClobType.java rename testsuite/src/test/java/org/hibernate/test/lob/{BlobTest.java => BlobLocatorTest.java} (75%) rename testsuite/src/test/java/org/hibernate/test/lob/{ClobTest.java => ClobLocatorTest.java} (75%) create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/ImageMappings.hbm.xml create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/ImageTest.java create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/LongByteArrayHolder.java create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/LongByteArrayTest.java create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/LongStringHolder.java create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/LongStringTest.java create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobMappings.hbm.xml create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobTest.java delete mode 100644 testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobType.java create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/MaterializedClobMappings.hbm.xml create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/MaterializedClobTest.java create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/SerializableHolder.java create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/SerializableMappings.hbm.xml create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/TextMappings.hbm.xml create mode 100644 testsuite/src/test/java/org/hibernate/test/lob/TextTest.java diff --git a/core/src/main/java/org/hibernate/Hibernate.java b/core/src/main/java/org/hibernate/Hibernate.java index f7a260d7b6..116f720745 100644 --- a/core/src/main/java/org/hibernate/Hibernate.java +++ b/core/src/main/java/org/hibernate/Hibernate.java @@ -79,6 +79,9 @@ import org.hibernate.type.YesNoType; import org.hibernate.type.CharArrayType; import org.hibernate.type.WrapperBinaryType; import org.hibernate.type.CharacterArrayType; +import org.hibernate.type.MaterializedBlobType; +import org.hibernate.type.ImageType; +import org.hibernate.type.MaterializedClobType; import org.hibernate.usertype.CompositeUserType; /** @@ -177,10 +180,22 @@ public final class Hibernate { * Hibernate Character[] type. */ public static final NullableType CHARACTER_ARRAY = new CharacterArrayType(); + /** + * Hibernate image type. + */ + public static final NullableType IMAGE = new ImageType(); /** * Hibernate text type. */ public static final NullableType TEXT = new TextType(); + /** + * Hibernate materialized_blob type. + */ + public static final NullableType MATERIALIZED_BLOB = new MaterializedBlobType(); + /** + * Hibernate materialized_clob type. + */ + public static final NullableType MATERIALIZED_CLOB = new MaterializedClobType(); /** * Hibernate blob type. */ diff --git a/core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/core/src/main/java/org/hibernate/dialect/DB2Dialect.java index 65fd03a799..c2f38d4c73 100644 --- a/core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -61,6 +61,8 @@ public class DB2Dialect extends Dialect { registerColumnType( Types.NUMERIC, "numeric($p,$s)" ); registerColumnType( Types.BLOB, "blob($l)" ); registerColumnType( Types.CLOB, "clob($l)" ); + registerColumnType( Types.LONGVARCHAR, "long varchar" ); + registerColumnType( Types.LONGVARBINARY, "long varchar for bit data" ); registerFunction("abs", new StandardSQLFunction("abs") ); registerFunction("absval", new StandardSQLFunction("absval") ); diff --git a/core/src/main/java/org/hibernate/dialect/HSQLDialect.java b/core/src/main/java/org/hibernate/dialect/HSQLDialect.java index ff77899009..8e0e9fb12d 100644 --- a/core/src/main/java/org/hibernate/dialect/HSQLDialect.java +++ b/core/src/main/java/org/hibernate/dialect/HSQLDialect.java @@ -81,6 +81,8 @@ public class HSQLDialect extends Dialect { //HSQL has no Blob/Clob support .... but just put these here for now! registerColumnType( Types.BLOB, "longvarbinary" ); registerColumnType( Types.CLOB, "longvarchar" ); + registerColumnType( Types.LONGVARBINARY, "longvarbinary" ); + registerColumnType( Types.LONGVARCHAR, "longvarchar" ); registerFunction( "ascii", new StandardSQLFunction( "ascii", Hibernate.INTEGER ) ); registerFunction( "char", new StandardSQLFunction( "char", Hibernate.CHARACTER ) ); diff --git a/core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java b/core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java index a59de9ce5b..fda7771665 100644 --- a/core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java +++ b/core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java @@ -36,5 +36,6 @@ public class MySQL5Dialect extends MySQLDialect { registerColumnType( Types.VARCHAR, "longtext" ); // registerColumnType( Types.VARCHAR, 16777215, "mediumtext" ); registerColumnType( Types.VARCHAR, 65535, "varchar($l)" ); + registerColumnType( Types.LONGVARCHAR, "longtext" ); } } diff --git a/core/src/main/java/org/hibernate/dialect/MySQLDialect.java b/core/src/main/java/org/hibernate/dialect/MySQLDialect.java index b9c1718e3c..a804672640 100644 --- a/core/src/main/java/org/hibernate/dialect/MySQLDialect.java +++ b/core/src/main/java/org/hibernate/dialect/MySQLDialect.java @@ -59,6 +59,8 @@ public class MySQLDialect extends Dialect { registerColumnType( Types.VARBINARY, 16777215, "mediumblob" ); registerColumnType( Types.VARBINARY, 65535, "blob" ); registerColumnType( Types.VARBINARY, 255, "tinyblob" ); + registerColumnType( Types.LONGVARBINARY, "longblob" ); + registerColumnType( Types.LONGVARBINARY, 16777215, "mediumblob" ); registerColumnType( Types.NUMERIC, "decimal($p,$s)" ); registerColumnType( Types.BLOB, "longblob" ); // registerColumnType( Types.BLOB, 16777215, "mediumblob" ); @@ -181,6 +183,7 @@ public class MySQLDialect extends Dialect { // registerColumnType( Types.VARCHAR, 16777215, "mediumtext" ); // registerColumnType( Types.VARCHAR, 65535, "text" ); registerColumnType( Types.VARCHAR, 255, "varchar($l)" ); + registerColumnType( Types.LONGVARCHAR, "longtext" ); } public String getAddColumnString() { @@ -344,4 +347,4 @@ public class MySQLDialect extends Dialect { public boolean supportsSubqueryOnMutatingTable() { return false; } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java b/core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java index 9bef9e7131..0360741802 100644 --- a/core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java +++ b/core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java @@ -98,6 +98,9 @@ public class Oracle8iDialect extends Dialect { registerColumnType( Types.BLOB, "blob" ); registerColumnType( Types.CLOB, "clob" ); + + registerColumnType( Types.LONGVARCHAR, "long" ); + registerColumnType( Types.LONGVARBINARY, "long raw" ); } protected void registerReverseHibernateTypeMappings() { diff --git a/core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java index 257f8f4bbb..90ba7e4d13 100644 --- a/core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -62,6 +62,8 @@ public class PostgreSQLDialect extends Dialect { registerColumnType( Types.TIME, "time" ); registerColumnType( Types.TIMESTAMP, "timestamp" ); registerColumnType( Types.VARBINARY, "bytea" ); + registerColumnType( Types.LONGVARCHAR, "text" ); + registerColumnType( Types.LONGVARBINARY, "bytea" ); registerColumnType( Types.CLOB, "text" ); registerColumnType( Types.BLOB, "oid" ); registerColumnType( Types.NUMERIC, "numeric($p, $s)" ); diff --git a/core/src/main/java/org/hibernate/dialect/SQLServerDialect.java b/core/src/main/java/org/hibernate/dialect/SQLServerDialect.java index f248a88afc..253726b586 100644 --- a/core/src/main/java/org/hibernate/dialect/SQLServerDialect.java +++ b/core/src/main/java/org/hibernate/dialect/SQLServerDialect.java @@ -42,6 +42,8 @@ public class SQLServerDialect extends SybaseDialect { public SQLServerDialect() { registerColumnType( Types.VARBINARY, "image" ); registerColumnType( Types.VARBINARY, 8000, "varbinary($l)" ); + registerColumnType( Types.LONGVARBINARY, "image" ); + registerColumnType( Types.LONGVARCHAR, "text" ); registerFunction( "second", new SQLFunctionTemplate( Hibernate.INTEGER, "datepart(second, ?1)" ) ); registerFunction( "minute", new SQLFunctionTemplate( Hibernate.INTEGER, "datepart(minute, ?1)" ) ); diff --git a/core/src/main/java/org/hibernate/dialect/SybaseASE15Dialect.java b/core/src/main/java/org/hibernate/dialect/SybaseASE15Dialect.java index 6acbcadeeb..533618aa21 100644 --- a/core/src/main/java/org/hibernate/dialect/SybaseASE15Dialect.java +++ b/core/src/main/java/org/hibernate/dialect/SybaseASE15Dialect.java @@ -50,6 +50,10 @@ import org.hibernate.dialect.function.VarArgsSQLFunction; public class SybaseASE15Dialect extends AbstractTransactSQLDialect { public SybaseASE15Dialect() { super(); + + registerColumnType( Types.LONGVARBINARY, "image" ); + registerColumnType( Types.LONGVARCHAR, "text" ); + registerFunction( "second", new SQLFunctionTemplate(Hibernate.INTEGER, "datepart(second, ?1)") ); registerFunction( "minute", new SQLFunctionTemplate(Hibernate.INTEGER, "datepart(minute, ?1)") ); registerFunction( "hour", new SQLFunctionTemplate(Hibernate.INTEGER, "datepart(hour, ?1)") ); diff --git a/core/src/main/java/org/hibernate/type/AbstractLongBinaryType.java b/core/src/main/java/org/hibernate/type/AbstractLongBinaryType.java new file mode 100644 index 0000000000..fbcb9ffc5d --- /dev/null +++ b/core/src/main/java/org/hibernate/type/AbstractLongBinaryType.java @@ -0,0 +1,46 @@ +//$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; + +/** + * An abstract type for mapping long binary SQL types to Java byte[]. + * + * @author Gail Badner + */ +public abstract class AbstractLongBinaryType extends AbstractBynaryType { + + public Class getReturnedClass() { + return byte[].class; + } + + protected Object toExternalFormat(byte[] bytes) { + return bytes; + } + + protected byte[] toInternalFormat(Object bytes) { + return ( byte[] ) bytes; + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hibernate/type/AbstractLongStringType.java b/core/src/main/java/org/hibernate/type/AbstractLongStringType.java new file mode 100644 index 0000000000..af8e7927a2 --- /dev/null +++ b/core/src/main/java/org/hibernate/type/AbstractLongStringType.java @@ -0,0 +1,94 @@ +//$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.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.hibernate.HibernateException; + +/** + * An abstract type for mapping long string SQL types to a Java String. + * @author Gavin King, Bertrand Renuart (from TextType) + */ +public abstract class AbstractLongStringType extends ImmutableType { + + public void set(PreparedStatement st, Object value, int index) throws HibernateException, SQLException { + String str = (String) value; + st.setCharacterStream( index, new StringReader(str), str.length() ); + } + + public Object get(ResultSet rs, String name) throws HibernateException, SQLException { + + // Retrieve the value of the designated column in the current row of this + // ResultSet object as a java.io.Reader object + Reader charReader = rs.getCharacterStream(name); + + // if the corresponding SQL value is NULL, the reader we got is NULL as well + if (charReader==null) return null; + + // Fetch Reader content up to the end - and put characters in a StringBuffer + StringBuffer sb = new StringBuffer(); + try { + char[] buffer = new char[2048]; + while (true) { + int amountRead = charReader.read(buffer, 0, buffer.length); + if ( amountRead == -1 ) break; + sb.append(buffer, 0, amountRead); + } + } + catch (IOException ioe) { + throw new HibernateException( "IOException occurred reading text", ioe ); + } + finally { + try { + charReader.close(); + } + catch (IOException e) { + throw new HibernateException( "IOException occurred closing stream", e ); + } + } + + // Return StringBuffer content as a large String + return sb.toString(); + } + + public Class getReturnedClass() { + return String.class; + } + + public String toString(Object val) { + return (String) val; + } + public Object fromStringValue(String xml) { + return xml; + } + +} \ No newline at end of file diff --git a/core/src/main/java/org/hibernate/type/ImageType.java b/core/src/main/java/org/hibernate/type/ImageType.java new file mode 100644 index 0000000000..8d52925703 --- /dev/null +++ b/core/src/main/java/org/hibernate/type/ImageType.java @@ -0,0 +1,44 @@ +//$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.sql.Types; + +/** + * image: A type that maps an SQL LONGVARBINARY to Java byte[]. + * + * @author Gail Badner + */ +public class ImageType extends AbstractLongBinaryType { + + public int sqlType() { + return Types.LONGVARBINARY; + } + + public String getName() { + return "image"; + } +} diff --git a/core/src/main/java/org/hibernate/type/MaterializedBlobType.java b/core/src/main/java/org/hibernate/type/MaterializedBlobType.java new file mode 100644 index 0000000000..567602bb25 --- /dev/null +++ b/core/src/main/java/org/hibernate/type/MaterializedBlobType.java @@ -0,0 +1,44 @@ +//$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.sql.Types; + +/** + * materialized_blob: A type that maps an SQL BLOB to Java byte[]. + * + * @author Gail Badner + */ +public class MaterializedBlobType extends AbstractLongBinaryType { + + public int sqlType() { + return Types.BLOB; + } + + public String getName() { + return "materialized_blob"; + } +} diff --git a/core/src/main/java/org/hibernate/type/MaterializedClobType.java b/core/src/main/java/org/hibernate/type/MaterializedClobType.java new file mode 100644 index 0000000000..f4d0be78e1 --- /dev/null +++ b/core/src/main/java/org/hibernate/type/MaterializedClobType.java @@ -0,0 +1,42 @@ +//$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.sql.Types; + +/** + * materialized_clob: A type that maps an SQL CLOB to a Java String. + * + * @author Gail Badner + */ +public class MaterializedClobType extends AbstractLongStringType { + + public int sqlType() { + return Types.CLOB; + } + + public String getName() { return "materialized_clob"; } +} \ No newline at end of file diff --git a/core/src/main/java/org/hibernate/type/TextType.java b/core/src/main/java/org/hibernate/type/TextType.java index 902fcb448c..25d092957e 100644 --- a/core/src/main/java/org/hibernate/type/TextType.java +++ b/core/src/main/java/org/hibernate/type/TextType.java @@ -1,3 +1,4 @@ +//$Id: $ /* * Hibernate, Relational Persistence for Idiomatic Java * @@ -24,79 +25,21 @@ */ package org.hibernate.type; -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; import java.sql.Types; -import org.hibernate.HibernateException; - /** - * text: A type that maps an SQL CLOB to a Java String. - * @author Gavin King, Bertrand Renuart + * text: A type that maps an SQL LONGVARCHAR to a Java String. + * + * @author Gail Badner */ -public class TextType extends ImmutableType { - - public void set(PreparedStatement st, Object value, int index) throws HibernateException, SQLException { - String str = (String) value; - st.setCharacterStream( index, new StringReader(str), str.length() ); - } - - public Object get(ResultSet rs, String name) throws HibernateException, SQLException { - - // Retrieve the value of the designated column in the current row of this - // ResultSet object as a java.io.Reader object - Reader charReader = rs.getCharacterStream(name); - - // if the corresponding SQL value is NULL, the reader we got is NULL as well - if (charReader==null) return null; - - // Fetch Reader content up to the end - and put characters in a StringBuffer - StringBuffer sb = new StringBuffer(); - try { - char[] buffer = new char[2048]; - while (true) { - int amountRead = charReader.read(buffer, 0, buffer.length); - if ( amountRead == -1 ) break; - sb.append(buffer, 0, amountRead); - } - } - catch (IOException ioe) { - throw new HibernateException( "IOException occurred reading text", ioe ); - } - finally { - try { - charReader.close(); - } - catch (IOException e) { - throw new HibernateException( "IOException occurred closing stream", e ); - } - } - - // Return StringBuffer content as a large String - return sb.toString(); - } +public class TextType extends AbstractLongStringType { public int sqlType() { - return Types.CLOB; //or Types.LONGVARCHAR? - } - - public Class getReturnedClass() { - return String.class; + return Types.LONGVARCHAR; } public String getName() { return "text"; } - public String toString(Object val) { - return (String) val; - } - public Object fromStringValue(String xml) { - return xml; - } - } diff --git a/core/src/main/java/org/hibernate/type/TypeFactory.java b/core/src/main/java/org/hibernate/type/TypeFactory.java index 8c8361cfc5..4dc9ab48c3 100644 --- a/core/src/main/java/org/hibernate/type/TypeFactory.java +++ b/core/src/main/java/org/hibernate/type/TypeFactory.java @@ -90,7 +90,10 @@ public final class TypeFactory { basics.put( Hibernate.TRUE_FALSE.getName(), Hibernate.TRUE_FALSE ); basics.put( Hibernate.YES_NO.getName(), Hibernate.YES_NO ); basics.put( Hibernate.BINARY.getName(), Hibernate.BINARY ); + basics.put( Hibernate.IMAGE.getName(), Hibernate.IMAGE ); basics.put( Hibernate.TEXT.getName(), Hibernate.TEXT ); + basics.put( Hibernate.MATERIALIZED_BLOB.getName(), Hibernate.MATERIALIZED_BLOB ); + basics.put( Hibernate.MATERIALIZED_CLOB.getName(), Hibernate.MATERIALIZED_CLOB ); basics.put( Hibernate.BLOB.getName(), Hibernate.BLOB ); basics.put( Hibernate.CLOB.getName(), Hibernate.CLOB ); basics.put( Hibernate.BIG_DECIMAL.getName(), Hibernate.BIG_DECIMAL ); diff --git a/testsuite/src/test/java/org/hibernate/test/lob/BlobTest.java b/testsuite/src/test/java/org/hibernate/test/lob/BlobLocatorTest.java similarity index 75% rename from testsuite/src/test/java/org/hibernate/test/lob/BlobTest.java rename to testsuite/src/test/java/org/hibernate/test/lob/BlobLocatorTest.java index de62ead9a4..b24f81fab5 100644 --- a/testsuite/src/test/java/org/hibernate/test/lob/BlobTest.java +++ b/testsuite/src/test/java/org/hibernate/test/lob/BlobLocatorTest.java @@ -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.Blob; @@ -14,14 +39,16 @@ import org.hibernate.junit.functional.FunctionalTestClassTestSuite; import org.hibernate.util.ArrayHelper; /** - * {@inheritDoc} + * Tests lazy materialization of data mapped by + * {@link org.hibernate.type.BlobType}, as well as bounded and unbounded + * materialization and mutation. * * @author Steve Ebersole */ -public class BlobTest extends DatabaseSpecificFunctionalTestCase { +public class BlobLocatorTest extends DatabaseSpecificFunctionalTestCase { private static final int BLOB_SIZE = 10000; - public BlobTest(String name) { + public BlobLocatorTest(String name) { super( name ); } @@ -30,7 +57,7 @@ public class BlobTest extends DatabaseSpecificFunctionalTestCase { } public static Test suite() { - return new FunctionalTestClassTestSuite( BlobTest.class ); + return new FunctionalTestClassTestSuite( BlobLocatorTest.class ); } public boolean appliesTo(Dialect dialect) { @@ -41,37 +68,6 @@ public class BlobTest extends DatabaseSpecificFunctionalTestCase { return true; } - 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 { byte[] original = buildRecursively( BLOB_SIZE, true ); byte[] changed = buildRecursively( BLOB_SIZE, false ); diff --git a/testsuite/src/test/java/org/hibernate/test/lob/ClobTest.java b/testsuite/src/test/java/org/hibernate/test/lob/ClobLocatorTest.java similarity index 75% rename from testsuite/src/test/java/org/hibernate/test/lob/ClobTest.java rename to testsuite/src/test/java/org/hibernate/test/lob/ClobLocatorTest.java index fb0b34a5d7..7c1af874e2 100644 --- a/testsuite/src/test/java/org/hibernate/test/lob/ClobTest.java +++ b/testsuite/src/test/java/org/hibernate/test/lob/ClobLocatorTest.java @@ -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.Clob; @@ -13,16 +38,16 @@ 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. + * Tests lazy materialization of data mapped by + * {@link org.hibernate.type.ClobType} as well as bounded and unbounded + * materialization and mutation. * * @author Steve Ebersole */ -public class ClobTest extends DatabaseSpecificFunctionalTestCase { +public class ClobLocatorTest extends DatabaseSpecificFunctionalTestCase { private static final int CLOB_SIZE = 10000; - public ClobTest(String name) { + public ClobLocatorTest(String name) { super( name ); } @@ -31,7 +56,7 @@ public class ClobTest extends DatabaseSpecificFunctionalTestCase { } public static Test suite() { - return new FunctionalTestClassTestSuite( ClobTest.class ); + return new FunctionalTestClassTestSuite( ClobLocatorTest.class ); } public boolean appliesTo(Dialect dialect) { @@ -42,37 +67,6 @@ public class ClobTest extends DatabaseSpecificFunctionalTestCase { return true; } - 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 { String original = buildRecursively( CLOB_SIZE, 'x' ); String changed = buildRecursively( CLOB_SIZE, 'y' ); diff --git a/testsuite/src/test/java/org/hibernate/test/lob/ImageMappings.hbm.xml b/testsuite/src/test/java/org/hibernate/test/lob/ImageMappings.hbm.xml new file mode 100644 index 0000000000..843f5cff58 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/ImageMappings.hbm.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/ImageTest.java b/testsuite/src/test/java/org/hibernate/test/lob/ImageTest.java new file mode 100644 index 0000000000..943e492106 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/ImageTest.java @@ -0,0 +1,51 @@ +//$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; + +/** + * Tests eager materialization and mutation of data mapped by + * {@link org.hibernate.type.ImageType}. + * + * @author Gail Badner + */ +public class ImageTest extends LongByteArrayTest { + + public ImageTest(String name) { + super( name ); + } + + public String[] getMappings() { + return new String[] { "lob/ImageMappings.hbm.xml" }; + } + + public static Test suite() { + return new FunctionalTestClassTestSuite( ImageTest.class ); + } +} \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/LobHolder.java b/testsuite/src/test/java/org/hibernate/test/lob/LobHolder.java index 22540459e2..c5c092284a 100644 --- a/testsuite/src/test/java/org/hibernate/test/lob/LobHolder.java +++ b/testsuite/src/test/java/org/hibernate/test/lob/LobHolder.java @@ -7,21 +7,10 @@ import java.sql.Blob; /** * An entity containing all kinds of good LOB-type data... *

- * {@link #serialData} is used to hold general serializable data which is - * mapped via the {@link org.hibernate.type.SerializableType}. - *

- * {@link #materializedClob} is used to hold CLOB data that is materialized - * into a String immediately; it is mapped via the - * {@link org.hibernate.type.TextType}. - *

* {@link #clobLocator} is used to hold CLOB data that is materialized lazily * via a JDBC CLOB locator; it is mapped via the * {@link org.hibernate.type.ClobType} *

- * {@link #materializedBlob} is used to hold BLOB data that is materialized - * into a byte array immediately; it is mapped via the - * {@link org.hibernate.test.lob.MaterializedBlobType}. - *

* {@link #blobLocator} is used to hold BLOB data that is materialized lazily * via a JDBC BLOB locator; it is mapped via the * {@link org.hibernate.type.BlobType} @@ -32,12 +21,8 @@ import java.sql.Blob; public class LobHolder { private Long id; - private Serializable serialData; - - private String materializedClob; private Clob clobLocator; - private byte[] materializedBlob; private Blob blobLocator; public Long getId() { @@ -48,22 +33,6 @@ public class LobHolder { this.id = id; } - public Serializable getSerialData() { - return serialData; - } - - public void setSerialData(Serializable serialData) { - this.serialData = serialData; - } - - public String getMaterializedClob() { - return materializedClob; - } - - public void setMaterializedClob(String materializedClob) { - this.materializedClob = materializedClob; - } - public Clob getClobLocator() { return clobLocator; } @@ -72,14 +41,6 @@ public class LobHolder { this.clobLocator = clobLocator; } - public byte[] getMaterializedBlob() { - return materializedBlob; - } - - public void setMaterializedBlob(byte[] materializedBlob) { - this.materializedBlob = materializedBlob; - } - public Blob getBlobLocator() { return blobLocator; } diff --git a/testsuite/src/test/java/org/hibernate/test/lob/LobMappings.hbm.xml b/testsuite/src/test/java/org/hibernate/test/lob/LobMappings.hbm.xml index ef325b7dc1..ac9ca03c88 100644 --- a/testsuite/src/test/java/org/hibernate/test/lob/LobMappings.hbm.xml +++ b/testsuite/src/test/java/org/hibernate/test/lob/LobMappings.hbm.xml @@ -10,13 +10,9 @@ - + - - - - - + \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/LongByteArrayHolder.java b/testsuite/src/test/java/org/hibernate/test/lob/LongByteArrayHolder.java new file mode 100644 index 0000000000..03dd5d2f8a --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/LongByteArrayHolder.java @@ -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; + +/** + * An entity containing data that is materialized into a byte array immediately. + * The hibernate type mapped for {@link #longByteArray} determines the SQL type + * asctually used. + * + * @author Gail Badner + */ +public class LongByteArrayHolder { + private Long id; + private byte[] longByteArray; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public byte[] getLongByteArray() { + return longByteArray; + } + + public void setLongByteArray(byte[] longByteArray) { + this.longByteArray = longByteArray; + } +} \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/LongByteArrayTest.java b/testsuite/src/test/java/org/hibernate/test/lob/LongByteArrayTest.java new file mode 100644 index 0000000000..6481984ab3 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/LongByteArrayTest.java @@ -0,0 +1,110 @@ +//$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.AssertionFailedError; +import org.hibernate.Session; +import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase; +import org.hibernate.util.ArrayHelper; + +/** + * Tests eager materialization and mutation of long byte arrays. + * + * @author Steve Ebersole + */ +public abstract class LongByteArrayTest extends DatabaseSpecificFunctionalTestCase { + private static final int ARRAY_SIZE = 10000; + + public LongByteArrayTest(String name) { + super( name ); + } + + public void testBoundedLongByteArrayAccess() { + byte[] original = buildRecursively( ARRAY_SIZE, true ); + byte[] changed = buildRecursively( ARRAY_SIZE, false ); + + Session s = openSession(); + s.beginTransaction(); + LongByteArrayHolder entity = new LongByteArrayHolder(); + s.save( entity ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + entity = ( LongByteArrayHolder ) s.get( LongByteArrayHolder.class, entity.getId() ); + assertNull( entity.getLongByteArray() ); + entity.setLongByteArray( original ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + entity = ( LongByteArrayHolder ) s.get( LongByteArrayHolder.class, entity.getId() ); + assertEquals( ARRAY_SIZE, entity.getLongByteArray().length ); + assertEquals( original, entity.getLongByteArray() ); + entity.setLongByteArray( changed ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + entity = ( LongByteArrayHolder ) s.get( LongByteArrayHolder.class, entity.getId() ); + assertEquals( ARRAY_SIZE, entity.getLongByteArray().length ); + assertEquals( changed, entity.getLongByteArray() ); + entity.setLongByteArray( null ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + entity = ( LongByteArrayHolder ) s.get( LongByteArrayHolder.class, entity.getId() ); + assertNull( entity.getLongByteArray() ); + s.delete( entity ); + s.getTransaction().commit(); + s.close(); + } + + 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" ); + } + } +} \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/LongStringHolder.java b/testsuite/src/test/java/org/hibernate/test/lob/LongStringHolder.java new file mode 100644 index 0000000000..300dd4bf84 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/LongStringHolder.java @@ -0,0 +1,53 @@ +//$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; + +/** + * An entity containing data that is materialized into a String immediately. + * + * @author Gail Badner + */ +public class LongStringHolder { + private Long id; + + private String longString; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getLongString() { + return longString; + } + + public void setLongString(String longString) { + this.longString = longString; + } +} \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/LongStringTest.java b/testsuite/src/test/java/org/hibernate/test/lob/LongStringTest.java new file mode 100644 index 0000000000..dbce1183f9 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/LongStringTest.java @@ -0,0 +1,99 @@ +//$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.Session; +import org.hibernate.junit.functional.DatabaseSpecificFunctionalTestCase; +import org.hibernate.junit.functional.FunctionalTestClassTestSuite; + +/** + * Tests eager materialization and mutation of long strings. + * + * @author Steve Ebersole + */ +public abstract class LongStringTest extends DatabaseSpecificFunctionalTestCase { + private static final int LONG_STRING_SIZE = 10000; + + public LongStringTest(String name) { + super( name ); + } + + public void testBoundedLongStringAccess() { + String original = buildRecursively( LONG_STRING_SIZE, 'x' ); + String changed = buildRecursively( LONG_STRING_SIZE, 'y' ); + + Session s = openSession(); + s.beginTransaction(); + LongStringHolder entity = new LongStringHolder(); + s.save( entity ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + entity = ( LongStringHolder ) s.get( LongStringHolder.class, entity.getId() ); + assertNull( entity.getLongString() ); + entity.setLongString( original ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + entity = ( LongStringHolder ) s.get( LongStringHolder.class, entity.getId() ); + assertEquals( LONG_STRING_SIZE, entity.getLongString().length() ); + assertEquals( original, entity.getLongString() ); + entity.setLongString( changed ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + entity = ( LongStringHolder ) s.get( LongStringHolder.class, entity.getId() ); + assertEquals( LONG_STRING_SIZE, entity.getLongString().length() ); + assertEquals( changed, entity.getLongString() ); + entity.setLongString( null ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + entity = ( LongStringHolder ) s.get( LongStringHolder.class, entity.getId() ); + assertNull( entity.getLongString() ); + s.delete( entity ); + s.getTransaction().commit(); + s.close(); + } + + 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 diff --git a/testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobMappings.hbm.xml b/testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobMappings.hbm.xml new file mode 100644 index 0000000000..5aaec0da90 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobMappings.hbm.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobTest.java b/testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobTest.java new file mode 100644 index 0000000000..13e49f5828 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobTest.java @@ -0,0 +1,60 @@ +//$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.dialect.Dialect; + +/** + * Tests eager materialization and mutation of data mapped by + * {@link org.hibernate.type.MaterializedBlobType}. + * + * @author Gail Badner + */ +public class MaterializedBlobTest extends LongByteArrayTest { + + public MaterializedBlobTest(String name) { + super( name ); + } + + public String[] getMappings() { + return new String[] { "lob/MaterializedBlobMappings.hbm.xml" }; + } + + public static Test suite() { + return new FunctionalTestClassTestSuite( MaterializedBlobTest.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; + } +} \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobType.java b/testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobType.java deleted file mode 100644 index 920bb49c83..0000000000 --- a/testsuite/src/test/java/org/hibernate/test/lob/MaterializedBlobType.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.hibernate.test.lob; - -import java.sql.Types; - -import org.hibernate.type.AbstractBynaryType; - -/** - * {@inheritDoc} - * - * @author Steve Ebersole - */ -public class MaterializedBlobType extends AbstractBynaryType { - - public int sqlType() { - return Types.BLOB; - } - - public String getName() { - return "materialized-blob"; - } - - public Class getReturnedClass() { - return byte[].class; - } - - protected Object toExternalFormat(byte[] bytes) { - return bytes; - } - - protected byte[] toInternalFormat(Object bytes) { - return ( byte[] ) bytes; - } -} diff --git a/testsuite/src/test/java/org/hibernate/test/lob/MaterializedClobMappings.hbm.xml b/testsuite/src/test/java/org/hibernate/test/lob/MaterializedClobMappings.hbm.xml new file mode 100644 index 0000000000..5b0b06b87e --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/MaterializedClobMappings.hbm.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/MaterializedClobTest.java b/testsuite/src/test/java/org/hibernate/test/lob/MaterializedClobTest.java new file mode 100644 index 0000000000..550168a927 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/MaterializedClobTest.java @@ -0,0 +1,60 @@ +//$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.dialect.Dialect; + +/** + * Tests eager materialization and mutation of data mapped by + * {@link org.hibernate.type.MaterializedClobType}. + * + * @author Gail Badner + */ +public class MaterializedClobTest extends LongStringTest { + + public MaterializedClobTest(String name) { + super( name ); + } + + public String[] getMappings() { + return new String[] { "lob/MaterializedClobMappings.hbm.xml" }; + } + + public static Test suite() { + return new FunctionalTestClassTestSuite( MaterializedClobTest.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; + } +} \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/SerializableHolder.java b/testsuite/src/test/java/org/hibernate/test/lob/SerializableHolder.java new file mode 100644 index 0000000000..a1ab4b2b8f --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/SerializableHolder.java @@ -0,0 +1,56 @@ +//$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; + +/** + * An entity containing serializable data which is + * mapped via the {@link org.hibernate.type.SerializableType}. + * + * @author Steve Ebersole + */ +public class SerializableHolder { + private Long id; + + private Serializable serialData; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Serializable getSerialData() { + return serialData; + } + + public void setSerialData(Serializable serialData) { + this.serialData = serialData; + } +} \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/SerializableMappings.hbm.xml b/testsuite/src/test/java/org/hibernate/test/lob/SerializableMappings.hbm.xml new file mode 100644 index 0000000000..c8bde1870f --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/SerializableMappings.hbm.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/SerializableTypeTest.java b/testsuite/src/test/java/org/hibernate/test/lob/SerializableTypeTest.java index d54813eaf3..c43fdf4111 100644 --- a/testsuite/src/test/java/org/hibernate/test/lob/SerializableTypeTest.java +++ b/testsuite/src/test/java/org/hibernate/test/lob/SerializableTypeTest.java @@ -24,7 +24,7 @@ public class SerializableTypeTest extends FunctionalTestCase { } public String[] getMappings() { - return new String[] { "lob/LobMappings.hbm.xml" }; + return new String[] { "lob/SerializableMappings.hbm.xml" }; } public static Test suite() { @@ -37,30 +37,49 @@ public class SerializableTypeTest extends FunctionalTestCase { } public void testNewSerializableType() { - // Sybase dialects do not support ResultSet.getBlob(String) - if ( getDialect() instanceof SybaseDialect || getDialect() instanceof Sybase11Dialect || getDialect() instanceof SybaseASE15Dialect || getDialect() instanceof SybaseAnywhereDialect ) { - return; - } - - final String payloadText = "Initial payload"; + final String initialPayloadText = "Initial payload"; + final String changedPayloadText = "Changed payload"; Session s = openSession(); s.beginTransaction(); - LobHolder holder = new LobHolder(); - holder.setSerialData( new SerializableData( payloadText ) ); + SerializableHolder holder = new SerializableHolder(); s.save( holder ); s.getTransaction().commit(); s.close(); s = openSession(); s.beginTransaction(); - holder = ( LobHolder ) s.get( LobHolder.class, holder.getId() ); + holder = ( SerializableHolder ) s.get( SerializableHolder.class, holder.getId() ); + assertNull( holder.getSerialData() ); + holder.setSerialData( new SerializableData( initialPayloadText ) ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + holder = ( SerializableHolder ) s.get( SerializableHolder.class, holder.getId() ); SerializableData serialData = ( SerializableData ) holder.getSerialData(); - assertEquals( payloadText, serialData.getPayload() ); + assertEquals( initialPayloadText, serialData.getPayload() ); + holder.setSerialData( new SerializableData( changedPayloadText ) ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + holder = ( SerializableHolder ) s.get( SerializableHolder.class, holder.getId() ); + serialData = ( SerializableData ) holder.getSerialData(); + assertEquals( changedPayloadText, serialData.getPayload() ); + holder.setSerialData( null ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + holder = ( SerializableHolder ) s.get( SerializableHolder.class, holder.getId() ); + assertNull( holder.getSerialData() ); s.delete( holder ); s.getTransaction().commit(); s.close(); } - } diff --git a/testsuite/src/test/java/org/hibernate/test/lob/TextMappings.hbm.xml b/testsuite/src/test/java/org/hibernate/test/lob/TextMappings.hbm.xml new file mode 100644 index 0000000000..a8b61310c7 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/TextMappings.hbm.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testsuite/src/test/java/org/hibernate/test/lob/TextTest.java b/testsuite/src/test/java/org/hibernate/test/lob/TextTest.java new file mode 100644 index 0000000000..d8cb416d7a --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/lob/TextTest.java @@ -0,0 +1,51 @@ +//$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; + +/** + * Test eager materialization and mutation data mapped by + * #{@link org.hibernate.type.TextType}. + * + * @author Gail Badner + */ +public class TextTest extends LongStringTest { + + public TextTest(String name) { + super( name ); + } + + public String[] getMappings() { + return new String[] { "lob/TextMappings.hbm.xml" }; + } + + public static Test suite() { + return new FunctionalTestClassTestSuite( TextTest.class ); + } +} \ No newline at end of file