remove the @Deprecated and @Incubating support for hibernate.create_empty_composites.enabled
Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
parent
0cbdc44fbc
commit
3fd2a146ef
|
@ -16,7 +16,6 @@ import java.util.List;
|
||||||
import java.util.ServiceConfigurationError;
|
import java.util.ServiceConfigurationError;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
|
|
@ -453,29 +453,6 @@ public interface MappingSettings {
|
||||||
*/
|
*/
|
||||||
String DEFAULT_LIST_SEMANTICS = "hibernate.mapping.default_list_semantics";
|
String DEFAULT_LIST_SEMANTICS = "hibernate.mapping.default_list_semantics";
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable instantiation of composite/embedded objects when all attribute values
|
|
||||||
* are {@code null}. The default (and historical) behavior is that a {@code null}
|
|
||||||
* reference will be used to represent the composite value when all of its
|
|
||||||
* attributes are {@code null}.
|
|
||||||
*
|
|
||||||
* @apiNote This is an experimental feature that has known issues. It should not
|
|
||||||
* be used in production until it is stabilized. See Hibernate JIRA issue
|
|
||||||
* HHH-11936 for details.
|
|
||||||
*
|
|
||||||
* @deprecated It makes no sense at all to enable this at the global level for a
|
|
||||||
* persistence unit. If anything, it could be a setting specific to
|
|
||||||
* a given embeddable class. But, four years after the introduction of
|
|
||||||
* this feature, it's still marked experimental and has multiple known
|
|
||||||
* unresolved bugs. It's therefore time for those who advocated for
|
|
||||||
* this feature to accept defeat.
|
|
||||||
*
|
|
||||||
* @since 5.1
|
|
||||||
*/
|
|
||||||
@Incubating
|
|
||||||
@Deprecated(since = "6")
|
|
||||||
String CREATE_EMPTY_COMPOSITES_ENABLED = "hibernate.create_empty_composites.enabled";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link org.hibernate.annotations.Where @Where} annotation specifies a
|
* The {@link org.hibernate.annotations.Where @Where} annotation specifies a
|
||||||
* restriction on the table rows which are visible as entity class instances or
|
* restriction on the table rows which are visible as entity class instances or
|
||||||
|
|
|
@ -138,7 +138,6 @@ import jakarta.persistence.TypedQueryReference;
|
||||||
import static jakarta.persistence.SynchronizationType.SYNCHRONIZED;
|
import static jakarta.persistence.SynchronizationType.SYNCHRONIZED;
|
||||||
import static java.util.Collections.emptySet;
|
import static java.util.Collections.emptySet;
|
||||||
import static java.util.Collections.unmodifiableSet;
|
import static java.util.Collections.unmodifiableSet;
|
||||||
import static org.hibernate.cfg.AvailableSettings.CREATE_EMPTY_COMPOSITES_ENABLED;
|
|
||||||
import static org.hibernate.cfg.AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS;
|
import static org.hibernate.cfg.AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS;
|
||||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_VALIDATION_FACTORY;
|
import static org.hibernate.cfg.AvailableSettings.JAKARTA_VALIDATION_FACTORY;
|
||||||
import static org.hibernate.cfg.AvailableSettings.JPA_VALIDATION_FACTORY;
|
import static org.hibernate.cfg.AvailableSettings.JPA_VALIDATION_FACTORY;
|
||||||
|
@ -147,7 +146,6 @@ import static org.hibernate.cfg.PersistenceSettings.SESSION_FACTORY_JNDI_NAME;
|
||||||
import static org.hibernate.engine.config.spi.StandardConverters.STRING;
|
import static org.hibernate.engine.config.spi.StandardConverters.STRING;
|
||||||
import static org.hibernate.internal.FetchProfileHelper.getFetchProfiles;
|
import static org.hibernate.internal.FetchProfileHelper.getFetchProfiles;
|
||||||
import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
|
import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
|
||||||
import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean;
|
|
||||||
import static org.hibernate.jpa.HibernateHints.HINT_TENANT_ID;
|
import static org.hibernate.jpa.HibernateHints.HINT_TENANT_ID;
|
||||||
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
|
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
|
||||||
import static org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT;
|
import static org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT;
|
||||||
|
@ -240,7 +238,6 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
|
||||||
maskOutSensitiveInformation( settings );
|
maskOutSensitiveInformation( settings );
|
||||||
deprecationCheck( settings );
|
deprecationCheck( settings );
|
||||||
LOG.debugf( "Instantiating SessionFactory with settings: %s", settings);
|
LOG.debugf( "Instantiating SessionFactory with settings: %s", settings);
|
||||||
logIfEmptyCompositesEnabled( settings );
|
|
||||||
|
|
||||||
sqlStringGenerationContext = createSqlStringGenerationContext( bootMetamodel, options, jdbcServices );
|
sqlStringGenerationContext = createSqlStringGenerationContext( bootMetamodel, options, jdbcServices );
|
||||||
|
|
||||||
|
@ -1784,13 +1781,6 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void logIfEmptyCompositesEnabled(Map<String, Object> props ) {
|
|
||||||
final boolean isEmptyCompositesEnabled = getBoolean( CREATE_EMPTY_COMPOSITES_ENABLED, props );
|
|
||||||
if ( isEmptyCompositesEnabled ) {
|
|
||||||
LOG.emptyCompositesEnabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the {@link FastSessionServices} for this {@code SessionFactory}.
|
* @return the {@link FastSessionServices} for this {@code SessionFactory}.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -39,8 +39,6 @@ public interface EmbeddableMappingType extends ManagedMappingType, SelectableMap
|
||||||
|
|
||||||
EmbeddableRepresentationStrategy getRepresentationStrategy();
|
EmbeddableRepresentationStrategy getRepresentationStrategy();
|
||||||
|
|
||||||
boolean isCreateEmptyCompositesEnabled();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@linkplain EmbeddableDiscriminatorMapping discriminator mapping}
|
* Returns the {@linkplain EmbeddableDiscriminatorMapping discriminator mapping}
|
||||||
* if this discriminator type is polymorphic, {@code null} otherwise.
|
* if this discriminator type is polymorphic, {@code null} otherwise.
|
||||||
|
|
|
@ -19,16 +19,13 @@ import java.util.function.Function;
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.SharedSessionContract;
|
import org.hibernate.SharedSessionContract;
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.aggregate.AggregateSupport;
|
import org.hibernate.dialect.aggregate.AggregateSupport;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
|
||||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.engine.spi.CascadeStyle;
|
import org.hibernate.engine.spi.CascadeStyle;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
|
||||||
import org.hibernate.mapping.AggregateColumn;
|
import org.hibernate.mapping.AggregateColumn;
|
||||||
import org.hibernate.mapping.Any;
|
import org.hibernate.mapping.Any;
|
||||||
import org.hibernate.mapping.BasicValue;
|
import org.hibernate.mapping.BasicValue;
|
||||||
|
@ -179,7 +176,6 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
||||||
private final Map<String, ConcreteEmbeddableTypeImpl> concreteEmbeddableBySubclass;
|
private final Map<String, ConcreteEmbeddableTypeImpl> concreteEmbeddableBySubclass;
|
||||||
private final Map<Object, ConcreteEmbeddableTypeImpl> concreteEmbeddableByDiscriminator;
|
private final Map<Object, ConcreteEmbeddableTypeImpl> concreteEmbeddableByDiscriminator;
|
||||||
|
|
||||||
private final boolean createEmptyCompositesEnabled;
|
|
||||||
private final SelectableMapping aggregateMapping;
|
private final SelectableMapping aggregateMapping;
|
||||||
private final boolean aggregateMappingRequiresColumnWriter;
|
private final boolean aggregateMappingRequiresColumnWriter;
|
||||||
private final boolean preferSelectAggregateMapping;
|
private final boolean preferSelectAggregateMapping;
|
||||||
|
@ -222,12 +218,6 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
||||||
this.concreteEmbeddableBySubclass = null;
|
this.concreteEmbeddableBySubclass = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.createEmptyCompositesEnabled = ConfigurationHelper.getBoolean(
|
|
||||||
Environment.CREATE_EMPTY_COMPOSITES_ENABLED,
|
|
||||||
creationContext.getServiceRegistry()
|
|
||||||
.requireService( ConfigurationService.class )
|
|
||||||
.getSettings()
|
|
||||||
);
|
|
||||||
final AggregateColumn aggregateColumn = bootDescriptor.getAggregateColumn();
|
final AggregateColumn aggregateColumn = bootDescriptor.getAggregateColumn();
|
||||||
if ( aggregateColumn != null ) {
|
if ( aggregateColumn != null ) {
|
||||||
final Dialect dialect = creationContext.getDialect();
|
final Dialect dialect = creationContext.getDialect();
|
||||||
|
@ -366,7 +356,6 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
||||||
this.discriminatorMapping = null;
|
this.discriminatorMapping = null;
|
||||||
this.concreteEmbeddableBySubclass = null;
|
this.concreteEmbeddableBySubclass = null;
|
||||||
this.concreteEmbeddableByDiscriminator = null;
|
this.concreteEmbeddableByDiscriminator = null;
|
||||||
this.createEmptyCompositesEnabled = inverseMappingType.isCreateEmptyCompositesEnabled();
|
|
||||||
this.aggregateMapping = null;
|
this.aggregateMapping = null;
|
||||||
this.aggregateMappingRequiresColumnWriter = false;
|
this.aggregateMappingRequiresColumnWriter = false;
|
||||||
this.preferSelectAggregateMapping = false;
|
this.preferSelectAggregateMapping = false;
|
||||||
|
@ -1120,11 +1109,6 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCreateEmptyCompositesEnabled() {
|
|
||||||
return createEmptyCompositesEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SelectableMapping getAggregateMapping() {
|
public SelectableMapping getAggregateMapping() {
|
||||||
return aggregateMapping;
|
return aggregateMapping;
|
||||||
|
|
|
@ -274,14 +274,6 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
|
||||||
return embedded;
|
return embedded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCreateEmptyCompositesEnabled() {
|
|
||||||
// generally we do not want empty composites for identifiers
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void forEachAttributeMapping(Consumer<? super AttributeMapping> action) {
|
public void forEachAttributeMapping(Consumer<? super AttributeMapping> action) {
|
||||||
forEachAttribute( (index, attribute) -> action.accept( attribute ) );
|
forEachAttribute( (index, attribute) -> action.accept( attribute ) );
|
||||||
|
|
|
@ -146,12 +146,6 @@ public class VirtualIdEmbeddable extends AbstractEmbeddableMapping implements Id
|
||||||
return representationStrategy;
|
return representationStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCreateEmptyCompositesEnabled() {
|
|
||||||
// generally we do not want empty composites for identifiers
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityMappingType findContainingEntityMapping() {
|
public EntityMappingType findContainingEntityMapping() {
|
||||||
return idMapping.findContainingEntityMapping();
|
return idMapping.findContainingEntityMapping();
|
||||||
|
|
|
@ -188,11 +188,6 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
|
||||||
.getRepresentationStrategy();
|
.getRepresentationStrategy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCreateEmptyCompositesEnabled() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EmbeddableMappingType createInverseMappingType(
|
public EmbeddableMappingType createInverseMappingType(
|
||||||
EmbeddedAttributeMapping valueMapping,
|
EmbeddedAttributeMapping valueMapping,
|
||||||
|
|
|
@ -21,7 +21,6 @@ import org.hibernate.metamodel.spi.EmbeddableInstantiator;
|
||||||
import org.hibernate.metamodel.spi.ValueAccess;
|
import org.hibernate.metamodel.spi.ValueAccess;
|
||||||
import org.hibernate.property.access.spi.PropertyAccess;
|
import org.hibernate.property.access.spi.PropertyAccess;
|
||||||
import org.hibernate.property.access.spi.Setter;
|
import org.hibernate.property.access.spi.Setter;
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
|
||||||
import org.hibernate.proxy.LazyInitializer;
|
import org.hibernate.proxy.LazyInitializer;
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||||
|
@ -44,6 +43,8 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
|
||||||
|
import static org.hibernate.sql.results.graph.embeddable.EmbeddableLoadingLogger.EMBEDDED_LOAD_LOGGER;
|
||||||
import static org.hibernate.sql.results.graph.entity.internal.BatchEntityInsideEmbeddableSelectFetchInitializer.BATCH_PROPERTY;
|
import static org.hibernate.sql.results.graph.entity.internal.BatchEntityInsideEmbeddableSelectFetchInitializer.BATCH_PROPERTY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,7 +59,6 @@ public class EmbeddableInitializerImpl extends AbstractInitializer<EmbeddableIni
|
||||||
private final @Nullable InitializerParent<InitializerData> parent;
|
private final @Nullable InitializerParent<InitializerData> parent;
|
||||||
private final boolean isResultInitializer;
|
private final boolean isResultInitializer;
|
||||||
private final boolean isPartOfKey;
|
private final boolean isPartOfKey;
|
||||||
private final boolean createEmptyCompositesEnabled;
|
|
||||||
private final SessionFactoryImplementor sessionFactory;
|
private final SessionFactoryImplementor sessionFactory;
|
||||||
|
|
||||||
protected final DomainResultAssembler<?>[][] assemblers;
|
protected final DomainResultAssembler<?>[][] assemblers;
|
||||||
|
@ -117,7 +117,6 @@ public class EmbeddableInitializerImpl extends AbstractInitializer<EmbeddableIni
|
||||||
|
|
||||||
this.isPartOfKey = embedded.isEntityIdentifierMapping() || Initializer.isPartOfKey( navigablePath, parent );
|
this.isPartOfKey = embedded.isEntityIdentifierMapping() || Initializer.isPartOfKey( navigablePath, parent );
|
||||||
// We never want to create empty composites for the FK target or PK, otherwise collections would break
|
// We never want to create empty composites for the FK target or PK, otherwise collections would break
|
||||||
this.createEmptyCompositesEnabled = !isPartOfKey && embeddableMappingType.isCreateEmptyCompositesEnabled();
|
|
||||||
this.sessionFactory = creationState.getSqlAstCreationContext().getSessionFactory();
|
this.sessionFactory = creationState.getSqlAstCreationContext().getSessionFactory();
|
||||||
final Collection<EmbeddableMappingType.ConcreteEmbeddableType> concreteEmbeddableTypes = embeddableMappingType.getConcreteEmbeddableTypes();
|
final Collection<EmbeddableMappingType.ConcreteEmbeddableType> concreteEmbeddableTypes = embeddableMappingType.getConcreteEmbeddableTypes();
|
||||||
final DomainResultAssembler<?>[][] assemblers = new DomainResultAssembler[concreteEmbeddableTypes.isEmpty() ? 1 : concreteEmbeddableTypes.size()][];
|
final DomainResultAssembler<?>[][] assemblers = new DomainResultAssembler[concreteEmbeddableTypes.isEmpty() ? 1 : concreteEmbeddableTypes.size()][];
|
||||||
|
@ -474,6 +473,8 @@ public class EmbeddableInitializerImpl extends AbstractInitializer<EmbeddableIni
|
||||||
if ( data.getInstance() == null ) {
|
if ( data.getInstance() == null ) {
|
||||||
data.setInstance( createCompositeInstance( data ) );
|
data.setInstance( createCompositeInstance( data ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EMBEDDED_LOAD_LOGGER.debugf( "Created composite instance [%s]", navigablePath );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractRowState(EmbeddableInitializerData data) {
|
private void extractRowState(EmbeddableInitializerData data) {
|
||||||
|
@ -515,18 +516,15 @@ public class EmbeddableInitializerImpl extends AbstractInitializer<EmbeddableIni
|
||||||
|
|
||||||
private Object createCompositeInstance(EmbeddableInitializerData data) {
|
private Object createCompositeInstance(EmbeddableInitializerData data) {
|
||||||
if ( data.getState() == State.MISSING ) {
|
if ( data.getState() == State.MISSING ) {
|
||||||
// todo (6.0) : should we initialize the composite instance if it has a parent attribute?
|
|
||||||
// if ( !createEmptyCompositesEnabled && embedded.getParentInjectionAttributePropertyAccess() == null ) {
|
|
||||||
if ( !createEmptyCompositesEnabled ) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
final EmbeddableInstantiator instantiator = data.concreteEmbeddableType == null
|
final EmbeddableInstantiator instantiator = data.concreteEmbeddableType == null
|
||||||
? embeddableMappingType.getRepresentationStrategy().getInstantiator()
|
? embeddableMappingType.getRepresentationStrategy().getInstantiator()
|
||||||
: data.concreteEmbeddableType.getInstantiator();
|
: data.concreteEmbeddableType.getInstantiator();
|
||||||
final Object instance = instantiator.instantiate( data, sessionFactory );
|
final Object instance = instantiator.instantiate( data, sessionFactory );
|
||||||
data.setState( State.RESOLVED );
|
data.setState( State.RESOLVED );
|
||||||
|
EMBEDDED_LOAD_LOGGER.debugf( "Created composite instance [%s] : %s", navigablePath, instance );
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,174 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.component.empty;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Set;
|
|
||||||
import jakarta.persistence.ElementCollection;
|
|
||||||
import jakarta.persistence.Embeddable;
|
|
||||||
import jakarta.persistence.EmbeddedId;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
|
|
||||||
import org.hibernate.Hibernate;
|
|
||||||
import org.hibernate.cfg.Configuration;
|
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Gail Badner
|
|
||||||
*/
|
|
||||||
public class EmptyCompositeCollectionKeyEagerTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] {
|
|
||||||
AnEntity.class
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(Configuration configuration) {
|
|
||||||
super.configure( configuration );
|
|
||||||
configuration.getProperties().put( Environment.CREATE_EMPTY_COMPOSITES_ENABLED, "true" );
|
|
||||||
configuration.getProperties().put( Environment.USE_SECOND_LEVEL_CACHE, "false" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetEntityWithEmptyCollection() {
|
|
||||||
AnEntity.PK id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity( new AnEntity.PK( "first", "last" ));
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.find( AnEntity.class, id );
|
|
||||||
assertTrue( Hibernate.isInitialized( anEntity.names ) );
|
|
||||||
assertTrue( anEntity.names.isEmpty() );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testQueryEntityWithEmptyCollection() {
|
|
||||||
AnEntity.PK id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity( new AnEntity.PK( "first", "last" ) );
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
"from AnEntity where id = :id",
|
|
||||||
AnEntity.class
|
|
||||||
).setParameter( "id", id ).uniqueResult();
|
|
||||||
assertTrue( Hibernate.isInitialized( anEntity.names ) );
|
|
||||||
assertTrue( anEntity.names.isEmpty() );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testQueryEntityJoinFetchEmptyCollection() {
|
|
||||||
AnEntity.PK id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity( new AnEntity.PK( "first", "last" ) );
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
"from AnEntity e join fetch e.names where e.id = :id ",
|
|
||||||
AnEntity.class
|
|
||||||
).setParameter( "id", id ).uniqueResult();
|
|
||||||
assertNull( anEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testQueryEntityLeftJoinFetchEmptyCollection() {
|
|
||||||
AnEntity.PK id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity( new AnEntity.PK( "first", "last" ) );
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
"from AnEntity e left join fetch e.names where e.id = :id",
|
|
||||||
AnEntity.class
|
|
||||||
).setParameter( "id", id ).uniqueResult();
|
|
||||||
assertTrue( Hibernate.isInitialized( anEntity.names ) );
|
|
||||||
assertTrue( anEntity.names.isEmpty() );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isCleanupTestDataRequired() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "AnEntity")
|
|
||||||
public static class AnEntity {
|
|
||||||
@EmbeddedId
|
|
||||||
private PK id;
|
|
||||||
|
|
||||||
@ElementCollection(fetch = FetchType.EAGER)
|
|
||||||
private Set<String> names;
|
|
||||||
|
|
||||||
public AnEntity() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public AnEntity(PK id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Embeddable
|
|
||||||
public static class PK implements Serializable {
|
|
||||||
private String firstName;
|
|
||||||
private String lastName;
|
|
||||||
|
|
||||||
public PK() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public PK(String firstName, String lastName) {
|
|
||||||
this.firstName = firstName;
|
|
||||||
this.lastName = lastName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,176 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.component.empty;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Set;
|
|
||||||
import jakarta.persistence.ElementCollection;
|
|
||||||
import jakarta.persistence.Embeddable;
|
|
||||||
import jakarta.persistence.EmbeddedId;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
|
|
||||||
import org.hibernate.Hibernate;
|
|
||||||
import org.hibernate.cfg.Configuration;
|
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Gail Badner
|
|
||||||
*/
|
|
||||||
public class EmptyCompositeCollectionKeyLazyTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] {
|
|
||||||
AnEntity.class
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(Configuration configuration) {
|
|
||||||
super.configure( configuration );
|
|
||||||
configuration.getProperties().put( Environment.CREATE_EMPTY_COMPOSITES_ENABLED, "true" );
|
|
||||||
configuration.getProperties().put( Environment.USE_SECOND_LEVEL_CACHE, "false" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetEntityWithEmptyCollection() {
|
|
||||||
AnEntity.PK id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity( new AnEntity.PK( "first", "last" ));
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.find( AnEntity.class, id );
|
|
||||||
assertFalse( Hibernate.isInitialized( anEntity.names ) );
|
|
||||||
assertTrue( anEntity.names.isEmpty() );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testQueryEntityWithEmptyCollection() {
|
|
||||||
AnEntity.PK id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity( new AnEntity.PK( "first", "last" ) );
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
"from AnEntity where id = :id",
|
|
||||||
AnEntity.class
|
|
||||||
).setParameter( "id", id ).uniqueResult();
|
|
||||||
assertFalse( Hibernate.isInitialized( anEntity.names ) );
|
|
||||||
assertTrue( anEntity.names.isEmpty() );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testQueryEntityJoinFetchEmptyCollection() {
|
|
||||||
AnEntity.PK id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity( new AnEntity.PK( "first", "last" ) );
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
"from AnEntity e join fetch e.names where e.id = :id ",
|
|
||||||
AnEntity.class
|
|
||||||
).setParameter( "id", id ).uniqueResult();
|
|
||||||
assertNull( anEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-11928" )
|
|
||||||
public void testQueryEntityLeftJoinFetchEmptyCollection() {
|
|
||||||
AnEntity.PK id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity( new AnEntity.PK( "first", "last" ) );
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
"from AnEntity e left join fetch e.names where e.id = :id",
|
|
||||||
AnEntity.class
|
|
||||||
).setParameter( "id", id ).uniqueResult();
|
|
||||||
assertTrue( Hibernate.isInitialized( anEntity.names ) );
|
|
||||||
assertTrue( anEntity.names.isEmpty() );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isCleanupTestDataRequired() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "AnEntity")
|
|
||||||
public static class AnEntity {
|
|
||||||
@EmbeddedId
|
|
||||||
private PK id;
|
|
||||||
|
|
||||||
@ElementCollection
|
|
||||||
private Set<String> names;
|
|
||||||
|
|
||||||
public AnEntity() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public AnEntity(PK id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Embeddable
|
|
||||||
public static class PK implements Serializable {
|
|
||||||
private String firstName;
|
|
||||||
private String lastName;
|
|
||||||
|
|
||||||
public PK() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public PK(String firstName, String lastName) {
|
|
||||||
this.firstName = firstName;
|
|
||||||
this.lastName = lastName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,226 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.component.empty;
|
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Embeddable;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
|
|
||||||
import org.hibernate.annotations.Parent;
|
|
||||||
import org.hibernate.cfg.Configuration;
|
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|
||||||
import org.hibernate.type.CompositeType;
|
|
||||||
|
|
||||||
import org.hibernate.testing.FailureExpected;
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Gail Badner
|
|
||||||
*/
|
|
||||||
public class EmptyCompositeEquivalentToNullTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] { AnEntity.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(Configuration configuration) {
|
|
||||||
super.configure( configuration );
|
|
||||||
configuration.getProperties().put( Environment.CREATE_EMPTY_COMPOSITES_ENABLED, "true" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-11898" )
|
|
||||||
@FailureExpected( jiraKey = "HHH-11898" )
|
|
||||||
public void testPrimitive() {
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
session.flush();
|
|
||||||
session.clear();
|
|
||||||
anEntity = session.get( AnEntity.class, anEntity.id );
|
|
||||||
checkEmptyCompositeTypeEquivalentToNull(
|
|
||||||
anEntity.embeddableWithPrimitive,
|
|
||||||
"embeddableWithPrimitive",
|
|
||||||
sessionFactory()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-11898" )
|
|
||||||
public void testParent() {
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
session.flush();
|
|
||||||
session.clear();
|
|
||||||
anEntity = session.get( AnEntity.class, anEntity.id );
|
|
||||||
checkEmptyCompositeTypeEquivalentToNull(
|
|
||||||
anEntity.embeddableWithParent,
|
|
||||||
"embeddableWithParent",
|
|
||||||
sessionFactory()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-11898" )
|
|
||||||
public void testNoPrimitiveNoParent() {
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
session.flush();
|
|
||||||
session.clear();
|
|
||||||
anEntity = session.get( AnEntity.class, anEntity.id );
|
|
||||||
checkEmptyCompositeTypeEquivalentToNull(
|
|
||||||
anEntity.embeddableWithNoPrimitiveNoParent,
|
|
||||||
"embeddableWithNoPrimitiveNoParent",
|
|
||||||
sessionFactory()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkEmptyCompositeTypeEquivalentToNull(
|
|
||||||
Object compositeValue,
|
|
||||||
String componentPropertyName,
|
|
||||||
SessionFactoryImplementor sessionFactory) {
|
|
||||||
assertNotNull( compositeValue );
|
|
||||||
final CompositeType compositeType = getCompositeType( componentPropertyName, sessionFactory );
|
|
||||||
assertTrue( compositeType.isEqual( null, compositeValue, sessionFactory ) );
|
|
||||||
assertTrue( compositeType.isEqual( compositeValue, null, sessionFactory ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
private CompositeType getCompositeType(String componentPropertyName, SessionFactoryImplementor sessionFactory) {
|
|
||||||
return (CompositeType) sessionFactory
|
|
||||||
.getRuntimeMetamodels()
|
|
||||||
.getMappingMetamodel()
|
|
||||||
.getEntityDescriptor( AnEntity.class )
|
|
||||||
.getPropertyType( componentPropertyName );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "AnEntity")
|
|
||||||
public static class AnEntity {
|
|
||||||
private int id;
|
|
||||||
private EmbeddableWithParent embeddableWithParent;
|
|
||||||
private EmbeddableWithPrimitive embeddableWithPrimitive;
|
|
||||||
private EmbeddableWithNoPrimitiveNoParent embeddableWithNoPrimitiveNoParent;
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EmbeddableWithParent getEmbeddableWithParent() {
|
|
||||||
return embeddableWithParent;
|
|
||||||
}
|
|
||||||
public void setEmbeddableWithParent(EmbeddableWithParent embeddableWithParent) {
|
|
||||||
this.embeddableWithParent = embeddableWithParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EmbeddableWithPrimitive getEmbeddableWithPrimitive() {
|
|
||||||
return embeddableWithPrimitive;
|
|
||||||
}
|
|
||||||
public void setEmbeddableWithPrimitive(EmbeddableWithPrimitive embeddableWithPrimitive) {
|
|
||||||
this.embeddableWithPrimitive = embeddableWithPrimitive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EmbeddableWithNoPrimitiveNoParent getEmbeddableWithNoPrimitiveNoParent() {
|
|
||||||
return embeddableWithNoPrimitiveNoParent;
|
|
||||||
}
|
|
||||||
public void setEmbeddableWithNoPrimitiveNoParent(EmbeddableWithNoPrimitiveNoParent embeddableWithNoPrimitiveNoParent) {
|
|
||||||
this.embeddableWithNoPrimitiveNoParent = embeddableWithNoPrimitiveNoParent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Embeddable
|
|
||||||
public static class EmbeddableWithParent {
|
|
||||||
private Object parent;
|
|
||||||
private Long longObjectValue;
|
|
||||||
|
|
||||||
@Parent
|
|
||||||
public Object getParent() {
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
public void setParent(Object parent) {
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getLongObjectValue() {
|
|
||||||
return longObjectValue;
|
|
||||||
}
|
|
||||||
public void setLongObjectValue(Long longObjectValue) {
|
|
||||||
this.longObjectValue = longObjectValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Embeddable
|
|
||||||
public static class EmbeddableWithPrimitive {
|
|
||||||
private int intValue;
|
|
||||||
private String stringValue;
|
|
||||||
|
|
||||||
@Column(nullable = true)
|
|
||||||
public int getIntValue() {
|
|
||||||
return intValue;
|
|
||||||
}
|
|
||||||
public void setIntValue(int intValue) {
|
|
||||||
this.intValue = intValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStringValue() {
|
|
||||||
return stringValue;
|
|
||||||
}
|
|
||||||
public void setStringValue(String stringValue) {
|
|
||||||
this.stringValue = stringValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Embeddable
|
|
||||||
public static class EmbeddableWithNoPrimitiveNoParent {
|
|
||||||
private Integer intObjectValue;
|
|
||||||
private String otherStringValue;
|
|
||||||
|
|
||||||
public Integer getIntObjectValue() {
|
|
||||||
return intObjectValue;
|
|
||||||
}
|
|
||||||
public void setIntObjectValue(Integer intObjectValue) {
|
|
||||||
this.intObjectValue = intObjectValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOtherStringValue() {
|
|
||||||
return otherStringValue;
|
|
||||||
}
|
|
||||||
public void setOtherStringValue(String otherStringValue) {
|
|
||||||
this.otherStringValue = otherStringValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,435 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.component.empty;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import jakarta.persistence.Cacheable;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import jakarta.persistence.SharedCacheMode;
|
|
||||||
|
|
||||||
import org.hibernate.cache.spi.access.AccessType;
|
|
||||||
import org.hibernate.cfg.Configuration;
|
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
import org.hibernate.stat.CacheRegionStatistics;
|
|
||||||
import org.hibernate.stat.QueryStatistics;
|
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Gail Badner
|
|
||||||
*/
|
|
||||||
public class EmptyCompositeManyToOneKeyCachedTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] {
|
|
||||||
AnEntity.class,
|
|
||||||
OtherEntity.class
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(Configuration configuration) {
|
|
||||||
super.configure( configuration );
|
|
||||||
configuration.getProperties().put( Environment.CREATE_EMPTY_COMPOSITES_ENABLED, "true" );
|
|
||||||
configuration.getProperties().put( Environment.USE_SECOND_LEVEL_CACHE, "true" );
|
|
||||||
configuration.getProperties().put( Environment.DEFAULT_CACHE_CONCURRENCY_STRATEGY, AccessType.READ_WRITE.getExternalName() );
|
|
||||||
configuration.getProperties().put( Environment.USE_QUERY_CACHE, "true" );
|
|
||||||
configuration.getProperties().put( Environment.GENERATE_STATISTICS, "true" );
|
|
||||||
configuration.getProperties().put( Environment.CACHE_REGION_PREFIX, "" );
|
|
||||||
configuration.getProperties().put( "javax.persistence.sharedCache.mode", SharedCacheMode.ALL );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetEntityWithNullManyToOne() {
|
|
||||||
|
|
||||||
sessionFactory().getCache().evictAllRegions();
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
int id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 1, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.find( AnEntity.class, id );
|
|
||||||
assertNotNull( anEntity );
|
|
||||||
assertNull( anEntity.otherEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
assertEquals( 1, getEntity2LCStatistics( AnEntity.class ).getHitCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getHitCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getMissCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getMissCount() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testQueryEntityWithNullManyToOne() {
|
|
||||||
|
|
||||||
sessionFactory().getCache().evictAllRegions();
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
int id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 1, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
final String queryString = "from AnEntity where id = " + id;
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
queryString,
|
|
||||||
AnEntity.class
|
|
||||||
).setCacheable( true ).uniqueResult();
|
|
||||||
assertNull( anEntity.otherEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCacheHitCount() );
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCacheMissCount() );
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCachePutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getHitCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getHitCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getMissCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getMissCount() );
|
|
||||||
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
queryString,
|
|
||||||
AnEntity.class
|
|
||||||
).setCacheable( true ).uniqueResult();
|
|
||||||
assertNull( anEntity.otherEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCacheHitCount() );
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCacheMissCount() );
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCachePutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getHitCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getHitCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getMissCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getMissCount() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testQueryEntityJoinFetchNullManyToOne() {
|
|
||||||
|
|
||||||
sessionFactory().getCache().evictAllRegions();
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
int id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 1, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
final String queryString = "from AnEntity e join fetch e.otherEntity where e.id = " + id;
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
queryString,
|
|
||||||
AnEntity.class
|
|
||||||
).setCacheable( true ).uniqueResult();
|
|
||||||
assertNull( anEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCacheHitCount() );
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCacheMissCount() );
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCachePutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getHitCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getHitCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getMissCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getMissCount() );
|
|
||||||
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
queryString,
|
|
||||||
AnEntity.class
|
|
||||||
).setCacheable( true ).uniqueResult();
|
|
||||||
assertNull( anEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCacheHitCount() );
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCacheMissCount() );
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCachePutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getHitCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getHitCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getMissCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getMissCount() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testQueryEntityLeftJoinFetchNullManyToOne() {
|
|
||||||
|
|
||||||
sessionFactory().getCache().evictAllRegions();
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
int id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 1, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
final String queryString = "from AnEntity e left join fetch e.otherEntity where e.id = " + id;
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
queryString,
|
|
||||||
AnEntity.class
|
|
||||||
).setCacheable( true ).uniqueResult();
|
|
||||||
assertNull( anEntity.otherEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCacheHitCount() );
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCacheMissCount() );
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCachePutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getHitCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getHitCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getMissCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getMissCount() );
|
|
||||||
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
queryString,
|
|
||||||
AnEntity.class
|
|
||||||
).setCacheable( true ).uniqueResult();
|
|
||||||
assertNull( anEntity.otherEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCacheHitCount() );
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCacheMissCount() );
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCachePutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getHitCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getHitCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getMissCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getMissCount() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testQueryEntityAndNullManyToOne() {
|
|
||||||
|
|
||||||
sessionFactory().getCache().evictAllRegions();
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
int id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 1, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
final String queryString = "select e, e.otherEntity from AnEntity e left join e.otherEntity where e.id = " + id;
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final Object[] result = session.createQuery(
|
|
||||||
queryString,
|
|
||||||
Object[].class
|
|
||||||
).setCacheable( true ).uniqueResult();
|
|
||||||
assertEquals( 2, result.length );
|
|
||||||
assertTrue( AnEntity.class.isInstance( result[0] ) );
|
|
||||||
assertNull( result[1] );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCacheHitCount() );
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCacheMissCount() );
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCachePutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getHitCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getHitCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getMissCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getMissCount() );
|
|
||||||
|
|
||||||
sessionFactory().getStatistics().clear();
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final Object[] result = session.createQuery(
|
|
||||||
queryString,
|
|
||||||
Object[].class
|
|
||||||
).setCacheable( true ).uniqueResult();
|
|
||||||
assertEquals( 2, result.length );
|
|
||||||
assertTrue( AnEntity.class.isInstance( result[0] ) );
|
|
||||||
assertNull( result[1] );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
assertEquals( 1, getQueryStatistics( queryString ).getCacheHitCount() );
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCacheMissCount() );
|
|
||||||
assertEquals( 0, getQueryStatistics( queryString ).getCachePutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getPutCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getPutCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getHitCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getHitCount() );
|
|
||||||
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( AnEntity.class ).getMissCount() );
|
|
||||||
assertEquals( 0, getEntity2LCStatistics( OtherEntity.class ).getMissCount() );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isCleanupTestDataRequired() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CacheRegionStatistics getEntity2LCStatistics(Class<?> className) {
|
|
||||||
return sessionFactory().getStatistics()
|
|
||||||
.getDomainDataRegionStatistics( className.getName() );
|
|
||||||
}
|
|
||||||
|
|
||||||
private QueryStatistics getQueryStatistics(String queryString) {
|
|
||||||
return sessionFactory().getStatistics().getQueryStatistics( queryString );
|
|
||||||
}
|
|
||||||
@Entity(name = "AnEntity")
|
|
||||||
@Cacheable
|
|
||||||
public static class AnEntity {
|
|
||||||
@Id
|
|
||||||
private int id;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
private OtherEntity otherEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "OtherEntity")
|
|
||||||
@Cacheable
|
|
||||||
public static class OtherEntity implements Serializable {
|
|
||||||
@Id
|
|
||||||
private String firstName;
|
|
||||||
|
|
||||||
@Id
|
|
||||||
private String lastName;
|
|
||||||
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "OtherEntity{" +
|
|
||||||
"firstName='" + firstName + '\'' +
|
|
||||||
", lastName='" + lastName + '\'' +
|
|
||||||
", description='" + description + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,202 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.component.empty;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
|
|
||||||
import org.hibernate.cfg.Configuration;
|
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Gail Badner
|
|
||||||
*/
|
|
||||||
public class EmptyCompositeManyToOneKeyTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] {
|
|
||||||
AnEntity.class,
|
|
||||||
OtherEntity.class
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(Configuration configuration) {
|
|
||||||
super.configure( configuration );
|
|
||||||
configuration.getProperties().put( Environment.CREATE_EMPTY_COMPOSITES_ENABLED, "true" );
|
|
||||||
configuration.getProperties().put( Environment.USE_SECOND_LEVEL_CACHE, "false" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-11922" )
|
|
||||||
public void testGetEntityWithNullManyToOne() {
|
|
||||||
int id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.find( AnEntity.class, id );
|
|
||||||
assertNotNull( anEntity );
|
|
||||||
assertNull( anEntity.otherEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-11922" )
|
|
||||||
public void testQueryEntityWithNullManyToOne() {
|
|
||||||
int id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
"from AnEntity where id = " + id,
|
|
||||||
AnEntity.class
|
|
||||||
).uniqueResult();
|
|
||||||
assertNull( anEntity.otherEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-11922" )
|
|
||||||
public void testQueryEntityJoinFetchNullManyToOne() {
|
|
||||||
int id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
"from AnEntity e join fetch e.otherEntity where e.id = " + id,
|
|
||||||
AnEntity.class
|
|
||||||
).uniqueResult();
|
|
||||||
assertNull( anEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-11922" )
|
|
||||||
public void testQueryEntityLeftJoinFetchNullManyToOne() {
|
|
||||||
int id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = session.createQuery(
|
|
||||||
"from AnEntity e left join fetch e.otherEntity where e.id = " + id,
|
|
||||||
AnEntity.class
|
|
||||||
).uniqueResult();
|
|
||||||
assertNull( anEntity.otherEntity );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-11922" )
|
|
||||||
public void testQueryEntityAndNullManyToOne() {
|
|
||||||
int id = doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final AnEntity anEntity = new AnEntity();
|
|
||||||
session.persist( anEntity );
|
|
||||||
return anEntity.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
final Object[] result = session.createQuery(
|
|
||||||
"select e, e.otherEntity from AnEntity e left join e.otherEntity where e.id = " + id,
|
|
||||||
Object[].class
|
|
||||||
).uniqueResult();
|
|
||||||
assertEquals( 2, result.length );
|
|
||||||
assertTrue( AnEntity.class.isInstance( result[0] ) );
|
|
||||||
assertNull( result[1] );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isCleanupTestDataRequired() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "AnEntity")
|
|
||||||
public static class AnEntity {
|
|
||||||
@Id
|
|
||||||
private int id;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
private OtherEntity otherEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "OtherEntity")
|
|
||||||
public static class OtherEntity implements Serializable {
|
|
||||||
@Id
|
|
||||||
private String firstName;
|
|
||||||
|
|
||||||
@Id
|
|
||||||
private String lastName;
|
|
||||||
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "OtherEntity{" +
|
|
||||||
"firstName='" + firstName + '\'' +
|
|
||||||
", lastName='" + lastName + '\'' +
|
|
||||||
", description='" + description + '\'' +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.component.empty;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.cfg.Configuration;
|
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test class for empty embedded dirtiness computation.
|
|
||||||
*
|
|
||||||
* @author Laurent Almeras
|
|
||||||
*/
|
|
||||||
public class EmptyCompositesDirtynessTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] { ComponentEmptyEmbeddedOwner.class, ComponentEmptyEmbedded.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(Configuration configuration) {
|
|
||||||
super.configure( configuration );
|
|
||||||
configuration.getProperties().put( Environment.CREATE_EMPTY_COMPOSITES_ENABLED, Boolean.valueOf( false ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for dirtyness computation consistency when a property is an empty composite.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@TestForIssue(jiraKey = "HHH-7610")
|
|
||||||
public void testCompositesEmpty() {
|
|
||||||
Session s = openSession();
|
|
||||||
try {
|
|
||||||
s.getTransaction().begin();
|
|
||||||
|
|
||||||
ComponentEmptyEmbeddedOwner owner = new ComponentEmptyEmbeddedOwner();
|
|
||||||
s.persist( owner );
|
|
||||||
|
|
||||||
s.flush();
|
|
||||||
s.getTransaction().commit();
|
|
||||||
|
|
||||||
s.clear();
|
|
||||||
s.getTransaction().begin();
|
|
||||||
owner = (ComponentEmptyEmbeddedOwner) s.get( ComponentEmptyEmbeddedOwner.class, owner.getId() );
|
|
||||||
assertNull( owner.getEmbedded() );
|
|
||||||
owner.setEmbedded( new ComponentEmptyEmbedded() );
|
|
||||||
|
|
||||||
// technically, as all properties are null, update may not be necessary
|
|
||||||
assertFalse( session.isDirty() ); // must be false to avoid unnecessary updates
|
|
||||||
|
|
||||||
s.getTransaction().rollback();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.component.empty;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.cfg.Configuration;
|
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test class for empty embedded dirtiness computation.
|
|
||||||
*
|
|
||||||
* @author Laurent Almeras
|
|
||||||
*/
|
|
||||||
public class EmptyInitializedCompositesDirtynessTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] { ComponentEmptyEmbeddedOwner.class, ComponentEmptyEmbedded.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(Configuration configuration) {
|
|
||||||
super.configure( configuration );
|
|
||||||
configuration.getProperties().put( Environment.CREATE_EMPTY_COMPOSITES_ENABLED, Boolean.valueOf( true ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for dirtyness computation consistency when a property is an empty composite and that empty composite
|
|
||||||
* initialization is set.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@TestForIssue(jiraKey = "HHH-7610")
|
|
||||||
public void testInitializedCompositesEmpty() {
|
|
||||||
Session s = openSession();
|
|
||||||
try {
|
|
||||||
s.getTransaction().begin();
|
|
||||||
|
|
||||||
ComponentEmptyEmbeddedOwner owner = new ComponentEmptyEmbeddedOwner();
|
|
||||||
s.persist( owner );
|
|
||||||
|
|
||||||
s.flush();
|
|
||||||
s.getTransaction().commit();
|
|
||||||
|
|
||||||
s.clear();
|
|
||||||
s.getTransaction().begin();
|
|
||||||
owner = (ComponentEmptyEmbeddedOwner) s.get( ComponentEmptyEmbeddedOwner.class, owner.getId() );
|
|
||||||
assertNotNull( owner.getEmbedded() );
|
|
||||||
assertFalse( s.isDirty() );
|
|
||||||
|
|
||||||
s.getTransaction().rollback();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.component.empty;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.hibernate.cfg.Configuration;
|
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test class for empty embedded dirtiness computation.
|
|
||||||
*
|
|
||||||
* @author Laurent Almeras
|
|
||||||
*/
|
|
||||||
public class EmptyInitializedCompositesTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] { ComponentEmptyEmbeddedOwner.class, ComponentEmptyEmbedded.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(Configuration configuration) {
|
|
||||||
super.configure( configuration );
|
|
||||||
configuration.getProperties().put( Environment.CREATE_EMPTY_COMPOSITES_ENABLED, Boolean.valueOf( true ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test empty composite initialization.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
@TestForIssue(jiraKey = "HHH-7610")
|
|
||||||
public void testCompositesEmpty() {
|
|
||||||
Session s = openSession();
|
|
||||||
try {
|
|
||||||
s.getTransaction().begin();
|
|
||||||
|
|
||||||
ComponentEmptyEmbeddedOwner owner = new ComponentEmptyEmbeddedOwner();
|
|
||||||
s.persist( owner );
|
|
||||||
|
|
||||||
s.flush();
|
|
||||||
s.getTransaction().commit();
|
|
||||||
|
|
||||||
s.clear();
|
|
||||||
s.getTransaction().begin();
|
|
||||||
owner = (ComponentEmptyEmbeddedOwner) s.get( ComponentEmptyEmbeddedOwner.class, owner.getId() );
|
|
||||||
assertNotNull( owner.getEmbedded() );
|
|
||||||
assertFalse( s.isDirty() );
|
|
||||||
|
|
||||||
owner.setEmbedded( null );
|
|
||||||
assertFalse( s.isDirty() ); // must be false to avoid unnecessary updates
|
|
||||||
|
|
||||||
s.getTransaction().rollback();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
s.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,114 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.component.empty;
|
|
||||||
|
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
|
||||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
|
||||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
|
||||||
import org.hibernate.testing.orm.junit.Setting;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import jakarta.persistence.Embeddable;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that an empty embeddable that is nested inside an embeddable is initialized.
|
|
||||||
*
|
|
||||||
* @author Gail Badner
|
|
||||||
*/
|
|
||||||
@TestForIssue(jiraKey = "HHH-11926")
|
|
||||||
@DomainModel(
|
|
||||||
annotatedClasses = EmptyInitializedNestedCompositesTest.ComponentEmptyNestedEmbeddedOwner.class
|
|
||||||
)
|
|
||||||
@SessionFactory
|
|
||||||
@ServiceRegistry(
|
|
||||||
settings = @Setting(name = Environment.CREATE_EMPTY_COMPOSITES_ENABLED, value = "true")
|
|
||||||
)
|
|
||||||
public class EmptyInitializedNestedCompositesTest {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test empty nested composite initialization.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testCompositesEmpty(SessionFactoryScope scope) {
|
|
||||||
|
|
||||||
scope.inSession(
|
|
||||||
session -> {
|
|
||||||
session.beginTransaction();
|
|
||||||
try {
|
|
||||||
ComponentEmptyNestedEmbeddedOwner owner = new ComponentEmptyNestedEmbeddedOwner();
|
|
||||||
session.persist( owner );
|
|
||||||
|
|
||||||
session.flush();
|
|
||||||
session.getTransaction().commit();
|
|
||||||
|
|
||||||
session.clear();
|
|
||||||
session.getTransaction().begin();
|
|
||||||
owner = session.get( ComponentEmptyNestedEmbeddedOwner.class, owner.getId() );
|
|
||||||
assertNotNull( owner.getEmbedded() );
|
|
||||||
assertNotNull( owner.getEmbedded().getNestedEmbedded() );
|
|
||||||
session.getTransaction().commit();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if ( session.getTransaction().isActive() ) {
|
|
||||||
session.getTransaction().rollback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "EmptyNestedOwner")
|
|
||||||
public static class ComponentEmptyNestedEmbeddedOwner {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
private EmptyNestedEmbeddedContainer embedded;
|
|
||||||
|
|
||||||
public Integer getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Integer id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EmptyNestedEmbeddedContainer getEmbedded() {
|
|
||||||
return embedded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmbedded(EmptyNestedEmbeddedContainer embedded) {
|
|
||||||
this.embedded = embedded;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Embeddable
|
|
||||||
public static class EmptyNestedEmbeddedContainer {
|
|
||||||
public ComponentEmptyEmbedded getNestedEmbedded() {
|
|
||||||
return nestedEmbedded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNestedEmbedded(ComponentEmptyEmbedded nestedEmbedded) {
|
|
||||||
this.nestedEmbedded = nestedEmbedded;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ComponentEmptyEmbedded nestedEmbedded;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,7 +17,6 @@ import jakarta.persistence.Version;
|
||||||
|
|
||||||
import org.hibernate.EmptyInterceptor;
|
import org.hibernate.EmptyInterceptor;
|
||||||
import org.hibernate.annotations.SelectBeforeUpdate;
|
import org.hibernate.annotations.SelectBeforeUpdate;
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -48,25 +47,16 @@ public class SelectBeforeUpdateEmbeddedTest extends BaseCoreFunctionalTestCase {
|
||||||
configuration.setInterceptor( i );
|
configuration.setInterceptor( i );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue(jiraKey = "HHH-11237")
|
|
||||||
public void testSelectBeforeUpdateUsingEmptyComposites() {
|
|
||||||
// Opt-in behavior 5.1+
|
|
||||||
rebuildSessionFactory( c -> c.setProperty( AvailableSettings.CREATE_EMPTY_COMPOSITES_ENABLED, "true" ) );
|
|
||||||
testSelectBeforeUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestForIssue(jiraKey = "HHH-11237")
|
@TestForIssue(jiraKey = "HHH-11237")
|
||||||
public void testSelectBeforeUpdateUsingNullComposites() {
|
public void testSelectBeforeUpdateUsingNullComposites() {
|
||||||
// Legacy behavior test
|
// Legacy behavior test
|
||||||
rebuildSessionFactory( c -> c.setProperty( AvailableSettings.CREATE_EMPTY_COMPOSITES_ENABLED, "false" ) );
|
|
||||||
testSelectBeforeUpdate();
|
testSelectBeforeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs various tests both available attached and detached entities which use
|
* Performs various tests both available attached and detached entities which use
|
||||||
* the {@code @SelectBeforeUpdate} annotation with an {code @Embedded} component.
|
* the {@code @SelectBeforeUpdate} annotation with an {@code @Embedded} component.
|
||||||
*/
|
*/
|
||||||
private void testSelectBeforeUpdate() {
|
private void testSelectBeforeUpdate() {
|
||||||
TransactionUtil.doInHibernate( this::sessionFactory, session -> {
|
TransactionUtil.doInHibernate( this::sessionFactory, session -> {
|
||||||
|
|
|
@ -1,165 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
||||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
||||||
*/
|
|
||||||
package org.hibernate.orm.test.where.annotations;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import jakarta.persistence.CascadeType;
|
|
||||||
import jakarta.persistence.ElementCollection;
|
|
||||||
import jakarta.persistence.Embeddable;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
|
|
||||||
import org.hibernate.annotations.Fetch;
|
|
||||||
import org.hibernate.annotations.FetchMode;
|
|
||||||
import org.hibernate.annotations.NotFound;
|
|
||||||
import org.hibernate.annotations.NotFoundAction;
|
|
||||||
import org.hibernate.annotations.SQLRestriction;
|
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertSame;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Gail Badner
|
|
||||||
*/
|
|
||||||
public class EagerManyToOneFetchModeSelectWhereTest extends BaseNonConfigCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addSettings(Map<String,Object> settings) {
|
|
||||||
settings.put( AvailableSettings.CREATE_EMPTY_COMPOSITES_ENABLED, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class[] getAnnotatedClasses() {
|
|
||||||
return new Class[] { Product.class, Category.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@TestForIssue( jiraKey = "HHH-12104" )
|
|
||||||
public void testAssociatedWhereClause() {
|
|
||||||
Product product = new Product();
|
|
||||||
Category category = new Category();
|
|
||||||
category.name = "flowers";
|
|
||||||
product.category = category;
|
|
||||||
product.containedCategory = new ContainedCategory();
|
|
||||||
product.containedCategory.category = category;
|
|
||||||
product.containedCategories.add( new ContainedCategory( category ) );
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
session.persist( product );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
Product p = session.get( Product.class, product.id );
|
|
||||||
assertNotNull( p );
|
|
||||||
assertNotNull( p.category );
|
|
||||||
assertNotNull( p.containedCategory.category );
|
|
||||||
assertEquals( 1, p.containedCategories.size() );
|
|
||||||
assertSame( p.category, p.containedCategory.category );
|
|
||||||
assertSame( p.category, p.containedCategories.iterator().next().category );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
Category c = session.get( Category.class, category.id );
|
|
||||||
assertNotNull( c );
|
|
||||||
c.inactive = 1;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
Category c = session.get( Category.class, category.id );
|
|
||||||
assertNull( c );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
doInHibernate(
|
|
||||||
this::sessionFactory,
|
|
||||||
session -> {
|
|
||||||
// Entity's where clause is taken into account when to-one associations
|
|
||||||
// to that entity is loaded eagerly using FetchMode.SELECT, so Category
|
|
||||||
// associations will be null.
|
|
||||||
Product p = session.get( Product.class, product.id );
|
|
||||||
assertNotNull( p );
|
|
||||||
assertNull( p.category );
|
|
||||||
assertNull( p.containedCategory.category );
|
|
||||||
assertEquals( 1, p.containedCategories.size() );
|
|
||||||
assertNull( p.containedCategories.iterator().next().category );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "Product")
|
|
||||||
public static class Product {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
private int id;
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
|
|
||||||
@NotFound(action = NotFoundAction.IGNORE)
|
|
||||||
@JoinColumn(name = "categoryId")
|
|
||||||
@Fetch(FetchMode.SELECT)
|
|
||||||
private Category category;
|
|
||||||
|
|
||||||
private ContainedCategory containedCategory;
|
|
||||||
|
|
||||||
@ElementCollection(fetch = FetchType.EAGER)
|
|
||||||
private Set<ContainedCategory> containedCategories = new HashSet<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "Category")
|
|
||||||
@Table(name = "CATEGORY")
|
|
||||||
@SQLRestriction("inactive = 0")
|
|
||||||
public static class Category {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
private int id;
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
private int inactive;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Embeddable
|
|
||||||
public static class ContainedCategory {
|
|
||||||
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
|
|
||||||
@NotFound(action = NotFoundAction.IGNORE)
|
|
||||||
@JoinColumn(name = "containedCategoryId")
|
|
||||||
@Fetch(FetchMode.SELECT)
|
|
||||||
private Category category;
|
|
||||||
|
|
||||||
public ContainedCategory() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ContainedCategory(Category category) {
|
|
||||||
this.category = category;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,11 +27,6 @@ import static org.junit.Assert.assertSame;
|
||||||
*/
|
*/
|
||||||
public class EagerManyToOneFetchModeSelectWhereTest extends BaseNonConfigCoreFunctionalTestCase {
|
public class EagerManyToOneFetchModeSelectWhereTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addSettings(Map<String,Object> settings) {
|
|
||||||
settings.put( AvailableSettings.CREATE_EMPTY_COMPOSITES_ENABLED, true );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getBaseForMappings() {
|
protected String getBaseForMappings() {
|
||||||
return "org/hibernate/orm/test/";
|
return "org/hibernate/orm/test/";
|
||||||
|
@ -99,9 +94,8 @@ public class EagerManyToOneFetchModeSelectWhereTest extends BaseNonConfigCoreFun
|
||||||
Product p = session.get( Product.class, product.id );
|
Product p = session.get( Product.class, product.id );
|
||||||
assertNotNull( p );
|
assertNotNull( p );
|
||||||
assertNull( p.category );
|
assertNull( p.category );
|
||||||
assertNull( p.containedCategory.category );
|
assertNull( p.containedCategory );
|
||||||
assertEquals( 1, p.containedCategories.size() );
|
assertEquals( 0, p.containedCategories.size() );
|
||||||
assertNull( p.containedCategories.iterator().next().category );
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue