Fix issue with hql and where clause with Embeddable is null
This commit is contained in:
parent
efb07506f2
commit
6cfbed73ba
|
@ -33,7 +33,7 @@ public class PojoInstantiatorImpl<J> extends AbstractPojoInstantiator {
|
|||
: resolveConstructor( getMappedPojoClass() );
|
||||
}
|
||||
|
||||
private static Constructor resolveConstructor(Class mappedPojoClass) {
|
||||
protected static Constructor resolveConstructor(Class mappedPojoClass) {
|
||||
try {
|
||||
//noinspection unchecked
|
||||
return ReflectHelper.getDefaultConstructor( mappedPojoClass);
|
||||
|
|
|
@ -12,7 +12,9 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
import org.hibernate.bytecode.spi.ReflectionOptimizer;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.mapping.Backref;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.IndexBackref;
|
||||
|
@ -47,6 +49,7 @@ public class StandardPojoEmbeddableRepresentationStrategy extends AbstractEmbedd
|
|||
creationContext
|
||||
);
|
||||
|
||||
|
||||
assert bootDescriptor.getComponentClass() != null;
|
||||
|
||||
this.strategySelector = creationContext.getSessionFactory()
|
||||
|
@ -54,6 +57,13 @@ public class StandardPojoEmbeddableRepresentationStrategy extends AbstractEmbedd
|
|||
.getService( StrategySelector.class );
|
||||
|
||||
this.reflectionOptimizer = buildReflectionOptimizer( bootDescriptor, creationContext );
|
||||
final ConfigurationService configurationService = creationContext.getMetadata().getMetadataBuildingOptions().getServiceRegistry()
|
||||
.getService(ConfigurationService.class);
|
||||
boolean createEmptyCompositesEnabled = ConfigurationHelper.getBoolean(
|
||||
Environment.CREATE_EMPTY_COMPOSITES_ENABLED,
|
||||
configurationService.getSettings(),
|
||||
false
|
||||
);
|
||||
|
||||
if ( reflectionOptimizer != null && reflectionOptimizer.getInstantiationOptimizer() != null ) {
|
||||
final ReflectionOptimizer.InstantiationOptimizer instantiationOptimizer = reflectionOptimizer.getInstantiationOptimizer();
|
||||
|
|
|
@ -17,9 +17,12 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
|
||||
|
@ -88,6 +91,8 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
|
||||
private final EmbeddableValuedModelPart valueMapping;
|
||||
|
||||
private final boolean createEmptyCompositesEnabled;
|
||||
|
||||
private EmbeddableMappingType(
|
||||
@SuppressWarnings("unused") Component bootDescriptor,
|
||||
EmbeddableRepresentationStrategy representationStrategy,
|
||||
|
@ -99,6 +104,14 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
|
||||
this.valueMapping = embeddedPartBuilder.apply( this );
|
||||
|
||||
final ConfigurationService cs = sessionFactory.getServiceRegistry()
|
||||
.getService(ConfigurationService.class);
|
||||
|
||||
this.createEmptyCompositesEnabled = ConfigurationHelper.getBoolean(
|
||||
Environment.CREATE_EMPTY_COMPOSITES_ENABLED,
|
||||
cs.getSettings(),
|
||||
false
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
@ -392,4 +405,8 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
public boolean isCreateEmptyCompositesEnabled() {
|
||||
return createEmptyCompositesEnabled;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,10 @@ public class EmbeddableValuedPathInterpretation<T> implements AssignableSqmPathI
|
|||
this.tableGroup = tableGroup;
|
||||
}
|
||||
|
||||
public Expression getSqlExpression() {
|
||||
return sqlExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return sqmPath.getNavigablePath();
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
|
|||
import org.hibernate.persister.entity.Loadable;
|
||||
import org.hibernate.query.QueryLiteralRendering;
|
||||
import org.hibernate.query.UnaryArithmeticOperator;
|
||||
import org.hibernate.query.sqm.sql.internal.EmbeddableValuedPathInterpretation;
|
||||
import org.hibernate.query.sqm.tree.expression.Conversion;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
|
@ -1108,12 +1109,56 @@ public abstract class AbstractSqlAstWalker
|
|||
|
||||
@Override
|
||||
public void visitNullnessPredicate(NullnessPredicate nullnessPredicate) {
|
||||
nullnessPredicate.getExpression().accept( this );
|
||||
if ( nullnessPredicate.isNegated() ) {
|
||||
appendSql( " is not null" );
|
||||
final Expression expression = nullnessPredicate.getExpression();
|
||||
if ( expression instanceof EmbeddableValuedPathInterpretation ) {
|
||||
final EmbeddableValuedPathInterpretation embeddableValuedPathInterpretation = (EmbeddableValuedPathInterpretation) expression;
|
||||
|
||||
final Expression sqlExpression = embeddableValuedPathInterpretation.getSqlExpression();
|
||||
String predicateValue;
|
||||
if ( nullnessPredicate.isNegated() ) {
|
||||
predicateValue = " is not null";
|
||||
}
|
||||
else {
|
||||
predicateValue = " is null";
|
||||
}
|
||||
if ( sqlExpression instanceof SqlTuple ) {
|
||||
SqlTuple tuple = (SqlTuple) sqlExpression;
|
||||
String separator = NO_SEPARATOR;
|
||||
|
||||
boolean isCurrentWhereClause = clauseStack.getCurrent() == Clause.WHERE;
|
||||
if ( isCurrentWhereClause ) {
|
||||
appendSql( OPEN_PARENTHESIS );
|
||||
}
|
||||
|
||||
for ( Expression exp : tuple.getExpressions() ) {
|
||||
appendSql( separator );
|
||||
exp.accept( this );
|
||||
appendSql( predicateValue );
|
||||
separator = " and ";
|
||||
}
|
||||
|
||||
if ( isCurrentWhereClause ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
if ( nullnessPredicate.isNegated() ) {
|
||||
appendSql( " is not null" );
|
||||
}
|
||||
else {
|
||||
appendSql( " is null" );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
appendSql( " is null" );
|
||||
expression.accept( this );
|
||||
if ( nullnessPredicate.isNegated() ) {
|
||||
appendSql( " is not null" );
|
||||
}
|
||||
else {
|
||||
appendSql( " is null" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@ import java.util.IdentityHashMap;
|
|||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
|
||||
|
@ -36,6 +39,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
|
||||
// per-row state
|
||||
private final Object[] resolvedValues;
|
||||
private final boolean createEmptyCompositesEnabled;
|
||||
private Object compositeInstance;
|
||||
|
||||
|
||||
|
@ -66,6 +70,8 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
}
|
||||
);
|
||||
|
||||
createEmptyCompositesEnabled = embeddableTypeDescriptor.isCreateEmptyCompositesEnabled();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -136,6 +142,7 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
compositeInstance
|
||||
);
|
||||
|
||||
boolean areAllValuesNull = true;
|
||||
for ( Map.Entry<StateArrayContributorMapping, DomainResultAssembler> entry : assemblerMap.entrySet() ) {
|
||||
final Object contributorValue = entry.getValue().assemble(
|
||||
rowProcessingState,
|
||||
|
@ -143,13 +150,21 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
|
|||
);
|
||||
|
||||
resolvedValues[ entry.getKey().getStateArrayPosition() ] = contributorValue;
|
||||
if ( contributorValue != null ) {
|
||||
areAllValuesNull = false;
|
||||
}
|
||||
}
|
||||
|
||||
embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues(
|
||||
compositeInstance,
|
||||
resolvedValues
|
||||
);
|
||||
|
||||
if ( !createEmptyCompositesEnabled && areAllValuesNull ) {
|
||||
compositeInstance = null;
|
||||
}
|
||||
else {
|
||||
embeddedModelPartDescriptor.getEmbeddableTypeDescriptor().setPropertyValues(
|
||||
compositeInstance,
|
||||
resolvedValues
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -359,9 +359,11 @@ public class EmbeddedTest {
|
|||
// Create short swap
|
||||
Swap shortSwap = new Swap();
|
||||
shortSwap.setTenor( 2 );
|
||||
|
||||
FixedLeg shortFixed = new FixedLeg();
|
||||
shortFixed.setPaymentFrequency( Frequency.SEMIANNUALLY );
|
||||
shortFixed.setRate( 5.6 );
|
||||
|
||||
FloatLeg shortFloating = new FloatLeg();
|
||||
shortFloating.setPaymentFrequency( Frequency.QUARTERLY );
|
||||
shortFloating.setRateIndex( RateIndex.LIBOR );
|
||||
|
@ -371,9 +373,11 @@ public class EmbeddedTest {
|
|||
// Create medium swap
|
||||
Swap swap = new Swap();
|
||||
swap.setTenor( 7 );
|
||||
|
||||
FixedLeg fixed = new FixedLeg();
|
||||
fixed.setPaymentFrequency( Frequency.MONTHLY );
|
||||
fixed.setRate( 7.6 );
|
||||
|
||||
FloatLeg floating = new FloatLeg();
|
||||
floating.setPaymentFrequency( Frequency.MONTHLY );
|
||||
floating.setRateIndex( RateIndex.TIBOR );
|
||||
|
@ -383,9 +387,11 @@ public class EmbeddedTest {
|
|||
// Create long swap
|
||||
Swap longSwap = new Swap();
|
||||
longSwap.setTenor( 7 );
|
||||
|
||||
FixedLeg longFixed = new FixedLeg();
|
||||
longFixed.setPaymentFrequency( Frequency.MONTHLY );
|
||||
longFixed.setRate( 7.6 );
|
||||
|
||||
FloatLeg longFloating = new FloatLeg();
|
||||
longFloating.setPaymentFrequency( Frequency.MONTHLY );
|
||||
longFloating.setRateIndex( RateIndex.TIBOR );
|
||||
|
@ -480,35 +486,25 @@ public class EmbeddedTest {
|
|||
|
||||
@Test
|
||||
public void testParent(SessionFactoryScope scope) {
|
||||
scope.inSession(
|
||||
Book book = new Book();
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.getTransaction().begin();
|
||||
try {
|
||||
Book book = new Book();
|
||||
book.setIsbn( "1234" );
|
||||
book.setName( "HiA Second Edition" );
|
||||
Summary summary = new Summary();
|
||||
summary.setText( "This is a HiA SE summary" );
|
||||
summary.setSize( summary.getText().length() );
|
||||
book.setSummary( summary );
|
||||
session.persist( book );
|
||||
session.getTransaction().commit();
|
||||
book.setIsbn( "1234" );
|
||||
book.setName( "HiA Second Edition" );
|
||||
Summary summary = new Summary();
|
||||
summary.setText( "This is a HiA SE summary" );
|
||||
summary.setSize( summary.getText().length() );
|
||||
book.setSummary( summary );
|
||||
session.persist( book );
|
||||
}
|
||||
);
|
||||
|
||||
session.clear();
|
||||
|
||||
Transaction tx = session.beginTransaction();
|
||||
Book loadedBook = session.get( Book.class, book.getIsbn() );
|
||||
assertNotNull( loadedBook.getSummary() );
|
||||
assertEquals( loadedBook, loadedBook.getSummary().getSummarizedBook() );
|
||||
session.delete( loadedBook );
|
||||
tx.commit();
|
||||
}
|
||||
catch (Exception e) {
|
||||
if ( session.getTransaction().isActive() ) {
|
||||
session.getTransaction().rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Book loadedBook = session.get( Book.class, book.getIsbn() );
|
||||
assertNotNull( loadedBook.getSummary() );
|
||||
assertEquals( loadedBook, loadedBook.getSummary().getSummarizedBook() );
|
||||
session.delete( loadedBook );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ public class MappedSuperclassTest {
|
|||
ForeignCustomer.class
|
||||
).getSingleResult();
|
||||
assertThat( foreignCustomer.getName(), is( "foreign" ) );
|
||||
assertThat( foreignCustomer.getAddress().getCity(), is( nullValue() ) );
|
||||
assertThat( foreignCustomer.getAddress(), is( nullValue() ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ public class TablePerClassTest {
|
|||
ForeignCustomer.class
|
||||
).getSingleResult();
|
||||
assertThat( foreignCustomer.getName(), is( "foreign" ) );
|
||||
assertThat( foreignCustomer.getAddress().getCity(), is( nullValue() ) );
|
||||
assertThat( foreignCustomer.getAddress(), is( nullValue() ) );
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ public class MultiLoadSubSelectCollectionTest {
|
|||
|
||||
// None of the collections should be loaded yet
|
||||
for ( Parent p : list ) {
|
||||
assertFalse( Hibernate.isInitialized( list.get( 0 ).children ) );
|
||||
assertFalse( Hibernate.isInitialized( p.children ) );
|
||||
}
|
||||
|
||||
// When the first collection is loaded, the full batch of 50 collections
|
||||
|
|
Loading…
Reference in New Issue