HHH-8382 - Fix ordering of lob columns when using HBM mappings.

(cherry picked from commit 676784d)
This commit is contained in:
Chris Cranford 2018-01-26 11:43:03 -05:00
parent 36d46b7f61
commit 8b4b9aa2f0
3 changed files with 52 additions and 2 deletions

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.boot.model.source.internal.hbm; package org.hibernate.boot.model.source.internal.hbm;
import java.sql.Types;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -140,8 +141,14 @@ import org.hibernate.mapping.UniqueKey;
import org.hibernate.mapping.Value; import org.hibernate.mapping.Value;
import org.hibernate.tuple.GeneratedValueGeneration; import org.hibernate.tuple.GeneratedValueGeneration;
import org.hibernate.tuple.GenerationTiming; 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.DiscriminatorType;
import org.hibernate.type.ForeignKeyDirection; 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 <class/>}, etc). * Responsible for coordinating the binding of all information inside entity tags ({@code <class/>}, etc).
@ -1913,6 +1920,8 @@ public class ModelBinder {
attributeSource.getAttributeRole() attributeSource.getAttributeRole()
); );
resolveLob( attributeSource, value );
// // this is done here 'cos we might only know the type here (ugly!) // // this is done here 'cos we might only know the type here (ugly!)
// // TODO: improve this a lot: // // TODO: improve this a lot:
// if ( value instanceof ToOne ) { // if ( value instanceof ToOne ) {
@ -1936,6 +1945,7 @@ public class ModelBinder {
Property property = new Property(); Property property = new Property();
property.setValue( value ); property.setValue( value );
property.setLob( value.isLob() );
bindProperty( bindProperty(
sourceDocument, sourceDocument,
attributeSource, attributeSource,
@ -1945,6 +1955,46 @@ public class ModelBinder {
return property; 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( private Property createOneToOneAttribute(
MappingDocument sourceDocument, MappingDocument sourceDocument,
SingularAttributeSourceOneToOne oneToOneSource, SingularAttributeSourceOneToOne oneToOneSource,

View File

@ -20,7 +20,7 @@ import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
/** /**
* @author Chris Cranford * @author Chris Cranford
*/ */
@RequiresDialectFeature(DialectChecks.SupportsForceLobAsLastValue.class) @RequiresDialectFeature(DialectChecks.ForceLobAsLastValue.class)
@TestForIssue(jiraKey = "HHH-8382") @TestForIssue(jiraKey = "HHH-8382")
public class LobAsLastValueTest extends BaseCoreFunctionalTestCase { public class LobAsLastValueTest extends BaseCoreFunctionalTestCase {
@Override @Override

View File

@ -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) { public boolean isMatch(Dialect dialect) {
return dialect.forceLobAsLastValue(); return dialect.forceLobAsLastValue();
} }