HHH-5869 - Add suport for nationalized character mappings

(cherry picked from commit e7b188c924)

Conflicts:

	hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java

Plus, added all nationalized variants of the character-based SqlTypeDescriptors
This commit is contained in:
Steve Ebersole 2013-01-14 17:12:11 -06:00 committed by Brett Meyer
parent 428866f058
commit 5d280a8041
25 changed files with 1065 additions and 75 deletions

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Marks a character data type (String, Character, character, Clob) as being a nationalized variant
* (NVARCHAR, NCHAR, NCLOB, etc).
*
* @author Steve Ebersole
*/
@Target( { METHOD, FIELD } )
@Retention( RUNTIME )
public @interface Nationalized {
}

View File

@ -615,4 +615,6 @@ public interface AvailableSettings {
* Default is to not store direct references. * Default is to not store direct references.
*/ */
public static final String USE_DIRECT_REFERENCE_CACHE_ENTRIES = "hibernate.cache.use_reference_entries"; public static final String USE_DIRECT_REFERENCE_CACHE_ENTRIES = "hibernate.cache.use_reference_entries";
public static final String USE_NATIONALIZED_CHARACTER_DATA = "hibernate.use_nationalized_character_data";
} }

View File

@ -3078,6 +3078,19 @@ public class Configuration implements Serializable {
return useNewGeneratorMappings.booleanValue(); return useNewGeneratorMappings.booleanValue();
} }
private Boolean useNationalizedCharacterData;
@Override
@SuppressWarnings( {"UnnecessaryUnboxing"})
public boolean useNationalizedCharacterData() {
if ( useNationalizedCharacterData == null ) {
final String booleanName = getConfigurationProperties()
.getProperty( AvailableSettings.USE_NATIONALIZED_CHARACTER_DATA );
useNationalizedCharacterData = Boolean.valueOf( booleanName );
}
return useNationalizedCharacterData.booleanValue();
}
private Boolean forceDiscriminatorInSelectsByDefault; private Boolean forceDiscriminatorInSelectsByDefault;
@Override @Override

View File

@ -747,6 +747,14 @@ public interface Mappings {
*/ */
public boolean useNewGeneratorMappings(); public boolean useNewGeneratorMappings();
/**
* Should we use nationalized variants of character data by default? This is controlled by the
* {@link AvailableSettings#USE_NATIONALIZED_CHARACTER_DATA} setting.
*
* @return {@code true} if nationalized character data should be used by default; {@code false} otherwise.
*/
public boolean useNationalizedCharacterData();
/** /**
* Return the property annotated with @ToOne and @Id if any. * Return the property annotated with @ToOne and @Id if any.
* Null otherwise * Null otherwise

View File

@ -38,6 +38,7 @@ import javax.persistence.TemporalType;
import org.hibernate.AnnotationException; import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.annotations.Nationalized;
import org.hibernate.annotations.Parameter; import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Type; import org.hibernate.annotations.Type;
import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XClass;
@ -56,10 +57,14 @@ import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.SimpleValue; import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
import org.hibernate.type.CharacterArrayClobType; import org.hibernate.type.CharacterArrayClobType;
import org.hibernate.type.CharacterArrayNClobType;
import org.hibernate.type.CharacterNCharType;
import org.hibernate.type.EnumType; import org.hibernate.type.EnumType;
import org.hibernate.type.PrimitiveCharacterArrayClobType; import org.hibernate.type.PrimitiveCharacterArrayClobType;
import org.hibernate.type.PrimitiveCharacterArrayNClobType;
import org.hibernate.type.SerializableToBlobType; import org.hibernate.type.SerializableToBlobType;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.StringNVarcharType;
import org.hibernate.type.WrappedMaterializedBlobType; import org.hibernate.type.WrappedMaterializedBlobType;
import org.hibernate.usertype.DynamicParameterizedType; import org.hibernate.usertype.DynamicParameterizedType;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -145,6 +150,9 @@ public class SimpleValueBinder {
this.xproperty = property; this.xproperty = property;
String type = BinderHelper.ANNOTATION_STRING_DEFAULT; String type = BinderHelper.ANNOTATION_STRING_DEFAULT;
final boolean isNationalized = property.isAnnotationPresent( Nationalized.class )
|| mappings.useNationalizedCharacterData();
Type annType = property.getAnnotation( Type.class ); Type annType = property.getAnnotation( Type.class );
if ( annType != null ) { if ( annType != null ) {
setExplicitType( annType ); setExplicitType( annType );
@ -191,19 +199,30 @@ public class SimpleValueBinder {
else if ( property.isAnnotationPresent( Lob.class ) ) { else if ( property.isAnnotationPresent( Lob.class ) ) {
if ( mappings.getReflectionManager().equals( returnedClassOrElement, java.sql.Clob.class ) ) { if ( mappings.getReflectionManager().equals( returnedClassOrElement, java.sql.Clob.class ) ) {
type = "clob"; type = isNationalized
? StandardBasicTypes.NCLOB.getName()
: StandardBasicTypes.CLOB.getName();
}
else if ( mappings.getReflectionManager().equals( returnedClassOrElement, java.sql.NClob.class ) ) {
type = StandardBasicTypes.NCLOB.getName();
} }
else if ( mappings.getReflectionManager().equals( returnedClassOrElement, java.sql.Blob.class ) ) { else if ( mappings.getReflectionManager().equals( returnedClassOrElement, java.sql.Blob.class ) ) {
type = "blob"; type = "blob";
} }
else if ( mappings.getReflectionManager().equals( returnedClassOrElement, String.class ) ) { else if ( mappings.getReflectionManager().equals( returnedClassOrElement, String.class ) ) {
type = StandardBasicTypes.MATERIALIZED_CLOB.getName(); type = isNationalized
? StandardBasicTypes.MATERIALIZED_NCLOB.getName()
: StandardBasicTypes.MATERIALIZED_CLOB.getName();
} }
else if ( mappings.getReflectionManager().equals( returnedClassOrElement, Character.class ) && isArray ) { else if ( mappings.getReflectionManager().equals( returnedClassOrElement, Character.class ) && isArray ) {
type = CharacterArrayClobType.class.getName(); type = isNationalized
? CharacterArrayNClobType.class.getName()
: CharacterArrayClobType.class.getName();
} }
else if ( mappings.getReflectionManager().equals( returnedClassOrElement, char.class ) && isArray ) { else if ( mappings.getReflectionManager().equals( returnedClassOrElement, char.class ) && isArray ) {
type = PrimitiveCharacterArrayClobType.class.getName(); type = isNationalized
? PrimitiveCharacterArrayNClobType.class.getName()
: PrimitiveCharacterArrayClobType.class.getName();
} }
else if ( mappings.getReflectionManager().equals( returnedClassOrElement, Byte.class ) && isArray ) { else if ( mappings.getReflectionManager().equals( returnedClassOrElement, Byte.class ) && isArray ) {
type = WrappedMaterializedBlobType.class.getName(); type = WrappedMaterializedBlobType.class.getName();
@ -237,6 +256,24 @@ public class SimpleValueBinder {
type = EnumType.class.getName(); type = EnumType.class.getName();
explicitType = type; explicitType = type;
} }
else if ( isNationalized ) {
if ( mappings.getReflectionManager().equals( returnedClassOrElement, String.class ) ) {
// nvarchar
type = StringNVarcharType.INSTANCE.getName();
explicitType = type;
}
else if ( mappings.getReflectionManager().equals( returnedClassOrElement, Character.class ) ) {
if ( isArray ) {
// nvarchar
type = StringNVarcharType.INSTANCE.getName();
}
else {
// nchar
type = CharacterNCharType.INSTANCE.getName();
}
explicitType = type;
}
}
// implicit type will check basic types and Serializable classes // implicit type will check basic types and Serializable classes
if ( columns == null ) { if ( columns == null ) {

View File

@ -2385,49 +2385,4 @@ public abstract class Dialect implements ConversionContext {
public String getNotExpression( String expression ) { public String getNotExpression( String expression ) {
return "not " + expression; return "not " + expression;
} }
/**
* Does this dialect support the <tt>UNIQUE</tt> column syntax?
*
* @return boolean
*
* @deprecated {@link #getUniqueDelegate()} should be overridden instead.
*/
@Deprecated
public boolean supportsUnique() {
return true;
}
/**
* Does this dialect support adding Unique constraints via create and alter table ?
*
* @return boolean
*
* @deprecated {@link #getUniqueDelegate()} should be overridden instead.
*/
@Deprecated
public boolean supportsUniqueConstraintInCreateAlterTable() {
return true;
}
/**
* The syntax used to add a unique constraint to a table.
*
* @param constraintName The name of the unique constraint.
* @return The "add unique" fragment
*
* @deprecated {@link #getUniqueDelegate()} should be overridden instead.
*/
@Deprecated
public String getAddUniqueConstraintString(String constraintName) {
return " add constraint " + constraintName + " unique ";
}
/**
* @deprecated {@link #getUniqueDelegate()} should be overridden instead.
*/
@Deprecated
public boolean supportsNotNullUnique() {
return true;
}
} }

View File

@ -24,6 +24,7 @@
package org.hibernate.engine.jdbc; package org.hibernate.engine.jdbc;
import java.sql.Blob; import java.sql.Blob;
import java.sql.Clob; import java.sql.Clob;
import java.sql.NClob;
/** /**
* Convenient base class for proxy-based LobCreator for handling wrapping. * Convenient base class for proxy-based LobCreator for handling wrapping.
@ -38,11 +39,16 @@ public abstract class AbstractLobCreator implements LobCreator {
@Override @Override
public Clob wrap(Clob clob) { public Clob wrap(Clob clob) {
if ( SerializableNClobProxy.isNClob( clob ) ) { if ( NClob.class.isInstance( clob ) ) {
return SerializableNClobProxy.generateProxy( clob ); return wrap( (NClob) clob );
} }
else { else {
return SerializableClobProxy.generateProxy( clob ); return SerializableClobProxy.generateProxy( clob );
} }
} }
@Override
public NClob wrap(NClob nclob) {
return SerializableNClobProxy.generateProxy( nclob );
}
} }

View File

@ -51,6 +51,14 @@ public interface LobCreator {
*/ */
public Clob wrap(Clob clob); public Clob wrap(Clob clob);
/**
* Wrap the given nclob in a serializable wrapper.
*
* @param nclob The nclob to be wrapped.
* @return The wrapped nclob which will be castable to {@link NClob} as well as {@link WrappedNClob}.
*/
public NClob wrap(NClob nclob);
/** /**
* Create a BLOB reference encapsulating the given byte array. * Create a BLOB reference encapsulating the given byte array.
* *

View File

@ -25,6 +25,7 @@ package org.hibernate.engine.jdbc;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.sql.Clob; import java.sql.Clob;
import java.sql.NClob;
/** /**
* Manages aspects of proxying java.sql.NClobs to add serializability. * Manages aspects of proxying java.sql.NClobs to add serializability.
@ -32,27 +33,10 @@ import java.sql.Clob;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SerializableNClobProxy extends SerializableClobProxy { public class SerializableNClobProxy extends SerializableClobProxy {
private static final Class NCLOB_CLASS = loadNClobClassIfAvailable(); private static final Class[] PROXY_INTERFACES = new Class[] { NClob.class, WrappedNClob.class };
private static Class loadNClobClassIfAvailable() {
try {
return getProxyClassLoader().loadClass( "java.sql.NClob" );
}
catch ( ClassNotFoundException e ) {
return null;
}
}
private static final Class[] PROXY_INTERFACES = new Class[] { determineNClobInterface(), WrappedClob.class };
private static Class determineNClobInterface() {
// java.sql.NClob is a simple marker interface extending java.sql.Clob. So if java.sql.NClob is not available
// on the classloader, just use java.sql.Clob
return NCLOB_CLASS == null ? Clob.class : NCLOB_CLASS;
}
public static boolean isNClob(Clob clob) { public static boolean isNClob(Clob clob) {
return NCLOB_CLASS != null && NCLOB_CLASS.isInstance( clob ); return NClob.class.isInstance( clob );
} }
/** /**
@ -67,16 +51,16 @@ public class SerializableNClobProxy extends SerializableClobProxy {
} }
/** /**
* Generates a SerializableClobProxy proxy wrapping the provided Clob object. * Generates a SerializableNClobProxy proxy wrapping the provided NClob object.
* *
* @param clob The Clob to wrap. * @param nclob The NClob to wrap.
* @return The generated proxy. * @return The generated proxy.
*/ */
public static Clob generateProxy(Clob clob) { public static NClob generateProxy(NClob nclob) {
return ( Clob ) Proxy.newProxyInstance( return ( NClob ) Proxy.newProxyInstance(
getProxyClassLoader(), getProxyClassLoader(),
PROXY_INTERFACES, PROXY_INTERFACES,
new SerializableNClobProxy( clob ) new SerializableNClobProxy( nclob )
); );
} }

View File

@ -0,0 +1,37 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc;
import java.sql.NClob;
/**
* @author Steve Ebersole
*/
public interface WrappedNClob extends WrappedClob {
@Override
@Deprecated
public NClob getWrappedClob();
public NClob getWrappedNClob();
}

View File

@ -64,6 +64,8 @@ public class BasicTypeRegistry implements Serializable {
register( BigIntegerType.INSTANCE ); register( BigIntegerType.INSTANCE );
register( StringType.INSTANCE ); register( StringType.INSTANCE );
register( StringNVarcharType.INSTANCE );
register( CharacterNCharType.INSTANCE );
register( UrlType.INSTANCE ); register( UrlType.INSTANCE );
register( DateType.INSTANCE ); register( DateType.INSTANCE );
@ -87,10 +89,13 @@ public class BasicTypeRegistry implements Serializable {
register( CharArrayType.INSTANCE ); register( CharArrayType.INSTANCE );
register( CharacterArrayType.INSTANCE ); register( CharacterArrayType.INSTANCE );
register( TextType.INSTANCE ); register( TextType.INSTANCE );
register( NTextType.INSTANCE );
register( BlobType.INSTANCE ); register( BlobType.INSTANCE );
register( MaterializedBlobType.INSTANCE ); register( MaterializedBlobType.INSTANCE );
register( ClobType.INSTANCE ); register( ClobType.INSTANCE );
register( NClobType.INSTANCE );
register( MaterializedClobType.INSTANCE ); register( MaterializedClobType.INSTANCE );
register( MaterializedNClobType.INSTANCE );
register( SerializableType.INSTANCE ); register( SerializableType.INSTANCE );
register( ObjectType.INSTANCE ); register( ObjectType.INSTANCE );

View File

@ -0,0 +1,49 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import org.hibernate.type.descriptor.java.CharacterArrayTypeDescriptor;
import org.hibernate.type.descriptor.sql.NClobTypeDescriptor;
/**
* A type that maps between {@link java.sql.Types#NCLOB NCLOB} and {@link Character Character[]}
* <p/>
* Essentially a {@link org.hibernate.type.MaterializedNClobType} but represented as a Character[] in Java rather than String.
*
* @author Emmanuel Bernard
* @author Steve Ebersole
*/
public class CharacterArrayNClobType extends AbstractSingleColumnStandardBasicType<Character[]> {
public static final CharacterArrayNClobType INSTANCE = new CharacterArrayNClobType();
public CharacterArrayNClobType() {
super( NClobTypeDescriptor.DEFAULT, CharacterArrayTypeDescriptor.INSTANCE );
}
public String getName() {
// todo name these annotation types for addition to the registry
return null;
}
}

View File

@ -0,0 +1,68 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import java.io.Serializable;
import org.hibernate.dialect.Dialect;
import org.hibernate.type.descriptor.java.CharacterTypeDescriptor;
import org.hibernate.type.descriptor.sql.NCharTypeDescriptor;
/**
* A type that maps between {@link java.sql.Types#NCHAR NCHAR(1)} and {@link Character}
*
* @author Gavin King
* @author Steve Ebersole
*/
public class CharacterNCharType
extends AbstractSingleColumnStandardBasicType<Character>
implements PrimitiveType<Character>, DiscriminatorType<Character> {
public static final CharacterNCharType INSTANCE = new CharacterNCharType();
public CharacterNCharType() {
super( NCharTypeDescriptor.INSTANCE, CharacterTypeDescriptor.INSTANCE );
}
public String getName() {
return "ncharacter";
}
public Serializable getDefaultValue() {
throw new UnsupportedOperationException( "not a valid id type" );
}
public Class getPrimitiveClass() {
return char.class;
}
public String objectToSQLString(Character value, Dialect dialect) {
return '\'' + toString( value ) + '\'';
}
public Character stringToObject(String xml) {
return fromString( xml );
}
}

View File

@ -0,0 +1,46 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import org.hibernate.type.descriptor.java.StringTypeDescriptor;
import org.hibernate.type.descriptor.sql.NClobTypeDescriptor;
/**
* A type that maps between {@link java.sql.Types#CLOB CLOB} and {@link String}
*
* @author Gavin King
* @author Gail Badner
* @author Steve Ebersole
*/
public class MaterializedNClobType extends AbstractSingleColumnStandardBasicType<String> {
public static final MaterializedNClobType INSTANCE = new MaterializedNClobType();
public MaterializedNClobType() {
super( NClobTypeDescriptor.DEFAULT, StringTypeDescriptor.INSTANCE );
}
public String getName() {
return "materialized_nclob";
}
}

View File

@ -0,0 +1,58 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import java.sql.NClob;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.type.descriptor.java.NClobTypeDescriptor;
/**
* A type that maps between {@link java.sql.Types#CLOB CLOB} and {@link java.sql.Clob}
*
* @author Gavin King
* @author Steve Ebersole
*/
public class NClobType extends AbstractSingleColumnStandardBasicType<NClob> {
public static final NClobType INSTANCE = new NClobType();
public NClobType() {
super( org.hibernate.type.descriptor.sql.NClobTypeDescriptor.DEFAULT, NClobTypeDescriptor.INSTANCE );
}
public String getName() {
return "nclob";
}
@Override
protected boolean registerUnderJavaType() {
return true;
}
@Override
protected NClob getReplacement(NClob original, NClob target, SessionImplementor session) {
return session.getFactory().getDialect().getLobMergeStrategy().mergeNClob( original, target, session );
}
}

View File

@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import org.hibernate.type.descriptor.java.StringTypeDescriptor;
import org.hibernate.type.descriptor.sql.LongNVarcharTypeDescriptor;
/**
* A type that maps between {@link java.sql.Types#LONGNVARCHAR LONGNVARCHAR} and {@link String}
*
* @author Gavin King,
* @author Bertrand Renuart
* @author Steve Ebersole
*/
public class NTextType extends AbstractSingleColumnStandardBasicType<String> {
public static final NTextType INSTANCE = new NTextType();
public NTextType() {
super( LongNVarcharTypeDescriptor.INSTANCE, StringTypeDescriptor.INSTANCE );
}
public String getName() {
return "ntext";
}
}

View File

@ -0,0 +1,45 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import org.hibernate.type.descriptor.java.PrimitiveCharacterArrayTypeDescriptor;
import org.hibernate.type.descriptor.sql.NClobTypeDescriptor;
/**
* Map a char[] to a NClob
*
* @author Emmanuel Bernard
*/
public class PrimitiveCharacterArrayNClobType extends AbstractSingleColumnStandardBasicType<char[]> {
public static final CharacterArrayClobType INSTANCE = new CharacterArrayClobType();
public PrimitiveCharacterArrayNClobType() {
super( NClobTypeDescriptor.DEFAULT, PrimitiveCharacterArrayTypeDescriptor.INSTANCE );
}
public String getName() {
// todo name these annotation types for addition to the registry
return null;
}
}

View File

@ -294,6 +294,15 @@ public class StandardBasicTypes {
*/ */
public static final TextType TEXT = TextType.INSTANCE; public static final TextType TEXT = TextType.INSTANCE;
/**
* The standard Hibernate type for mapping {@link String} to JDBC {@link java.sql.Types#LONGNVARCHAR LONGNVARCHAR}.
* <p/>
* Similar to a {@link #MATERIALIZED_NCLOB}
*
* @see NTextType
*/
public static final NTextType NTEXT = NTextType.INSTANCE;
/** /**
* The standard Hibernate type for mapping {@link java.sql.Clob} to JDBC {@link java.sql.Types#CLOB CLOB}. * The standard Hibernate type for mapping {@link java.sql.Clob} to JDBC {@link java.sql.Types#CLOB CLOB}.
* *
@ -302,6 +311,14 @@ public class StandardBasicTypes {
*/ */
public static final ClobType CLOB = ClobType.INSTANCE; public static final ClobType CLOB = ClobType.INSTANCE;
/**
* The standard Hibernate type for mapping {@link java.sql.NClob} to JDBC {@link java.sql.Types#NCLOB NCLOB}.
*
* @see NClobType
* @see #MATERIALIZED_NCLOB
*/
public static final NClobType NCLOB = NClobType.INSTANCE;
/** /**
* The standard Hibernate type for mapping {@link String} to JDBC {@link java.sql.Types#CLOB CLOB}. * The standard Hibernate type for mapping {@link String} to JDBC {@link java.sql.Types#CLOB CLOB}.
* *
@ -311,6 +328,15 @@ public class StandardBasicTypes {
*/ */
public static final MaterializedClobType MATERIALIZED_CLOB = MaterializedClobType.INSTANCE; public static final MaterializedClobType MATERIALIZED_CLOB = MaterializedClobType.INSTANCE;
/**
* The standard Hibernate type for mapping {@link String} to JDBC {@link java.sql.Types#NCLOB NCLOB}.
*
* @see MaterializedNClobType
* @see #MATERIALIZED_CLOB
* @see #NTEXT
*/
public static final MaterializedNClobType MATERIALIZED_NCLOB = MaterializedNClobType.INSTANCE;
/** /**
* The standard Hibernate type for mapping {@link java.io.Serializable} to JDBC {@link java.sql.Types#VARBINARY VARBINARY}. * The standard Hibernate type for mapping {@link java.io.Serializable} to JDBC {@link java.sql.Types#VARBINARY VARBINARY}.
* <p/> * <p/>

View File

@ -0,0 +1,66 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type;
import org.hibernate.dialect.Dialect;
import org.hibernate.type.descriptor.java.StringTypeDescriptor;
import org.hibernate.type.descriptor.sql.NVarcharTypeDescriptor;
/**
* A type that maps between {@link java.sql.Types#VARCHAR VARCHAR} and {@link String}
*
* @author Gavin King
* @author Steve Ebersole
*/
public class StringNVarcharType
extends AbstractSingleColumnStandardBasicType<String>
implements DiscriminatorType<String> {
public static final StringNVarcharType INSTANCE = new StringNVarcharType();
public StringNVarcharType() {
super( NVarcharTypeDescriptor.INSTANCE, StringTypeDescriptor.INSTANCE );
}
public String getName() {
return "nstring";
}
@Override
protected boolean registerUnderJavaType() {
return false;
}
public String objectToSQLString(String value, Dialect dialect) throws Exception {
return '\'' + value + '\'';
}
public String stringToObject(String xml) throws Exception {
return xml;
}
public String toString(String value) {
return value;
}
}

View File

@ -0,0 +1,134 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type.descriptor.java;
import java.io.Serializable;
import java.sql.NClob;
import java.util.Comparator;
import org.hibernate.engine.jdbc.CharacterStream;
import org.hibernate.engine.jdbc.NClobImplementer;
import org.hibernate.engine.jdbc.NClobProxy;
import org.hibernate.engine.jdbc.WrappedNClob;
import org.hibernate.engine.jdbc.internal.CharacterStreamImpl;
import org.hibernate.type.descriptor.WrapperOptions;
/**
* Descriptor for {@link java.sql.NClob} handling.
* <p/>
* Note, {@link java.sql.NClob nclobs} really are mutable (their internal state can in fact be mutated). We simply
* treat them as immutable because we cannot properly check them for changes nor deep copy them.
*
* @author Steve Ebersole
*/
public class NClobTypeDescriptor extends AbstractTypeDescriptor<NClob> {
public static final NClobTypeDescriptor INSTANCE = new NClobTypeDescriptor();
public static class NClobMutabilityPlan implements MutabilityPlan<NClob> {
public static final NClobMutabilityPlan INSTANCE = new NClobMutabilityPlan();
public boolean isMutable() {
return false;
}
public NClob deepCopy(NClob value) {
return value;
}
public Serializable disassemble(NClob value) {
throw new UnsupportedOperationException( "Clobs are not cacheable" );
}
public NClob assemble(Serializable cached) {
throw new UnsupportedOperationException( "Clobs are not cacheable" );
}
}
public NClobTypeDescriptor() {
super( NClob.class, NClobMutabilityPlan.INSTANCE );
}
public String toString(NClob value) {
return DataHelper.extractString( value );
}
public NClob fromString(String string) {
return NClobProxy.generateProxy( string );
}
@Override
@SuppressWarnings({ "unchecked" })
public Comparator<NClob> getComparator() {
return IncomparableComparator.INSTANCE;
}
@Override
public int extractHashCode(NClob value) {
return System.identityHashCode( value );
}
@Override
public boolean areEqual(NClob one, NClob another) {
return one == another;
}
@SuppressWarnings({ "unchecked" })
public <X> X unwrap(final NClob value, Class<X> type, WrapperOptions options) {
if ( ! ( NClob.class.isAssignableFrom( type ) || CharacterStream.class.isAssignableFrom( type ) ) ) {
throw unknownUnwrap( type );
}
if ( value == null ) {
return null;
}
if ( CharacterStream.class.isAssignableFrom( type ) ) {
if ( NClobImplementer.class.isInstance( value ) ) {
// if the incoming Clob is a wrapper, just pass along its CharacterStream
return (X) ( (NClobImplementer) value ).getUnderlyingStream();
}
else {
// otherwise we need to build one...
return (X) new CharacterStreamImpl( DataHelper.extractString( value ) );
}
}
final NClob clob = WrappedNClob.class.isInstance( value )
? ( (WrappedNClob) value ).getWrappedNClob()
: value;
return (X) clob;
}
public <X> NClob wrap(X value, WrapperOptions options) {
if ( value == null ) {
return null;
}
if ( ! NClob.class.isAssignableFrom( value.getClass() ) ) {
throw unknownWrap( value.getClass() );
}
return options.getLobCreator().wrap( (NClob) value );
}
}

View File

@ -0,0 +1,40 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type.descriptor.sql;
import java.sql.Types;
/**
* Descriptor for {@link Types#LONGNVARCHAR LONGNVARCHAR} handling.
*
* @author Steve Ebersole
*/
public class LongNVarcharTypeDescriptor extends NVarcharTypeDescriptor {
public static final LongVarcharTypeDescriptor INSTANCE = new LongVarcharTypeDescriptor();
@Override
public int getSqlType() {
return Types.LONGNVARCHAR;
}
}

View File

@ -0,0 +1,38 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type.descriptor.sql;
import java.sql.Types;
/**
* @author Steve Ebersole
*/
public class NCharTypeDescriptor extends NVarcharTypeDescriptor {
public static final NCharTypeDescriptor INSTANCE = new NCharTypeDescriptor();
@Override
public int getSqlType() {
return Types.NCHAR;
}
}

View File

@ -0,0 +1,113 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type.descriptor.sql;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.engine.jdbc.CharacterStream;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* Descriptor for {@link Types#NCLOB NCLOB} handling.
*
* @author Steve Ebersole
* @author Gail Badner
*/
public abstract class NClobTypeDescriptor implements SqlTypeDescriptor {
public static final NClobTypeDescriptor DEFAULT =
new NClobTypeDescriptor() {
public <X> BasicBinder<X> getNClobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
if ( options.useStreamForLobBinding() ) {
STREAM_BINDING.getNClobBinder( javaTypeDescriptor ).doBind( st, value, index, options );
}
else {
CLOB_BINDING.getNClobBinder( javaTypeDescriptor ).doBind( st, value, index, options );
}
}
};
}
};
public static final NClobTypeDescriptor CLOB_BINDING =
new NClobTypeDescriptor() {
public <X> BasicBinder<X> getNClobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
st.setNClob( index, javaTypeDescriptor.unwrap( value, NClob.class, options ) );
}
};
}
};
public static final NClobTypeDescriptor STREAM_BINDING =
new NClobTypeDescriptor() {
public <X> BasicBinder<X> getNClobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
final CharacterStream characterStream = javaTypeDescriptor.unwrap( value, CharacterStream.class, options );
st.setCharacterStream( index, characterStream.asReader(), characterStream.getLength() );
}
};
}
};
protected abstract <X> BasicBinder<X> getNClobBinder(final JavaTypeDescriptor<X> javaTypeDescriptor);
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return getNClobBinder( javaTypeDescriptor );
}
public int getSqlType() {
return Types.CLOB;
}
@Override
public boolean canBeRemapped() {
return true;
}
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
@Override
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
return javaTypeDescriptor.wrap( rs.getNClob( name ), options );
}
};
}
}

View File

@ -0,0 +1,73 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.type.descriptor.sql;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* Descriptor for {@link Types#NVARCHAR NVARCHAR} handling.
*
* @author Steve Ebersole
*/
public class NVarcharTypeDescriptor implements SqlTypeDescriptor {
public static final NVarcharTypeDescriptor INSTANCE = new NVarcharTypeDescriptor();
@Override
public int getSqlType() {
return Types.NVARCHAR;
}
@Override
public boolean canBeRemapped() {
return true;
}
@Override
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
st.setNString( index, javaTypeDescriptor.unwrap( value, String.class, options ) );
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
@Override
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
return javaTypeDescriptor.wrap( rs.getNString( name ), options );
}
};
}
}

View File

@ -0,0 +1,90 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.test.nationalized;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import java.sql.NClob;
import org.hibernate.annotations.Nationalized;
import org.hibernate.cfg.Configuration;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.type.MaterializedNClobType;
import org.hibernate.type.NClobType;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.StringNVarcharType;
import org.junit.Test;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
/**
* @author Steve Ebersole
*/
public class SimpleNationalizedTest extends BaseUnitTestCase {
@Entity( name="NationalizedEntity")
public static class NationalizedEntity {
@Id
private Integer id;
@Nationalized
private String nvarcharAtt;
@Lob
@Nationalized
private String materializedNclobAtt;
@Lob
@Nationalized
private NClob nclobAtt;
}
@Test
public void simpleNationalizedTest() {
Configuration cfg = new Configuration();
cfg.addAnnotatedClass( NationalizedEntity.class );
cfg.buildMappings();
PersistentClass pc = cfg.getClassMapping( NationalizedEntity.class.getName() );
assertNotNull( pc );
{
Property prop = pc.getProperty( "nvarcharAtt" );
assertSame( StringNVarcharType.INSTANCE, prop.getType() );
}
{
Property prop = pc.getProperty( "materializedNclobAtt" );
assertSame( MaterializedNClobType.INSTANCE, prop.getType() );
}
{
Property prop = pc.getProperty( "nclobAtt" );
assertSame( NClobType.INSTANCE, prop.getType() );
}
}
}