diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java index 83226e6516..3b07b41a22 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SQLiteDialect.java @@ -109,7 +109,6 @@ public class SQLiteDialect extends Dialect { registerColumnType( Types.BINARY, "blob" ); registerColumnType( Types.VARBINARY, "blob" ); - registerColumnType( Types.LONGVARBINARY, "blob" ); uniqueDelegate = new SQLiteUniqueDelegate( this ); } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java index a430e8f6d0..a85f3f7a6e 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java @@ -55,22 +55,18 @@ public class SybaseAnywhereDialect extends SybaseDialect { registerColumnType( Types.TIMESTAMP, "timestamp" ); registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp with time zone" ); - final int maxStringLength = 32_767; - - registerColumnType( Types.CHAR, maxStringLength, "char($l)" ); - registerColumnType( Types.VARCHAR, maxStringLength, "varchar($l)" ); registerColumnType( Types.VARCHAR, "long varchar)" ); - - registerColumnType( Types.NCHAR, maxStringLength, "nchar($l)" ); - registerColumnType( Types.NVARCHAR, maxStringLength, "nvarchar($l)" ); registerColumnType( Types.NVARCHAR, "long nvarchar)" ); //note: 'binary' is actually a synonym for 'varbinary' - registerColumnType( Types.BINARY, maxStringLength, "binary($l)" ); - registerColumnType( Types.VARBINARY, maxStringLength, "varbinary($l)" ); registerColumnType( Types.VARBINARY, "long binary)" ); } + @Override + public int getMaxVarcharLength() { + return 32_767; + } + @Override public SqlAstTranslatorFactory getSqlAstTranslatorFactory() { return new StandardSqlAstTranslatorFactory() { diff --git a/hibernate-core/src/main/java/org/hibernate/Length.java b/hibernate-core/src/main/java/org/hibernate/Length.java new file mode 100644 index 0000000000..891fd26b70 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/Length.java @@ -0,0 +1,67 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate; + +/** + * Defines a list of useful constant values that may be used + * to specify long column lengths in the JPA + * {@link jakarta.persistence.Column} annotation. + *

+ * For example, {@code @Column(length=LONG16)} would specify + * that Hibernate should generate DDL with a column type + * capable of holding strings with 16-bit lengths. + * + * @see jakarta.persistence.Column#length() + * + * @author Gavin King + */ +public final class Length { + /** + * The default length for a column in JPA. + * + * @see jakarta.persistence.Column#length() + * @see org.hibernate.type.descriptor.java.JavaType#getDefaultSqlLength + */ + public static final int DEFAULT = 255; + /** + * Used to select a variable-length SQL type large + * enough to contain values of maximum length 32600. + * This arbitrary-looking number was chosen because + * some databases support variable-length types + * right up to a limit that is just slightly below + * 32767. (For some, the limit is 32672 characters.) + *

+ * This is also the default length for a column + * declared using + * {@code @JdbcTypeCode(Types.LONGVARCHAR)} or + * {@code @JdbcTypeCode(Types.LONGVARBINARY)}. + * + * @see org.hibernate.type.descriptor.java.JavaType#getLongSqlLength + */ + public static final int LONG = 32_600; + /** + * The maximum length that fits in 16 bits. + * Used to select a variable-length SQL type large + * enough to contain values of maximum length 32767. + */ + public static final int LONG16 = Short.MAX_VALUE; + /** + * The maximum length of a Java string, that is, + * the maximum length that fits in 32 bits. + * Used to select a variable-length SQL type large + * enough to contain any Java string. + */ + public static final int LONG32 = Integer.MAX_VALUE; + /** + * The default length for a LOB column. + * + * @see org.hibernate.dialect.Dialect#getDefaultLobLength + */ + public static final int LOB_DEFAULT = 1_048_576; + + private Length() {} +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java index d99f311d1f..9113fc9ada 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/CockroachDialect.java @@ -95,20 +95,23 @@ public class CockroachDialect extends Dialect { registerColumnType( Types.TINYINT, "smallint" ); //no tinyint + //use 'string' instead of 'varchar' + registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "string($l)"); + registerColumnType( Types.VARCHAR, "string"); + //no binary/varbinary registerColumnType( Types.VARBINARY, "bytes" ); registerColumnType( Types.BINARY, "bytes" ); //no clob - registerColumnType( Types.LONGVARCHAR, "string" ); registerColumnType( Types.CLOB, "string" ); //no nchar/nvarchar registerColumnType( Types.NCHAR, "string($l)" ); - registerColumnType( Types.NVARCHAR, "string($l)" ); + registerColumnType( Types.NVARCHAR, getMaxNVarcharLength(), "string($l)" ); + registerColumnType( Types.NVARCHAR, "string"); //no nclob - registerColumnType( Types.LONGNVARCHAR, "string" ); registerColumnType( Types.NCLOB, "string" ); registerColumnType( SqlTypes.UUID, "uuid" ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java index 093f9b9d36..e4e7ca9db3 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -101,14 +101,16 @@ public class DB2Dialect extends Dialect { registerColumnType( Types.NUMERIC, "decimal($p,$s)" ); if ( getVersion().isBefore( 11 ) ) { - registerColumnType( Types.BINARY, "varchar($l) for bit data" ); //should use 'binary' since version 11 registerColumnType( Types.BINARY, 254, "char($l) for bit data" ); //should use 'binary' since version 11 - registerColumnType( Types.VARBINARY, "varchar($l) for bit data" ); //should use 'varbinary' since version 11 + registerColumnType( Types.BINARY, "varchar($l) for bit data" ); //should use 'binary' since version 11 + + registerColumnType( Types.VARBINARY, getMaxVarbinaryLength(), "varchar($l) for bit data" ); //should use 'varbinary' since version 11 //prior to DB2 11, the 'boolean' type existed, //but was not allowed as a column type registerColumnType( Types.BOOLEAN, "smallint" ); } + registerColumnType( Types.VARBINARY, "blob($l)" ); registerColumnType( Types.BLOB, "blob($l)" ); registerColumnType( Types.CLOB, "clob($l)" ); @@ -117,7 +119,8 @@ public class DB2Dialect extends Dialect { registerColumnType( Types.TIME_WITH_TIMEZONE, "time" ); // The long varchar data type was deprecated in DB2 and shouldn't be used anymore - registerColumnType( Types.LONGVARCHAR, "clob($l)" ); + registerColumnType( Types.VARCHAR, "clob($l)" ); + registerColumnType( Types.NVARCHAR, "nclob($l)" ); //not keywords, at least not in DB2 11, //but perhaps they were in older versions? @@ -143,6 +146,11 @@ public class DB2Dialect extends Dialect { return new DB2UniqueDelegate( this ); } + @Override + public int getMaxVarcharLength() { + return 32_672; + } + @Override public DatabaseVersion getVersion() { return version; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java index cda8158c76..2f232ffc8c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DerbyDialect.java @@ -120,10 +120,11 @@ public class DerbyDialect extends Dialect { registerColumnType( Types.NUMERIC, "decimal($p,$s)" ); registerColumnType( Types.BINARY, 254, "char($l) for bit data" ); - registerColumnType( Types.BINARY, 32672, "varchar($l) for bit data" ); + registerColumnType( Types.BINARY, getMaxVarbinaryLength(), "varchar($l) for bit data" ); registerColumnType( Types.BINARY, "long varchar for bit data" ); - registerColumnType( Types.VARBINARY, 32672, "varchar($l) for bit data" ); - registerColumnType( Types.VARBINARY, "long varchar for bit data" ); + registerColumnType( Types.VARBINARY, getMaxVarbinaryLength(), "varchar($l) for bit data" ); + registerColumnType( Types.VARBINARY, 32_700,"long varchar for bit data" ); + registerColumnType( Types.VARBINARY, "blob($l)" ); registerColumnType( Types.BLOB, "blob($l)" ); registerColumnType( Types.CLOB, "clob($l)" ); @@ -131,7 +132,8 @@ public class DerbyDialect extends Dialect { registerColumnType( Types.TIMESTAMP, "timestamp" ); registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp" ); - registerColumnType( Types.LONGVARCHAR, "long varchar" ); + registerColumnType( Types.VARCHAR, 32_700, "long varchar" ); + registerColumnType( Types.VARCHAR, "clob($l)" ); registerDerbyKeywords(); @@ -142,6 +144,11 @@ public class DerbyDialect extends Dialect { getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, NO_BATCH ); } + @Override + public int getMaxVarcharLength() { + return 32_672; + } + @Override public String getTypeName(int code, Size size) throws HibernateException { if ( code == Types.CHAR ) { diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index 3691a81636..e5c2be84cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -221,7 +221,41 @@ public abstract class Dialect implements ConversionContext { // constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ protected Dialect() { + this(true); + } + protected Dialect(boolean autoRegisterColumnTypes) { + uniqueDelegate = new DefaultUniqueDelegate( this ); + sizeStrategy = new SizeStrategyImpl(); + if (autoRegisterColumnTypes) { + registerDefaultColumnTypes(); + } + registerHibernateTypes(); + registerDefaultKeywords(); + } + + protected void registerDefaultColumnTypes() { + registerDefaultColumnTypes( getMaxVarcharLength(), getMaxNVarcharLength(), getMaxVarbinaryLength() ); + } + + /** + * Register an ANSI-standard column type for each JDBC type defined + * by {@link Types}. These mappings may be overridden by a concrete + * {@code Dialect} by calling {@link #registerColumnType(int,String)} + * from the constructor. + *

+ * Note that {@link Types#LONGVARCHAR}, {@link Types#LONGNVARCHAR} + * and {@link Types#LONGVARBINARY} are considered synonyms for their + * non-{@code LONG} counterparts, with the only difference being that + * a different default length is used: {@link org.hibernate.Length#LONG} + * instead of {@link org.hibernate.Length#DEFAULT}. Concrete dialects + * should usually avoid registering mappings for these JDBC types. + * + * @param maxVarcharLength the maximum length of the {@link Types#VARCHAR} type + * @param maxNVarcharLength the maximum length of the {@link Types#NVARCHAR} type + * @param maxVarBinaryLength the maximum length of the {@link Types#VARBINARY} type + */ + protected void registerDefaultColumnTypes(int maxVarcharLength, int maxNVarcharLength, int maxVarBinaryLength) { registerColumnType( Types.BOOLEAN, "boolean" ); registerColumnType( Types.TINYINT, "tinyint" ); @@ -249,17 +283,19 @@ public abstract class Dialect implements ConversionContext { registerColumnType( Types.TIME_WITH_TIMEZONE, "time with time zone" ); registerColumnType( Types.BINARY, "binary($l)" ); - registerColumnType( Types.VARBINARY, "varbinary($l)" ); + registerColumnType( Types.VARBINARY, maxVarBinaryLength, "varbinary($l)" ); registerColumnType( Types.BLOB, "blob" ); registerColumnType( Types.CHAR, "char($l)" ); - registerColumnType( Types.VARCHAR, "varchar($l)" ); + registerColumnType( Types.VARCHAR, maxVarcharLength, "varchar($l)" ); registerColumnType( Types.CLOB, "clob" ); registerColumnType( Types.NCHAR, "nchar($l)" ); - registerColumnType( Types.NVARCHAR, "nvarchar($l)" ); + registerColumnType( Types.NVARCHAR, maxNVarcharLength, "nvarchar($l)" ); registerColumnType( Types.NCLOB, "nclob" ); + } + protected void registerHibernateTypes() { // register hibernate types for default use in scalar sqlquery type auto detection registerHibernateType( Types.BOOLEAN, StandardBasicTypes.BOOLEAN.getName() ); @@ -298,11 +334,6 @@ public abstract class Dialect implements ConversionContext { registerHibernateType( Types.DATE, StandardBasicTypes.DATE.getName() ); registerHibernateType( Types.TIME, StandardBasicTypes.TIME.getName() ); registerHibernateType( Types.TIMESTAMP, StandardBasicTypes.TIMESTAMP.getName() ); - - registerDefaultKeywords(); - - uniqueDelegate = new DefaultUniqueDelegate( this ); - sizeStrategy = new SizeStrategyImpl(); } protected void registerDefaultKeywords() { @@ -382,7 +413,7 @@ public abstract class Dialect implements ConversionContext { /** * Does the given JDBC type code represent some sort of - * string type? + * character string type? * @param sqlType a JDBC type code from {@link Types} */ private static boolean isCharacterType(int sqlType) { @@ -399,6 +430,38 @@ public abstract class Dialect implements ConversionContext { } } + /** + * Does the given JDBC type code represent some sort of + * variable-length character string type? + * @param sqlType a JDBC type code from {@link Types} + */ + private static boolean isVarcharType(int sqlType) { + switch (sqlType) { + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.NVARCHAR: + case Types.LONGNVARCHAR: + return true; + default: + return false; + } + } + + /** + * Does the given JDBC type code represent some sort of + * variable-length binary string type? + * @param sqlType a JDBC type code from {@link Types} + */ + private static boolean isVarbinaryType(int sqlType) { + switch (sqlType) { + case Types.VARBINARY: + case Types.LONGVARBINARY: + return true; + default: + return false; + } + } + /** * Render a SQL check condition for a column that represents a boolean value. */ @@ -1021,12 +1084,20 @@ public abstract class Dialect implements ConversionContext { /** * Do the given JDBC type codes, as defined in {@link Types} represent - * essentially the same type in this dialect of SQL? The default - * implementation treats {@link Types#NUMERIC NUMERIC} and + * essentially the same type in this dialect of SQL? + *

+ * The default implementation treats {@link Types#NUMERIC NUMERIC} and * {@link Types#DECIMAL DECIMAL} as the same type, and * {@link Types#FLOAT FLOAT}, {@link Types#REAL REAL}, and * {@link Types#DOUBLE DOUBLE} as essentially the same type, since the * ANSI SQL specification fails to meaningfully distinguish them. + *

+ * The default implementation also treats {@link Types#VARCHAR VARCHAR}, + * {@link Types#NVARCHAR NVARCHAR}, {@link Types#LONGVARCHAR LONGVARCHAR}, + * and {@link Types#LONGNVARCHAR LONGNVARCHAR} as the same type, and + * {@link Types#VARBINARY BINARY} and + * {@link Types#LONGVARBINARY LONGVARBINARY} as the same type, since + * Hibernate doesn't really differentiate these types. * * @param typeCode1 the first JDBC type code * @param typeCode2 the second JDBC type code @@ -1036,7 +1107,9 @@ public abstract class Dialect implements ConversionContext { public boolean equivalentTypes(int typeCode1, int typeCode2) { return typeCode1==typeCode2 || isNumericOrDecimal(typeCode1) && isNumericOrDecimal(typeCode2) - || isFloatOrRealOrDouble(typeCode1) && isFloatOrRealOrDouble(typeCode2); + || isFloatOrRealOrDouble(typeCode1) && isFloatOrRealOrDouble(typeCode2) + || isVarcharType(typeCode1) && isVarcharType(typeCode2) + || isVarbinaryType(typeCode1) && isVarbinaryType(typeCode2); } private static boolean isNumericOrDecimal(int typeCode) { @@ -1152,6 +1225,10 @@ public abstract class Dialect implements ConversionContext { String result = typeNames.get( code, size.getLength(), size.getPrecision(), size.getScale() ); if ( result == null ) { switch ( code ) { + // these are no longer considered separate column types as such + // they're just used to indicate that JavaType.getLongSqlLength() + // should be used by default (and that's already handled by the + // time we get to here) case Types.LONGVARCHAR: return getTypeName( Types.VARCHAR, size ); case Types.LONGNVARCHAR: @@ -3467,6 +3544,36 @@ public abstract class Dialect implements ConversionContext { return sizeStrategy; } + /** + * The longest possible length of a {@link java.sql.Types#VARCHAR}-like column. + * For longer column lengths, use some sort of {@code text}-like type for the + * column. + */ + public int getMaxVarcharLength() { + //the longest possible length of a Java string + return Integer.MAX_VALUE; + } + + /** + * The longest possible length of a {@link java.sql.Types#NVARCHAR}-like column. + * For longer column lengths, use some sort of {@code text}-like type for the + * column. + */ + public int getMaxNVarcharLength() { + //for most databases it's the same as for VARCHAR + return getMaxVarcharLength(); + } + + /** + * The longest possible length of a {@link java.sql.Types#VARBINARY}-like column. + * For longer column lengths, use some sort of {@code image}-like type for the + * column. + */ + public int getMaxVarbinaryLength() { + //for most databases it's the same as for VARCHAR + return getMaxVarcharLength(); + } + public long getDefaultLobLength() { return Size.DEFAULT_LOB_LENGTH; } @@ -3634,7 +3741,7 @@ public abstract class Dialect implements ConversionContext { switch (jdbcTypeCode) { case Types.BIT: // Use the default length for Boolean if we encounter the JPA default 255 instead - if ( javaType.getJavaTypeClass() == Boolean.class && length != null && length == 255 ) { + if ( javaType.getJavaTypeClass() == Boolean.class && length != null && length == Size.DEFAULT_LENGTH ) { length = null; } size.setLength( javaType.getDefaultSqlLength( Dialect.this, jdbcType ) ); @@ -3642,7 +3749,7 @@ public abstract class Dialect implements ConversionContext { case Types.CHAR: case Types.NCHAR: // Use the default length for char and UUID if we encounter the JPA default 255 instead - if ( length != null && length == 255 ) { + if ( length != null && length == Size.DEFAULT_LENGTH ) { if ( javaType.getJavaTypeClass() == Character.class || javaType.getJavaTypeClass() == UUID.class ) { length = null; } @@ -3654,7 +3761,7 @@ public abstract class Dialect implements ConversionContext { case Types.BINARY: case Types.VARBINARY: // Use the default length for UUID if we encounter the JPA default 255 instead - if ( javaType.getJavaTypeClass() == UUID.class && length != null && length == 255 ) { + if ( javaType.getJavaTypeClass() == UUID.class && length != null && length == Size.DEFAULT_LENGTH ) { length = null; } size.setLength( javaType.getDefaultSqlLength( Dialect.this, jdbcType ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java index bcc173be1e..00369653b8 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -128,7 +128,12 @@ public class H2Dialect extends Dialect { // http://code.google.com/p/h2database/issues/detail?id=235 getDefaultProperties().setProperty( AvailableSettings.NON_CONTEXTUAL_LOB_CREATION, "true" ); + registerColumnType( Types.VARCHAR, "varchar" ); + registerColumnType( Types.NVARCHAR, "varchar" ); + registerColumnType( Types.VARBINARY, "varbinary" ); + registerColumnType( SqlTypes.ARRAY, "array" ); + if ( version.isSameOrAfter( 1, 4, 32 ) ) { this.sequenceInformationExtractor = version.isSameOrAfter( 1, 4, 201 ) ? SequenceInformationExtractorLegacyImpl.INSTANCE @@ -240,6 +245,11 @@ public class H2Dialect extends Dialect { CommonFunctionFactory.rownum( queryEngine ); } + @Override + public int getMaxVarcharLength() { + return 1_048_576; + } + @Override public String currentTime() { return useLocalTime ? "localtime" : super.currentTime(); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java index 67be45a8a2..fab80d83f8 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HANAColumnStoreDialect.java @@ -47,12 +47,10 @@ public class HANAColumnStoreDialect extends AbstractHANADialect { public HANAColumnStoreDialect(DatabaseVersion version) { super( version ); if ( version.isSameOrAfter( 4 ) ) { - registerColumnType( Types.CHAR, "nvarchar(1)" ); - registerColumnType( Types.VARCHAR, 5000, "nvarchar($l)" ); - registerColumnType( Types.LONGVARCHAR, 5000, "nvarchar($l)" ); + registerColumnType( Types.CHAR, "nvarchar($l)" ); + registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "nvarchar($l)" ); // for longer values map to clob/nclob - registerColumnType( Types.LONGVARCHAR, "nclob" ); registerColumnType( Types.VARCHAR, "nclob" ); registerColumnType( Types.CLOB, "nclob" ); @@ -69,6 +67,11 @@ public class HANAColumnStoreDialect extends AbstractHANADialect { } } + @Override + public int getMaxVarcharLength() { + return 5000; + } + @Override public DatabaseVersion getVersion(){ return version; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBDialect.java index fce2a752da..ca4478570a 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBDialect.java @@ -60,10 +60,6 @@ public class MariaDBDialect extends MySQLDialect { this.version = version; } - protected int getMaxVarcharLen() { - return getMySQLVersion().isBefore( 5 ) ? 255 : 65_534; - } - @Override public DatabaseVersion getVersion() { return version; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java index b07d4a5610..1cdad7562f 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java @@ -105,10 +105,12 @@ public class MySQLDialect extends Dialect { } public MySQLDialect(DatabaseVersion version, int characterSetBytesPerCharacter) { - super(); + super(false); this.version = version; this.characterSetBytesPerCharacter = characterSetBytesPerCharacter; + registerDefaultColumnTypes(); + String storageEngine = Environment.getProperties().getProperty( Environment.STORAGE_ENGINE ); if (storageEngine == null) { storageEngine = System.getProperty( Environment.STORAGE_ENGINE ); @@ -141,41 +143,40 @@ public class MySQLDialect extends Dialect { registerColumnType(Types.TIMESTAMP_WITH_TIMEZONE, "timestamp($p)"); } - // max length for VARCHAR changed in 5.0.3 - final int maxVarcharLen = getMaxVarcharLen(); - - registerColumnType( Types.VARCHAR, maxVarcharLen, "varchar($l)" ); - registerColumnType( Types.VARBINARY, maxVarcharLen, "varbinary($l)" ); - final int maxTinyLobLen = 255; final int maxLobLen = 65_535; final int maxMediumLobLen = 16_777_215; - final long maxLongLobLen = 4_294_967_295L; + //the maximum long LOB length is 4_294_967_295, bigger than any Java string - registerColumnType( Types.VARCHAR, maxLongLobLen, "longtext" ); + registerColumnType( Types.VARCHAR, "longtext" ); registerColumnType( Types.VARCHAR, maxMediumLobLen, "mediumtext" ); - if ( maxVarcharLen < maxLobLen ) { + if ( getMaxVarcharLength() < maxLobLen ) { registerColumnType( Types.VARCHAR, maxLobLen, "text" ); } - registerColumnType( Types.VARBINARY, maxLongLobLen, "longblob" ); + registerColumnType( Types.NVARCHAR, "longtext" ); + registerColumnType( Types.NVARCHAR, maxMediumLobLen, "mediumtext" ); + if ( getMaxNVarcharLength() < maxLobLen ) { + registerColumnType( Types.NVARCHAR, maxLobLen, "text" ); + } + + registerColumnType( Types.VARBINARY, "longblob" ); registerColumnType( Types.VARBINARY, maxMediumLobLen, "mediumblob" ); - if ( maxVarcharLen < maxLobLen ) { + if ( getMaxVarbinaryLength() < maxLobLen ) { registerColumnType( Types.VARBINARY, maxLobLen, "blob" ); } - registerColumnType( Types.BLOB, maxLongLobLen, "longblob" ); + registerColumnType( Types.BLOB, "longblob" ); registerColumnType( Types.BLOB, maxMediumLobLen, "mediumblob" ); registerColumnType( Types.BLOB, maxLobLen, "blob" ); registerColumnType( Types.BLOB, maxTinyLobLen, "tinyblob" ); - registerColumnType( Types.CLOB, maxLongLobLen, "longtext" ); + registerColumnType( Types.CLOB, "longtext" ); registerColumnType( Types.CLOB, maxMediumLobLen, "mediumtext" ); registerColumnType( Types.CLOB, maxLobLen, "text" ); registerColumnType( Types.CLOB, maxTinyLobLen, "tinytext" ); registerColumnType( Types.NCLOB, "longtext" ); - registerColumnType( Types.NCLOB, maxLongLobLen, "longtext" ); registerColumnType( Types.NCLOB, maxMediumLobLen, "mediumtext" ); registerColumnType( Types.NCLOB, maxLobLen, "text" ); registerColumnType( Types.NCLOB, maxTinyLobLen, "tinytext" ); @@ -253,7 +254,9 @@ public class MySQLDialect extends Dialect { return 4; } - protected int getMaxVarcharLen() { + @Override + public int getMaxVarcharLength() { + // max length for VARCHAR changed in 5.0.3 if ( getMySQLVersion().isBefore( 5 ) ) { return 255; } @@ -272,6 +275,11 @@ public class MySQLDialect extends Dialect { } } + @Override + public int getMaxVarbinaryLength() { + return getMySQLVersion().isBefore( 5 ) ? 255 : 65_535; + } + @Override public String getNullColumnString(String columnType) { // Good job MySQL https://dev.mysql.com/doc/refman/8.0/en/timestamp-initialization.html diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java index e98555c773..cbe5e6720d 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java @@ -199,6 +199,19 @@ public class OracleDialect extends Dialect { ).setArgumentListSignature("(pattern, string[, start])"); } + @Override + public int getMaxVarcharLength() { + //with MAX_STRING_SIZE=EXTENDED, changes to 32_767 + //TODO: provide a way to change this without a custom Dialect + return 4000; + } + + @Override + public int getMaxVarbinaryLength() { + //with MAX_STRING_SIZE=EXTENDED, changes to 32_767 + return 2000; + } + @Override public SqlAstTranslatorFactory getSqlAstTranslatorFactory() { return new StandardSqlAstTranslatorFactory() { @@ -525,16 +538,17 @@ public class OracleDialect extends Dialect { protected void registerCharacterTypeMappings() { if ( getVersion().isBefore( 9 ) ) { - registerColumnType( Types.VARCHAR, 4000, "varchar2($l)" ); + registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "varchar2($l)" ); registerColumnType( Types.VARCHAR, "clob" ); } else { registerColumnType( Types.CHAR, "char($l char)" ); - registerColumnType( Types.VARCHAR, 4000, "varchar2($l char)" ); + registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "varchar2($l char)" ); registerColumnType( Types.VARCHAR, "clob" ); - registerColumnType( Types.NVARCHAR, 4000, "nvarchar2($l)" ); + registerColumnType( Types.NVARCHAR, getMaxNVarcharLength(), "nvarchar2($l)" ); registerColumnType( Types.NVARCHAR, "nclob" ); } + //note: the 'long' type is deprecated } protected void registerNumericTypeMappings() { @@ -576,10 +590,10 @@ public class OracleDialect extends Dialect { } protected void registerBinaryTypeMappings() { - registerColumnType( Types.BINARY, 2000, "raw($l)" ); + registerColumnType( Types.BINARY, getMaxVarbinaryLength(), "raw($l)" ); registerColumnType( Types.BINARY, "blob" ); - registerColumnType( Types.VARBINARY, 2000, "raw($l)" ); + registerColumnType( Types.VARBINARY, getMaxVarbinaryLength(), "raw($l)" ); registerColumnType( Types.VARBINARY, "blob" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java index 86f9823e17..b23f45e479 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -132,13 +132,13 @@ public class PostgreSQLDialect extends Dialect { //there are no nchar/nvarchar types in Postgres registerColumnType( Types.NCHAR, "char($l)" ); - registerColumnType( Types.NVARCHAR, "varchar($l)" ); + registerColumnType( Types.NVARCHAR, getMaxNVarcharLength(), "varchar($l)" ); + registerColumnType( Types.NVARCHAR, "text" ); - //since there's no real difference between - //TEXT and VARCHAR, except for the length limit, - //we can just use 'text' for the "long" types - registerColumnType( Types.LONGVARCHAR, "text" ); - registerColumnType( Types.LONGNVARCHAR, "text" ); + // since there's no real difference between TEXT and VARCHAR, + // except for the length limit, we can just use 'text' for the + // "long" string types + registerColumnType( Types.VARCHAR, "text" ); registerColumnType( SqlTypes.INET, "inet" ); registerColumnType( SqlTypes.INTERVAL_SECOND, "interval second($s)" ); @@ -163,6 +163,17 @@ public class PostgreSQLDialect extends Dialect { getDefaultProperties().setProperty( Environment.NON_CONTEXTUAL_LOB_CREATION, "true" ); } + @Override + public int getMaxVarcharLength() { + return 10_485_760; + } + + @Override + public int getMaxVarbinaryLength() { + //postgres has no varbinary-like type + return 0; + } + @Override public String getTypeName(int code, Size size) throws HibernateException { // The maximum scale for `interval second` is 6 unfortunately so we have to use numeric by default diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java index 182ae50280..a5b74d6c68 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java @@ -66,7 +66,6 @@ import java.util.TimeZone; import jakarta.persistence.TemporalType; -import static java.util.regex.Pattern.compile; import static org.hibernate.query.TemporalUnit.NANOSECOND; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate; import static org.hibernate.type.descriptor.DateTimeUtils.appendAsTime; @@ -113,13 +112,10 @@ public class SQLServerDialect extends AbstractTransactSQLDialect { exporter = new SqlServerSequenceExporter( this ); } - registerColumnType( Types.VARCHAR, 8000, "varchar($l)" ); - registerColumnType( Types.NVARCHAR, 4000, "nvarchar($l)" ); - registerColumnType( Types.VARBINARY, 8000, "varbinary($l)" ); - if ( getVersion().isBefore( 9 ) ) { registerColumnType( Types.VARBINARY, "image" ); registerColumnType( Types.VARCHAR, "text" ); + registerColumnType( Types.NVARCHAR, "text" ); } else { @@ -146,6 +142,16 @@ public class SQLServerDialect extends AbstractTransactSQLDialect { registerKeyword( "key" ); } + @Override + public int getMaxVarcharLength() { + return 8000; + } + + @Override + public int getMaxNVarcharLength() { + return 4000; + } + @Override public DatabaseVersion getVersion() { return version; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java index 70b22e55b9..0e75c5f5a1 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java @@ -92,17 +92,20 @@ public class SpannerDialect extends Dialect { //there is no time type of any kind registerColumnType( Types.TIME, "timestamp" ); - final int stringMaxLength = 2_621_440; - final int bytesMaxLength = 10_485_760; + registerColumnType( Types.CHAR, getMaxVarcharLength(), "string($l)" ); + registerColumnType( Types.CHAR, "string(max)" ); + registerColumnType( Types.VARCHAR, getMaxVarcharLength(), "string($l)" ); + registerColumnType( Types.VARCHAR, "string(max)" ); - registerColumnType( Types.CHAR, stringMaxLength, "string($l)" ); - registerColumnType( Types.VARCHAR, stringMaxLength, "string($l)" ); + registerColumnType( Types.NCHAR, getMaxNVarcharLength(), "string($l)" ); + registerColumnType( Types.NCHAR, "string(max)" ); + registerColumnType( Types.NVARCHAR, getMaxNVarcharLength(), "string($l)" ); + registerColumnType( Types.NVARCHAR, "string(max)" ); - registerColumnType( Types.NCHAR, stringMaxLength, "string($l)" ); - registerColumnType( Types.NVARCHAR, stringMaxLength, "string($l)" ); - - registerColumnType( Types.BINARY, bytesMaxLength, "bytes($l)" ); - registerColumnType( Types.VARBINARY, bytesMaxLength, "bytes($l)" ); + registerColumnType( Types.BINARY, getMaxBytesLength(), "bytes($l)" ); + registerColumnType( Types.BINARY, "bytes(max)" ); + registerColumnType( Types.VARBINARY, getMaxBytesLength(), "bytes($l)" ); + registerColumnType( Types.VARBINARY, "bytes(max)" ); registerColumnType( Types.CLOB, "string(max)" ); registerColumnType( Types.NCLOB, "string(max)" ); @@ -114,6 +117,17 @@ public class SpannerDialect extends Dialect { registerKeywords( info ); } + @Override + public int getMaxVarcharLength() { + //max is equivalent to 2_621_440 + return 2_621_440; + } + + public int getMaxBytesLength() { + //max is equivalent to 10_485_760 + return 10_485_760; + } + @Override public DatabaseVersion getVersion() { return ZERO_VERSION; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java index 7a3e624d7d..e557f9f453 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java @@ -99,12 +99,8 @@ public class SybaseASEDialect extends SybaseDialect { } } - // the maximum length of a VARCHAR or VARBINARY - // depends on the page size, and also on the - // version of Sybase ASE, and can be quite small, - // so use 'image' and 'text' as the "long" types - registerColumnType( Types.LONGVARBINARY, "image" ); - registerColumnType( Types.LONGVARCHAR, "text" ); + registerColumnType( Types.VARBINARY, "image" ); + registerColumnType( Types.VARCHAR, "text" ); registerSybaseKeywords(); sizeStrategy = new SizeStrategyImpl() { @@ -127,6 +123,17 @@ public class SybaseASEDialect extends SybaseDialect { }; } + @Override + public int getMaxVarcharLength() { + // the maximum length of a VARCHAR or VARBINARY + // column depends on the page size and ASE version + // and is actually a limit on the whole row length, + // not the individual column length -- anyway, the + // largest possible page size is 16k, so that's a + // hard upper limit + return 16_384; + } + private static boolean isAnsiNull(DatabaseMetaData databaseMetaData) { if ( databaseMetaData != null ) { try (java.sql.Statement s = databaseMetaData.getConnection().createStatement() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/Size.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/Size.java index 6a90450463..72de119bbb 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/Size.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/Size.java @@ -6,6 +6,8 @@ */ package org.hibernate.engine.jdbc; +import org.hibernate.Length; + import java.io.Serializable; /** @@ -35,9 +37,9 @@ public class Size implements Serializable { } } - public static final long DEFAULT_LENGTH = 255; - public static final long LONG_LENGTH = 65_535; - public static final long DEFAULT_LOB_LENGTH = 1_048_576; + public static final long DEFAULT_LENGTH = Length.DEFAULT; + public static final long LONG_LENGTH = Length.LONG; + public static final long DEFAULT_LOB_LENGTH = Length.LOB_DEFAULT; public static final int DEFAULT_PRECISION = 19; public static final int DEFAULT_SCALE = 2; diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java index e2e3c7d05f..db3897f084 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java @@ -18,7 +18,6 @@ import org.hibernate.boot.model.relational.internal.SqlStringGenerationContextIm import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.mapping.Column; -import org.hibernate.mapping.Selectable; import org.hibernate.mapping.Table; import org.hibernate.resource.transaction.spi.DdlTransactionIsolator; import org.hibernate.tool.schema.extract.spi.ColumnInformation; @@ -48,12 +47,7 @@ public abstract class AbstractSchemaValidator implements SchemaValidator { HibernateSchemaManagementTool tool, SchemaFilter validateFilter) { this.tool = tool; - if ( validateFilter == null ) { - this.schemaFilter = DefaultSchemaFilter.INSTANCE; - } - else { - this.schemaFilter = validateFilter; - } + this.schemaFilter = validateFilter == null ? DefaultSchemaFilter.INSTANCE : validateFilter; } @Override @@ -143,23 +137,20 @@ public abstract class AbstractSchemaValidator implements SchemaValidator { ); } - final Iterator selectableItr = table.getColumnIterator(); - while ( selectableItr.hasNext() ) { - final Selectable selectable = (Selectable) selectableItr.next(); - if ( Column.class.isInstance( selectable ) ) { - final Column column = (Column) selectable; - final ColumnInformation existingColumn = tableInformation.getColumn( Identifier.toIdentifier( column.getQuotedName() ) ); - if ( existingColumn == null ) { - throw new SchemaManagementException( - String.format( - "Schema-validation: missing column [%s] in table [%s]", - column.getName(), - table.getQualifiedTableName() - ) - ); - } - validateColumnType( table, column, existingColumn, metadata, options, dialect ); + final Iterator columnIter = table.getColumnIterator(); + while ( columnIter.hasNext() ) { + final Column column = columnIter.next(); + final ColumnInformation existingColumn = tableInformation.getColumn( Identifier.toIdentifier( column.getQuotedName() ) ); + if ( existingColumn == null ) { + throw new SchemaManagementException( + String.format( + "Schema-validation: missing column [%s] in table [%s]", + column.getName(), + table.getQualifiedTableName() + ) + ); } + validateColumnType( table, column, existingColumn, metadata, options, dialect ); } } @@ -171,7 +162,8 @@ public abstract class AbstractSchemaValidator implements SchemaValidator { ExecutionOptions options, Dialect dialect) { boolean typesMatch = dialect.equivalentTypes( column.getSqlTypeCode( metadata ), columnInformation.getTypeCode() ) - || column.getSqlType( dialect, metadata ).toLowerCase(Locale.ROOT).startsWith( columnInformation.getTypeName().toLowerCase(Locale.ROOT) ); + || column.getSqlType( dialect, metadata ).toLowerCase(Locale.ROOT) + .startsWith( columnInformation.getTypeName().toLowerCase(Locale.ROOT) ); if ( !typesMatch ) { throw new SchemaManagementException( String.format( @@ -186,14 +178,6 @@ public abstract class AbstractSchemaValidator implements SchemaValidator { ) ); } - - // this is the old Hibernate check... - // - // but I think a better check involves checks against type code and then the type code family, not - // just the type name. - // - // See org.hibernate.type.descriptor.sql.JdbcTypeFamilyInformation - // todo : this ^^ } protected void validateSequence(Sequence sequence, SequenceInformation sequenceInformation) { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/length/LengthTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/length/LengthTest.java new file mode 100644 index 0000000000..9b36becf99 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/length/LengthTest.java @@ -0,0 +1,25 @@ +package org.hibernate.orm.test.length; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.junit.Assert.assertEquals; + +@SessionFactory +@DomainModel(annotatedClasses = WithLongStrings.class) +public class LengthTest { + @Test + public void testLength(SessionFactoryScope scope) { + WithLongStrings strings = new WithLongStrings(); + strings.long16 = "hello world ".repeat(2700); + strings.long32 = "hello world ".repeat(20000); + scope.inTransaction(s->s.persist(strings)); + scope.inTransaction(s-> { + WithLongStrings strs = s.find(WithLongStrings.class, strings.id); + assertEquals(strs.long16, strings.long16); + assertEquals(strs.long32, strings.long32); + }); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/length/WithLongStrings.java b/hibernate-core/src/test/java/org/hibernate/orm/test/length/WithLongStrings.java new file mode 100644 index 0000000000..126931752a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/length/WithLongStrings.java @@ -0,0 +1,21 @@ +package org.hibernate.orm.test.length; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +import static org.hibernate.Length.*; + +@Entity +public class WithLongStrings { + @Id + @GeneratedValue + public int id; + + @Column(length = LONG16) + public String long16; + + @Column(length = LONG32) + public String long32; +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/lob/ImageMappings.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/lob/ImageMappings.hbm.xml index 5956bb992f..8bc22aff63 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/lob/ImageMappings.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/lob/ImageMappings.hbm.xml @@ -16,7 +16,7 @@ - + \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedUuidTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedUuidTests.java index a27fc26afd..5a202057f2 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedUuidTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/temporals/GeneratedUuidTests.java @@ -53,7 +53,7 @@ public class GeneratedUuidTests { // then changing final GeneratedUuidEntity merged = scope.fromTransaction( (session) -> { - return (GeneratedUuidEntity) session.merge( created ); + return session.merge( created ); } ); assertThat( merged ).isNotNull(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/schemavalidation/LongVarcharValidationTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/schemavalidation/LongVarcharValidationTest.java index 717d29bf79..61473b217b 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/schemavalidation/LongVarcharValidationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/schemavalidation/LongVarcharValidationTest.java @@ -53,7 +53,8 @@ public class LongVarcharValidationTest implements ExecutionOptions { @Parameterized.Parameters public static Collection parameters() { return Arrays.asList( - new String[] {JdbcMetadaAccessStrategy.GROUPED.toString(), JdbcMetadaAccessStrategy.INDIVIDUALLY.toString()} + JdbcMetadaAccessStrategy.GROUPED.toString(), + JdbcMetadaAccessStrategy.INDIVIDUALLY.toString() ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/schemavalidation/NumericValidationTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/schemavalidation/NumericValidationTest.java index 2c74bbf129..eafdba5421 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/schemavalidation/NumericValidationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/schemavalidation/NumericValidationTest.java @@ -52,10 +52,8 @@ public class NumericValidationTest implements ExecutionOptions { @Parameterized.Parameters public static Collection parameters() { return Arrays.asList( - new String[] { - JdbcMetadaAccessStrategy.GROUPED.toString(), - JdbcMetadaAccessStrategy.INDIVIDUALLY.toString() - } + JdbcMetadaAccessStrategy.GROUPED.toString(), + JdbcMetadaAccessStrategy.INDIVIDUALLY.toString() ); }