HHH-5869 - Add suport for nationalized character mappings

This commit is contained in:
Steve Ebersole 2013-01-14 17:12:11 -06:00
parent 8e38db5833
commit e7b188c924
20 changed files with 801 additions and 30 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

@ -592,4 +592,6 @@ public interface AvailableSettings {
* 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_NATIONALIZED_CHARACTER_DATA = "hibernate.use_nationalized_character_data";
}

View File

@ -3144,6 +3144,19 @@ public class Configuration implements Serializable {
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;
@Override

View File

@ -765,6 +765,14 @@ public interface Mappings {
*/
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.
* Null otherwise

View File

@ -43,6 +43,7 @@ import javax.persistence.TemporalType;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.MappingException;
import org.hibernate.annotations.Nationalized;
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.common.reflection.XClass;
@ -62,10 +63,14 @@ import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.type.CharacterArrayClobType;
import org.hibernate.type.CharacterArrayNClobType;
import org.hibernate.type.CharacterNCharType;
import org.hibernate.type.EnumType;
import org.hibernate.type.PrimitiveCharacterArrayClobType;
import org.hibernate.type.PrimitiveCharacterArrayNClobType;
import org.hibernate.type.SerializableToBlobType;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.StringNVarcharType;
import org.hibernate.type.WrappedMaterializedBlobType;
import org.hibernate.usertype.DynamicParameterizedType;
import org.jboss.logging.Logger;
@ -155,6 +160,9 @@ public class SimpleValueBinder {
typeParameters.clear();
String type = BinderHelper.ANNOTATION_STRING_DEFAULT;
final boolean isNationalized = property.isAnnotationPresent( Nationalized.class )
|| mappings.useNationalizedCharacterData();
Type annType = property.getAnnotation( Type.class );
if ( annType != null ) {
setExplicitType( annType );
@ -200,19 +208,30 @@ public class SimpleValueBinder {
}
else if ( property.isAnnotationPresent( Lob.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 ) ) {
type = "blob";
}
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 ) {
type = CharacterArrayClobType.class.getName();
type = isNationalized
? CharacterArrayNClobType.class.getName()
: CharacterArrayClobType.class.getName();
}
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 ) {
type = WrappedMaterializedBlobType.class.getName();
@ -250,6 +269,24 @@ public class SimpleValueBinder {
type = EnumType.class.getName();
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
if ( columns == null ) {

View File

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

View File

@ -25,6 +25,7 @@ package org.hibernate.engine.jdbc;
import java.lang.reflect.Proxy;
import java.sql.Clob;
import java.sql.NClob;
/**
* Manages aspects of proxying java.sql.NClobs to add serializability.
@ -32,27 +33,10 @@ import java.sql.Clob;
* @author Steve Ebersole
*/
public class SerializableNClobProxy extends SerializableClobProxy {
private static final Class NCLOB_CLASS = loadNClobClassIfAvailable();
private static Class loadNClobClassIfAvailable() {
try {
return getProxyClassLoader().loadClass( "java.sql.NClob" );
}
catch ( ClassNotFoundException e ) {
return null;
}
}
private static final Class[] PROXY_INTERFACES = new Class[] { determineNClobInterface(), WrappedClob.class };
private static Class determineNClobInterface() {
// java.sql.NClob is a simple marker interface extending java.sql.Clob. So if java.sql.NClob is not available
// on the classloader, just use java.sql.Clob
return NCLOB_CLASS == null ? Clob.class : NCLOB_CLASS;
}
private static final Class[] PROXY_INTERFACES = new Class[] { NClob.class, WrappedNClob.class };
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.
*/
public static Clob generateProxy(Clob clob) {
return ( Clob ) Proxy.newProxyInstance(
public static NClob generateProxy(NClob nclob) {
return ( NClob ) Proxy.newProxyInstance(
getProxyClassLoader(),
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( StringType.INSTANCE );
register( StringNVarcharType.INSTANCE );
register( CharacterNCharType.INSTANCE );
register( UrlType.INSTANCE );
register( DateType.INSTANCE );
@ -87,10 +89,13 @@ public class BasicTypeRegistry implements Serializable {
register( CharArrayType.INSTANCE );
register( CharacterArrayType.INSTANCE );
register( TextType.INSTANCE );
register( NTextType.INSTANCE );
register( BlobType.INSTANCE );
register( MaterializedBlobType.INSTANCE );
register( ClobType.INSTANCE );
register( NClobType.INSTANCE );
register( MaterializedClobType.INSTANCE );
register( MaterializedNClobType.INSTANCE );
register( SerializableType.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;
/**
* 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}.
*
@ -302,6 +311,14 @@ public class StandardBasicTypes {
*/
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}.
*
@ -311,6 +328,15 @@ public class StandardBasicTypes {
*/
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}.
* <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,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() );
}
}
}