From 676784d28149b3ef22032b4f672ddf11e69e346d Mon Sep 17 00:00:00 2001 From: Chris Cranford Date: Fri, 26 Jan 2018 11:43:03 -0500 Subject: [PATCH] HHH-8382 - Fix ordering of lob columns when using HBM mappings. --- .../source/internal/hbm/ModelBinder.java | 50 +++++++++++++++++++ .../test/lob/LobAsLastValueTest.java | 2 +- .../org/hibernate/testing/DialectChecks.java | 2 +- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java index 38e79eaa3e..ae15a9ad61 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ModelBinder.java @@ -6,6 +6,7 @@ */ package org.hibernate.boot.model.source.internal.hbm; +import java.sql.Types; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -140,8 +141,14 @@ import org.hibernate.mapping.UniqueKey; import org.hibernate.mapping.Value; import org.hibernate.tuple.GeneratedValueGeneration; import org.hibernate.tuple.GenerationTiming; +import org.hibernate.type.AbstractSingleColumnStandardBasicType; +import org.hibernate.type.BasicType; +import org.hibernate.type.BlobType; +import org.hibernate.type.ClobType; import org.hibernate.type.DiscriminatorType; import org.hibernate.type.ForeignKeyDirection; +import org.hibernate.type.NClobType; +import org.hibernate.type.TypeResolver; /** * Responsible for coordinating the binding of all information inside entity tags ({@code }, etc). @@ -1913,6 +1920,8 @@ public class ModelBinder { attributeSource.getAttributeRole() ); + resolveLob( attributeSource, value ); + // // this is done here 'cos we might only know the type here (ugly!) // // TODO: improve this a lot: // if ( value instanceof ToOne ) { @@ -1936,6 +1945,7 @@ public class ModelBinder { Property property = new Property(); property.setValue( value ); + property.setLob( value.isLob() ); bindProperty( sourceDocument, attributeSource, @@ -1945,6 +1955,46 @@ public class ModelBinder { return property; } + private void resolveLob(final SingularAttributeSourceBasic attributeSource, SimpleValue value) { + // Resolves whether the property is LOB based on the type attribute on the attribute property source. + // Essentially this expects the type to map to a CLOB/NCLOB/BLOB sql type internally and compares. + if ( !value.isLob() && value.getTypeName() != null ) { + final TypeResolver typeResolver = attributeSource.getBuildingContext().getMetadataCollector().getTypeResolver(); + final BasicType basicType = typeResolver.basic( value.getTypeName() ); + if ( basicType instanceof AbstractSingleColumnStandardBasicType ) { + if ( isLob( ( (AbstractSingleColumnStandardBasicType) basicType ).getSqlTypeDescriptor().getSqlType(), null ) ) { + value.makeLob(); + } + } + } + + // If the prior check didn't set the lob flag, this will inspect the column sql-type attribute value and + // if this maps to CLOB/NCLOB/BLOB then the value will be marked as lob. + if ( !value.isLob() ) { + for ( RelationalValueSource relationalValueSource : attributeSource.getRelationalValueSources() ) { + if ( ColumnSource.class.isInstance( relationalValueSource ) ) { + if ( isLob( null, ( (ColumnSource) relationalValueSource ).getSqlType() ) ) { + value.makeLob(); + } + } + } + } + } + + private static boolean isLob(Integer sqlType, String sqlTypeName) { + if ( sqlType != null ) { + return ClobType.INSTANCE.getSqlTypeDescriptor().getSqlType() == sqlType || + BlobType.INSTANCE.getSqlTypeDescriptor().getSqlType() == sqlType || + NClobType.INSTANCE.getSqlTypeDescriptor().getSqlType() == sqlType; + } + else if ( sqlTypeName != null ) { + return ClobType.INSTANCE.getName().equalsIgnoreCase( sqlTypeName ) || + BlobType.INSTANCE.getName().equalsIgnoreCase( sqlTypeName ) || + NClobType.INSTANCE.getName().equalsIgnoreCase( sqlTypeName ); + } + return false; + } + private Property createOneToOneAttribute( MappingDocument sourceDocument, SingularAttributeSourceOneToOne oneToOneSource, diff --git a/hibernate-core/src/test/java/org/hibernate/test/lob/LobAsLastValueTest.java b/hibernate-core/src/test/java/org/hibernate/test/lob/LobAsLastValueTest.java index b6b855c69c..f320548a8e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/lob/LobAsLastValueTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/lob/LobAsLastValueTest.java @@ -20,7 +20,7 @@ import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; /** * @author Chris Cranford */ -@RequiresDialectFeature(DialectChecks.SupportsForceLobAsLastValue.class) +@RequiresDialectFeature(DialectChecks.ForceLobAsLastValue.class) @TestForIssue(jiraKey = "HHH-8382") public class LobAsLastValueTest extends BaseCoreFunctionalTestCase { @Override diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/DialectChecks.java b/hibernate-testing/src/main/java/org/hibernate/testing/DialectChecks.java index 9b8ed5b8b4..7905e6d8a5 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/DialectChecks.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/DialectChecks.java @@ -236,7 +236,7 @@ abstract public class DialectChecks { } } - public static class SupportsForceLobAsLastValue implements DialectCheck { + public static class ForceLobAsLastValue implements DialectCheck { public boolean isMatch(Dialect dialect) { return dialect.forceLobAsLastValue(); }