HHH-15934 correctly handle @Basic(optional=false)
previously it had no effect
This commit is contained in:
parent
9e9a363154
commit
218ace291f
|
@ -18,6 +18,41 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import jakarta.persistence.AttributeConverter;
|
||||||
|
import jakarta.persistence.Basic;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.ElementCollection;
|
||||||
|
import jakarta.persistence.Embeddable;
|
||||||
|
import jakarta.persistence.Embedded;
|
||||||
|
import jakarta.persistence.EmbeddedId;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Inheritance;
|
||||||
|
import jakarta.persistence.InheritanceType;
|
||||||
|
import jakarta.persistence.JoinColumn;
|
||||||
|
import jakarta.persistence.JoinColumns;
|
||||||
|
import jakarta.persistence.JoinTable;
|
||||||
|
import jakarta.persistence.ManyToMany;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import jakarta.persistence.MappedSuperclass;
|
||||||
|
import jakarta.persistence.MapsId;
|
||||||
|
import jakarta.persistence.NamedNativeQueries;
|
||||||
|
import jakarta.persistence.NamedNativeQuery;
|
||||||
|
import jakarta.persistence.NamedQueries;
|
||||||
|
import jakarta.persistence.NamedQuery;
|
||||||
|
import jakarta.persistence.NamedStoredProcedureQueries;
|
||||||
|
import jakarta.persistence.NamedStoredProcedureQuery;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
import jakarta.persistence.OneToOne;
|
||||||
|
import jakarta.persistence.SequenceGenerator;
|
||||||
|
import jakarta.persistence.SequenceGenerators;
|
||||||
|
import jakarta.persistence.SqlResultSetMapping;
|
||||||
|
import jakarta.persistence.SqlResultSetMappings;
|
||||||
|
import jakarta.persistence.TableGenerator;
|
||||||
|
import jakarta.persistence.TableGenerators;
|
||||||
|
import jakarta.persistence.Version;
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
@ -112,42 +147,6 @@ import org.hibernate.usertype.UserType;
|
||||||
import org.hibernate.usertype.internal.OffsetDateTimeCompositeUserType;
|
import org.hibernate.usertype.internal.OffsetDateTimeCompositeUserType;
|
||||||
import org.hibernate.usertype.internal.ZonedDateTimeCompositeUserType;
|
import org.hibernate.usertype.internal.ZonedDateTimeCompositeUserType;
|
||||||
|
|
||||||
import jakarta.persistence.AttributeConverter;
|
|
||||||
import jakarta.persistence.Basic;
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.ElementCollection;
|
|
||||||
import jakarta.persistence.Embeddable;
|
|
||||||
import jakarta.persistence.Embedded;
|
|
||||||
import jakarta.persistence.EmbeddedId;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.Inheritance;
|
|
||||||
import jakarta.persistence.InheritanceType;
|
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.JoinColumns;
|
|
||||||
import jakarta.persistence.JoinTable;
|
|
||||||
import jakarta.persistence.ManyToMany;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import jakarta.persistence.MappedSuperclass;
|
|
||||||
import jakarta.persistence.MapsId;
|
|
||||||
import jakarta.persistence.NamedNativeQueries;
|
|
||||||
import jakarta.persistence.NamedNativeQuery;
|
|
||||||
import jakarta.persistence.NamedQueries;
|
|
||||||
import jakarta.persistence.NamedQuery;
|
|
||||||
import jakarta.persistence.NamedStoredProcedureQueries;
|
|
||||||
import jakarta.persistence.NamedStoredProcedureQuery;
|
|
||||||
import jakarta.persistence.OneToMany;
|
|
||||||
import jakarta.persistence.OneToOne;
|
|
||||||
import jakarta.persistence.SequenceGenerator;
|
|
||||||
import jakarta.persistence.SequenceGenerators;
|
|
||||||
import jakarta.persistence.SqlResultSetMapping;
|
|
||||||
import jakarta.persistence.SqlResultSetMappings;
|
|
||||||
import jakarta.persistence.TableGenerator;
|
|
||||||
import jakarta.persistence.TableGenerators;
|
|
||||||
import jakarta.persistence.Version;
|
|
||||||
|
|
||||||
import static org.hibernate.boot.model.internal.BinderHelper.getMappedSuperclassOrNull;
|
import static org.hibernate.boot.model.internal.BinderHelper.getMappedSuperclassOrNull;
|
||||||
import static org.hibernate.boot.model.internal.BinderHelper.getOverridableAnnotation;
|
import static org.hibernate.boot.model.internal.BinderHelper.getOverridableAnnotation;
|
||||||
import static org.hibernate.boot.model.internal.BinderHelper.getPath;
|
import static org.hibernate.boot.model.internal.BinderHelper.getPath;
|
||||||
|
@ -1252,7 +1251,6 @@ public final class AnnotationBinder {
|
||||||
isIdentifierMapper,
|
isIdentifierMapper,
|
||||||
context,
|
context,
|
||||||
inheritanceStatePerClass,
|
inheritanceStatePerClass,
|
||||||
property,
|
|
||||||
columnsBuilder.getColumns(),
|
columnsBuilder.getColumns(),
|
||||||
propertyBinder
|
propertyBinder
|
||||||
);
|
);
|
||||||
|
@ -1349,7 +1347,6 @@ public final class AnnotationBinder {
|
||||||
boolean isIdentifierMapper,
|
boolean isIdentifierMapper,
|
||||||
MetadataBuildingContext context,
|
MetadataBuildingContext context,
|
||||||
Map<XClass, InheritanceState> inheritanceStatePerClass,
|
Map<XClass, InheritanceState> inheritanceStatePerClass,
|
||||||
XProperty annotatedProperty,
|
|
||||||
AnnotatedColumns columns,
|
AnnotatedColumns columns,
|
||||||
PropertyBinder propertyBinder) {
|
PropertyBinder propertyBinder) {
|
||||||
checkVersionProperty( propertyHolder, isIdentifierMapper );
|
checkVersionProperty( propertyHolder, isIdentifierMapper );
|
||||||
|
@ -1565,32 +1562,12 @@ public final class AnnotationBinder {
|
||||||
AnnotatedColumns columns,
|
AnnotatedColumns columns,
|
||||||
PropertyBinder propertyBinder,
|
PropertyBinder propertyBinder,
|
||||||
boolean isOverridden) {
|
boolean isOverridden) {
|
||||||
//provide the basic property mapping
|
|
||||||
final boolean optional;
|
if ( shouldForceNotNull( nullability, propertyBinder, isOptional( property ) ) ) {
|
||||||
final boolean lazy;
|
forceColumnsNotNull( propertyHolder, inferredData, columns, propertyBinder );
|
||||||
if ( property.isAnnotationPresent( Basic.class ) ) {
|
|
||||||
final Basic basic = property.getAnnotation( Basic.class );
|
|
||||||
optional = basic.optional();
|
|
||||||
lazy = basic.fetch() == FetchType.LAZY;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
optional = true;
|
|
||||||
lazy = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//implicit type will check basic types and Serializable classes
|
propertyBinder.setLazy( BasicValueBinder.isLazy( property ) );
|
||||||
if ( propertyBinder.isId() || !optional && nullability != Nullability.FORCED_NULL ) {
|
|
||||||
//force columns to not null
|
|
||||||
for ( AnnotatedColumn column : columns.getColumns() ) {
|
|
||||||
if ( propertyBinder.isId() && column.isFormula() ) {
|
|
||||||
throw new CannotForceNonNullableException( "Identifier property '"
|
|
||||||
+ getPath( propertyHolder, inferredData ) + "' cannot map to a '@Formula'" );
|
|
||||||
}
|
|
||||||
column.forceNotNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
propertyBinder.setLazy( lazy );
|
|
||||||
propertyBinder.setColumns( columns );
|
propertyBinder.setColumns( columns );
|
||||||
if ( isOverridden ) {
|
if ( isOverridden ) {
|
||||||
final PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
|
final PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
|
||||||
|
@ -1605,6 +1582,36 @@ public final class AnnotationBinder {
|
||||||
propertyBinder.makePropertyValueAndBind();
|
propertyBinder.makePropertyValueAndBind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void forceColumnsNotNull(
|
||||||
|
PropertyHolder propertyHolder,
|
||||||
|
PropertyData inferredData,
|
||||||
|
AnnotatedColumns columns,
|
||||||
|
PropertyBinder propertyBinder) {
|
||||||
|
for ( AnnotatedColumn column : columns.getColumns() ) {
|
||||||
|
if ( propertyBinder.isId() && column.isFormula() ) {
|
||||||
|
throw new CannotForceNonNullableException( "Identifier property '"
|
||||||
|
+ getPath( propertyHolder, inferredData ) + "' cannot map to a '@Formula'" );
|
||||||
|
}
|
||||||
|
column.forceNotNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean shouldForceNotNull(Nullability nullability, PropertyBinder propertyBinder, boolean optional) {
|
||||||
|
return propertyBinder.isId()
|
||||||
|
|| !optional && nullability != Nullability.FORCED_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isOptional(XProperty property) {
|
||||||
|
if ( property.isAnnotationPresent( Basic.class ) ) {
|
||||||
|
final Basic basic = property.getAnnotation( Basic.class );
|
||||||
|
return basic.optional();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static PropertyBinder createCompositeBinder(
|
private static PropertyBinder createCompositeBinder(
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
|
|
|
@ -14,6 +14,8 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import jakarta.persistence.Basic;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
|
@ -105,6 +107,26 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
||||||
|
|
||||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, BasicValueBinder.class.getName() );
|
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, BasicValueBinder.class.getName() );
|
||||||
|
|
||||||
|
static boolean isOptional(XProperty property) {
|
||||||
|
if ( property.isAnnotationPresent( Basic.class ) ) {
|
||||||
|
final Basic basic = property.getAnnotation( Basic.class );
|
||||||
|
return basic.optional();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return property.isArray() || !property.getClassOrElementClass().isPrimitive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isLazy(XProperty property) {
|
||||||
|
if ( property.isAnnotationPresent( Basic.class ) ) {
|
||||||
|
final Basic basic = property.getAnnotation( Basic.class );
|
||||||
|
return basic.fetch() == FetchType.LAZY;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public enum Kind {
|
public enum Kind {
|
||||||
ATTRIBUTE( ValueMappingAccess.INSTANCE ),
|
ATTRIBUTE( ValueMappingAccess.INSTANCE ),
|
||||||
ANY_DISCRIMINATOR( AnyDiscriminatorMappingAccess.INSTANCE ),
|
ANY_DISCRIMINATOR( AnyDiscriminatorMappingAccess.INSTANCE ),
|
||||||
|
@ -143,7 +165,6 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
||||||
|
|
||||||
private ConverterDescriptor converterDescriptor;
|
private ConverterDescriptor converterDescriptor;
|
||||||
|
|
||||||
private boolean isVersion;
|
|
||||||
private boolean isNationalized;
|
private boolean isNationalized;
|
||||||
private boolean isLob;
|
private boolean isLob;
|
||||||
private EnumType enumType;
|
private EnumType enumType;
|
||||||
|
@ -266,7 +287,6 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
||||||
// in-flight handling
|
// in-flight handling
|
||||||
|
|
||||||
public void setVersion(boolean isVersion) {
|
public void setVersion(boolean isVersion) {
|
||||||
this.isVersion = isVersion;
|
|
||||||
if ( isVersion && basicValue != null ) {
|
if ( isVersion && basicValue != null ) {
|
||||||
basicValue.makeVersion();
|
basicValue.makeVersion();
|
||||||
}
|
}
|
||||||
|
@ -511,7 +531,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
||||||
};
|
};
|
||||||
|
|
||||||
// todo (6.0) - handle generator
|
// todo (6.0) - handle generator
|
||||||
final String generator = collectionIdAnn.generator();
|
// final String generator = collectionIdAnn.generator();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ManagedBeanRegistry getManagedBeanRegistry() {
|
private ManagedBeanRegistry getManagedBeanRegistry() {
|
||||||
|
@ -523,17 +543,9 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
||||||
private void prepareMapKey(
|
private void prepareMapKey(
|
||||||
XProperty mapAttribute,
|
XProperty mapAttribute,
|
||||||
XClass modelPropertyTypeXClass) {
|
XClass modelPropertyTypeXClass) {
|
||||||
final XClass mapKeyClass;
|
final XClass mapKeyClass = modelPropertyTypeXClass == null ? mapAttribute.getMapKey() : modelPropertyTypeXClass;
|
||||||
if ( modelPropertyTypeXClass == null ) {
|
|
||||||
mapKeyClass = mapAttribute.getMapKey();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mapKeyClass = modelPropertyTypeXClass;
|
|
||||||
}
|
|
||||||
final java.lang.reflect.Type javaType = resolveJavaType( mapKeyClass );
|
final java.lang.reflect.Type javaType = resolveJavaType( mapKeyClass );
|
||||||
final Class<Object> javaTypeClass = ReflectHelper.getClass( javaType );
|
implicitJavaTypeAccess = typeConfiguration -> javaType;
|
||||||
|
|
||||||
implicitJavaTypeAccess = (typeConfiguration) -> javaType;
|
|
||||||
|
|
||||||
final MapKeyEnumerated mapKeyEnumeratedAnn = mapAttribute.getAnnotation( MapKeyEnumerated.class );
|
final MapKeyEnumerated mapKeyEnumeratedAnn = mapAttribute.getAnnotation( MapKeyEnumerated.class );
|
||||||
if ( mapKeyEnumeratedAnn != null ) {
|
if ( mapKeyEnumeratedAnn != null ) {
|
||||||
|
@ -570,8 +582,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
|
||||||
if ( javaTypeAnn != null ) {
|
if ( javaTypeAnn != null ) {
|
||||||
final Class<? extends BasicJavaType<?>> jdbcTypeImpl = normalizeJavaType( javaTypeAnn.value() );
|
final Class<? extends BasicJavaType<?>> jdbcTypeImpl = normalizeJavaType( javaTypeAnn.value() );
|
||||||
if ( jdbcTypeImpl != null ) {
|
if ( jdbcTypeImpl != null ) {
|
||||||
final ManagedBean<? extends BasicJavaType> jdbcTypeBean = getManagedBeanRegistry().getBean( jdbcTypeImpl );
|
return getManagedBeanRegistry().getBean( jdbcTypeImpl ).getBeanInstance();
|
||||||
return jdbcTypeBean.getBeanInstance();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1629,6 +1629,7 @@ public abstract class CollectionBinder {
|
||||||
+ '_' + foreignJoinColumns.getColumns().get(0).getLogicalColumnName()
|
+ '_' + foreignJoinColumns.getColumns().get(0).getLogicalColumnName()
|
||||||
+ "Backref";
|
+ "Backref";
|
||||||
backref.setName( backrefName );
|
backref.setName( backrefName );
|
||||||
|
backref.setOptional( true );
|
||||||
backref.setUpdateable( false);
|
backref.setUpdateable( false);
|
||||||
backref.setSelectable( false );
|
backref.setSelectable( false );
|
||||||
backref.setCollectionRole( collection.getRole() );
|
backref.setCollectionRole( collection.getRole() );
|
||||||
|
|
|
@ -104,6 +104,7 @@ public class ListBinder extends CollectionBinder {
|
||||||
final PersistentClass referenced = buildingContext.getMetadataCollector().getEntityBinding( entityName );
|
final PersistentClass referenced = buildingContext.getMetadataCollector().getEntityBinding( entityName );
|
||||||
final IndexBackref backref = new IndexBackref();
|
final IndexBackref backref = new IndexBackref();
|
||||||
backref.setName( '_' + propertyName + "IndexBackref" );
|
backref.setName( '_' + propertyName + "IndexBackref" );
|
||||||
|
backref.setOptional( true );
|
||||||
backref.setUpdateable( false );
|
backref.setUpdateable( false );
|
||||||
backref.setSelectable( false );
|
backref.setSelectable( false );
|
||||||
backref.setCollectionRole( collection.getRole() );
|
backref.setCollectionRole( collection.getRole() );
|
||||||
|
|
|
@ -55,6 +55,7 @@ import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.Lob;
|
import jakarta.persistence.Lob;
|
||||||
import jakarta.persistence.Version;
|
import jakarta.persistence.Version;
|
||||||
|
|
||||||
|
import static org.hibernate.boot.model.internal.BasicValueBinder.isOptional;
|
||||||
import static org.hibernate.boot.model.internal.BinderHelper.getMappedSuperclassOrNull;
|
import static org.hibernate.boot.model.internal.BinderHelper.getMappedSuperclassOrNull;
|
||||||
import static org.hibernate.boot.model.internal.HCANNHelper.findContainingAnnotation;
|
import static org.hibernate.boot.model.internal.HCANNHelper.findContainingAnnotation;
|
||||||
import static org.hibernate.internal.util.StringHelper.qualify;
|
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||||
|
@ -324,19 +325,15 @@ public class PropertyBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<? extends EmbeddableInstantiator> resolveCustomInstantiator(XProperty property, XClass embeddableClass) {
|
private Class<? extends EmbeddableInstantiator> resolveCustomInstantiator(XProperty property, XClass embeddableClass) {
|
||||||
final org.hibernate.annotations.EmbeddableInstantiator propertyAnnotation =
|
if ( property.isAnnotationPresent( org.hibernate.annotations.EmbeddableInstantiator.class ) ) {
|
||||||
property.getAnnotation( org.hibernate.annotations.EmbeddableInstantiator.class );
|
return property.getAnnotation( org.hibernate.annotations.EmbeddableInstantiator.class ).value();
|
||||||
if ( propertyAnnotation != null ) {
|
|
||||||
return propertyAnnotation.value();
|
|
||||||
}
|
}
|
||||||
|
else if ( property.isAnnotationPresent( org.hibernate.annotations.EmbeddableInstantiator.class ) ) {
|
||||||
final org.hibernate.annotations.EmbeddableInstantiator classAnnotation =
|
return embeddableClass.getAnnotation( org.hibernate.annotations.EmbeddableInstantiator.class ).value();
|
||||||
embeddableClass.getAnnotation( org.hibernate.annotations.EmbeddableInstantiator.class );
|
}
|
||||||
if ( classAnnotation != null ) {
|
else {
|
||||||
return classAnnotation.value();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//used when the value is provided and the binding is done elsewhere
|
//used when the value is provided and the binding is done elsewhere
|
||||||
|
@ -351,48 +348,58 @@ public class PropertyBinder {
|
||||||
property.setCascade( cascade );
|
property.setCascade( cascade );
|
||||||
property.setPropertyAccessorName( accessType.getType() );
|
property.setPropertyAccessorName( accessType.getType() );
|
||||||
property.setReturnedClassName( returnedClassName );
|
property.setReturnedClassName( returnedClassName );
|
||||||
|
|
||||||
if ( this.property != null ) {
|
|
||||||
if ( entityBinder != null ) {
|
|
||||||
handleNaturalId( property );
|
|
||||||
property.setValueGeneratorCreator( getValueGenerationFromAnnotations( this.property ) );
|
|
||||||
}
|
|
||||||
// HHH-4635 -- needed for dialect-specific property ordering
|
|
||||||
property.setLob( this.property.isAnnotationPresent( Lob.class ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
property.setPropertyAccessStrategy( propertyAccessStrategy );
|
property.setPropertyAccessStrategy( propertyAccessStrategy );
|
||||||
|
handleValueGeneration( property );
|
||||||
handleImmutable( property );
|
handleNaturalId( property );
|
||||||
|
handleLob( property );
|
||||||
|
handleMutability( property );
|
||||||
|
handleOptional( property );
|
||||||
inferOptimisticLocking( property );
|
inferOptimisticLocking( property );
|
||||||
|
|
||||||
property.setInsertable( insertable );
|
|
||||||
property.setUpdateable( updatable );
|
|
||||||
|
|
||||||
LOG.tracev( "Cascading {0} with {1}", name, cascade );
|
LOG.tracev( "Cascading {0} with {1}", name, cascade );
|
||||||
|
|
||||||
return property;
|
return property;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleImmutable(Property property) {
|
private void handleValueGeneration(Property property) {
|
||||||
|
if ( this.property!=null ) {
|
||||||
|
property.setValueGeneratorCreator( getValueGenerationFromAnnotations( this.property ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleLob(Property property) {
|
||||||
|
if ( this.property != null ) {
|
||||||
|
// HHH-4635 -- needed for dialect-specific property ordering
|
||||||
|
property.setLob( this.property.isAnnotationPresent( Lob.class ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleMutability(Property property) {
|
||||||
if ( this.property != null && this.property.isAnnotationPresent( Immutable.class ) ) {
|
if ( this.property != null && this.property.isAnnotationPresent( Immutable.class ) ) {
|
||||||
updatable = false;
|
updatable = false;
|
||||||
}
|
}
|
||||||
|
property.setInsertable( insertable );
|
||||||
|
property.setUpdateable( updatable );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleOptional(Property property) {
|
||||||
|
if ( this.property != null ) {
|
||||||
|
property.setOptional( !isId && isOptional( this.property ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNaturalId(Property property) {
|
private void handleNaturalId(Property property) {
|
||||||
final NaturalId naturalId = this.property.getAnnotation(NaturalId.class);
|
if ( this.property != null && entityBinder != null ) {
|
||||||
if ( naturalId != null ) {
|
final NaturalId naturalId = this.property.getAnnotation( NaturalId.class );
|
||||||
if ( !entityBinder.isRootEntity() ) {
|
if ( naturalId != null ) {
|
||||||
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
|
if ( !entityBinder.isRootEntity() ) {
|
||||||
+ "' belongs to an entity subclass and may not be annotated '@NaturalId'" +
|
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
|
||||||
" (only a property of a root '@Entity' or a '@MappedSuperclass' may be a '@NaturalId')" );
|
+ "' belongs to an entity subclass and may not be annotated '@NaturalId'" +
|
||||||
|
" (only a property of a root '@Entity' or a '@MappedSuperclass' may be a '@NaturalId')" );
|
||||||
|
}
|
||||||
|
if ( !naturalId.mutable() ) {
|
||||||
|
updatable = false;
|
||||||
|
}
|
||||||
|
property.setNaturalIdentifier( true );
|
||||||
}
|
}
|
||||||
if ( !naturalId.mutable() ) {
|
|
||||||
updatable = false;
|
|
||||||
}
|
|
||||||
property.setNaturalIdentifier( true );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,8 +408,8 @@ public class PropertyBinder {
|
||||||
if ( value instanceof Collection ) {
|
if ( value instanceof Collection ) {
|
||||||
property.setOptimisticLocked( ((Collection) value).isOptimisticLocked() );
|
property.setOptimisticLocked( ((Collection) value).isOptimisticLocked() );
|
||||||
}
|
}
|
||||||
else if ( this.property != null && this.property.isAnnotationPresent(OptimisticLock.class) ) {
|
else if ( this.property != null && this.property.isAnnotationPresent( OptimisticLock.class ) ) {
|
||||||
final OptimisticLock optimisticLock = this.property.getAnnotation(OptimisticLock.class);
|
final OptimisticLock optimisticLock = this.property.getAnnotation( OptimisticLock.class );
|
||||||
validateOptimisticLock( optimisticLock );
|
validateOptimisticLock( optimisticLock );
|
||||||
property.setOptimisticLocked( !optimisticLock.excluded() );
|
property.setOptimisticLocked( !optimisticLock.excluded() );
|
||||||
}
|
}
|
||||||
|
@ -413,15 +420,15 @@ public class PropertyBinder {
|
||||||
|
|
||||||
private void validateOptimisticLock(OptimisticLock optimisticLock) {
|
private void validateOptimisticLock(OptimisticLock optimisticLock) {
|
||||||
if ( optimisticLock.excluded() ) {
|
if ( optimisticLock.excluded() ) {
|
||||||
if ( property.isAnnotationPresent(Version.class) ) {
|
if ( property.isAnnotationPresent( Version.class ) ) {
|
||||||
throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
|
throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
|
||||||
+ "' is annotated '@OptimisticLock(excluded=true)' and '@Version'" );
|
+ "' is annotated '@OptimisticLock(excluded=true)' and '@Version'" );
|
||||||
}
|
}
|
||||||
if ( property.isAnnotationPresent(Id.class) ) {
|
if ( property.isAnnotationPresent( Id.class ) ) {
|
||||||
throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
|
throw new AnnotationException("Property '" + qualify( holder.getPath(), name )
|
||||||
+ "' is annotated '@OptimisticLock(excluded=true)' and '@Id'" );
|
+ "' is annotated '@OptimisticLock(excluded=true)' and '@Id'" );
|
||||||
}
|
}
|
||||||
if ( property.isAnnotationPresent(EmbeddedId.class) ) {
|
if ( property.isAnnotationPresent( EmbeddedId.class ) ) {
|
||||||
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
|
throw new AnnotationException( "Property '" + qualify( holder.getPath(), name )
|
||||||
+ "' is annotated '@OptimisticLock(excluded=true)' and '@EmbeddedId'" );
|
+ "' is annotated '@OptimisticLock(excluded=true)' and '@EmbeddedId'" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,11 +94,10 @@ public class ToOneBinder {
|
||||||
joinColumn.setExplicitTableName( join.getTable().getName() );
|
joinColumn.setExplicitTableName( join.getTable().getName() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final boolean mandatory = isMandatory( manyToOne.optional(), property, notFoundAction );
|
|
||||||
bindManyToOne(
|
bindManyToOne(
|
||||||
getCascadeStrategy( manyToOne.cascade(), hibernateCascade, false, forcePersist ),
|
getCascadeStrategy( manyToOne.cascade(), hibernateCascade, false, forcePersist ),
|
||||||
joinColumns,
|
joinColumns,
|
||||||
!mandatory,
|
!isMandatory( manyToOne.optional(), property, notFoundAction ),
|
||||||
notFoundAction,
|
notFoundAction,
|
||||||
onDelete == null ? null : onDelete.action(),
|
onDelete == null ? null : onDelete.action(),
|
||||||
getTargetEntity( inferredData, context ),
|
getTargetEntity( inferredData, context ),
|
||||||
|
|
|
@ -1090,6 +1090,7 @@ public class ModelBinder {
|
||||||
(PluralAttributeSource) attributeSource,
|
(PluralAttributeSource) attributeSource,
|
||||||
entityDescriptor
|
entityDescriptor
|
||||||
);
|
);
|
||||||
|
attribute.setOptional( true );
|
||||||
entityDescriptor.addProperty( attribute );
|
entityDescriptor.addProperty( attribute );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1116,9 +1117,7 @@ public class ModelBinder {
|
||||||
entityDescriptor.getClassName()
|
entityDescriptor.getClassName()
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( secondaryTableJoin != null ) {
|
attribute.setOptional( isOptional( secondaryTableJoin, attribute ) );
|
||||||
attribute.setOptional( secondaryTableJoin.isOptional() );
|
|
||||||
}
|
|
||||||
|
|
||||||
attributeContainer.addProperty( attribute );
|
attributeContainer.addProperty( attribute );
|
||||||
|
|
||||||
|
@ -1151,9 +1150,7 @@ public class ModelBinder {
|
||||||
entityDescriptor.getClassName()
|
entityDescriptor.getClassName()
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( secondaryTableJoin != null ) {
|
attribute.setOptional( isOptional( secondaryTableJoin, attribute ) );
|
||||||
attribute.setOptional( secondaryTableJoin.isOptional() );
|
|
||||||
}
|
|
||||||
|
|
||||||
attributeContainer.addProperty( attribute );
|
attributeContainer.addProperty( attribute );
|
||||||
|
|
||||||
|
@ -1186,9 +1183,7 @@ public class ModelBinder {
|
||||||
entityDescriptor.getClassName()
|
entityDescriptor.getClassName()
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( secondaryTableJoin != null ) {
|
attribute.setOptional( isOptional( secondaryTableJoin, attribute ) );
|
||||||
attribute.setOptional( secondaryTableJoin.isOptional() );
|
|
||||||
}
|
|
||||||
|
|
||||||
attributeContainer.addProperty( attribute );
|
attributeContainer.addProperty( attribute );
|
||||||
|
|
||||||
|
@ -1208,6 +1203,9 @@ public class ModelBinder {
|
||||||
new OneToOne( mappingDocument, table, entityDescriptor ),
|
new OneToOne( mappingDocument, table, entityDescriptor ),
|
||||||
entityDescriptor.getClassName()
|
entityDescriptor.getClassName()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
attribute.setOptional( attribute.getValue().isNullable() );
|
||||||
|
|
||||||
entityDescriptor.addProperty( attribute );
|
entityDescriptor.addProperty( attribute );
|
||||||
|
|
||||||
handleNaturalIdBinding(
|
handleNaturalIdBinding(
|
||||||
|
@ -1243,9 +1241,7 @@ public class ModelBinder {
|
||||||
entityDescriptor.getEntityName()
|
entityDescriptor.getEntityName()
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( secondaryTableJoin != null ) {
|
attribute.setOptional( isOptional( secondaryTableJoin, attribute ) );
|
||||||
attribute.setOptional( secondaryTableJoin.isOptional() );
|
|
||||||
}
|
|
||||||
|
|
||||||
attributeContainer.addProperty( attribute );
|
attributeContainer.addProperty( attribute );
|
||||||
|
|
||||||
|
@ -1260,6 +1256,11 @@ public class ModelBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isOptional(Join secondaryTableJoin, Property attribute) {
|
||||||
|
return secondaryTableJoin != null && secondaryTableJoin.isOptional()
|
||||||
|
|| attribute.getValue().isNullable();
|
||||||
|
}
|
||||||
|
|
||||||
private void handleNaturalIdBinding(
|
private void handleNaturalIdBinding(
|
||||||
MappingDocument mappingDocument,
|
MappingDocument mappingDocument,
|
||||||
PersistentClass entityBinding,
|
PersistentClass entityBinding,
|
||||||
|
@ -2785,6 +2786,8 @@ public class ModelBinder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attribute.setOptional( attribute.getValue().isNullable() );
|
||||||
|
|
||||||
component.addProperty( attribute );
|
component.addProperty( attribute );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3286,19 +3289,20 @@ public class ModelBinder {
|
||||||
// for non-inverse one-to-many, with a not-null fk, add a backref!
|
// for non-inverse one-to-many, with a not-null fk, add a backref!
|
||||||
final String entityName = ( (OneToMany) collectionBinding.getElement() ).getReferencedEntityName();
|
final String entityName = ( (OneToMany) collectionBinding.getElement() ).getReferencedEntityName();
|
||||||
final PersistentClass referenced = getReferencedEntityBinding( entityName );
|
final PersistentClass referenced = getReferencedEntityBinding( entityName );
|
||||||
final Backref prop = new Backref();
|
final Backref backref = new Backref();
|
||||||
prop.setName( '_' + collectionBinding.getOwnerEntityName() + "." + pluralAttributeSource.getName() + "Backref" );
|
backref.setName( '_' + collectionBinding.getOwnerEntityName() + "." + pluralAttributeSource.getName() + "Backref" );
|
||||||
prop.setUpdateable( false );
|
backref.setOptional( true );
|
||||||
prop.setSelectable( false );
|
backref.setUpdateable( false );
|
||||||
prop.setCollectionRole( collectionBinding.getRole() );
|
backref.setSelectable( false );
|
||||||
prop.setEntityName( collectionBinding.getOwner().getEntityName() );
|
backref.setCollectionRole( collectionBinding.getRole() );
|
||||||
prop.setValue( collectionBinding.getKey() );
|
backref.setEntityName( collectionBinding.getOwner().getEntityName() );
|
||||||
referenced.addProperty( prop );
|
backref.setValue( collectionBinding.getKey() );
|
||||||
|
referenced.addProperty( backref );
|
||||||
|
|
||||||
if ( log.isDebugEnabled() ) {
|
if ( log.isDebugEnabled() ) {
|
||||||
log.debugf(
|
log.debugf(
|
||||||
"Added virtual backref property [%s] : %s",
|
"Added virtual backref property [%s] : %s",
|
||||||
prop.getName(),
|
backref.getName(),
|
||||||
pluralAttributeSource.getAttributeRole().getFullPath()
|
pluralAttributeSource.getAttributeRole().getFullPath()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3748,14 +3752,15 @@ public class ModelBinder {
|
||||||
&& !indexIsFormula ) {
|
&& !indexIsFormula ) {
|
||||||
final String entityName = ( (OneToMany) getCollectionBinding().getElement() ).getReferencedEntityName();
|
final String entityName = ( (OneToMany) getCollectionBinding().getElement() ).getReferencedEntityName();
|
||||||
final PersistentClass referenced = getMappingDocument().getMetadataCollector().getEntityBinding( entityName );
|
final PersistentClass referenced = getMappingDocument().getMetadataCollector().getEntityBinding( entityName );
|
||||||
final IndexBackref ib = new IndexBackref();
|
final IndexBackref backref = new IndexBackref();
|
||||||
ib.setName( '_' + getCollectionBinding().getOwnerEntityName() + "." + getPluralAttributeSource().getName() + "IndexBackref" );
|
backref.setName( '_' + getCollectionBinding().getOwnerEntityName() + "." + getPluralAttributeSource().getName() + "IndexBackref" );
|
||||||
ib.setUpdateable( false );
|
backref.setOptional( true );
|
||||||
ib.setSelectable( false );
|
backref.setUpdateable( false );
|
||||||
ib.setCollectionRole( getCollectionBinding().getRole() );
|
backref.setSelectable( false );
|
||||||
ib.setEntityName( getCollectionBinding().getOwner().getEntityName() );
|
backref.setCollectionRole( getCollectionBinding().getRole() );
|
||||||
ib.setValue( getCollectionBinding().getIndex() );
|
backref.setEntityName( getCollectionBinding().getOwner().getEntityName() );
|
||||||
referenced.addProperty( ib );
|
backref.setValue( getCollectionBinding().getIndex() );
|
||||||
|
referenced.addProperty( backref );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3826,14 +3831,15 @@ public class ModelBinder {
|
||||||
&& !collectionBinding.isInverse() ) {
|
&& !collectionBinding.isInverse() ) {
|
||||||
final String entityName = ( (OneToMany) collectionBinding.getElement() ).getReferencedEntityName();
|
final String entityName = ( (OneToMany) collectionBinding.getElement() ).getReferencedEntityName();
|
||||||
final PersistentClass referenced = mappingDocument.getMetadataCollector().getEntityBinding( entityName );
|
final PersistentClass referenced = mappingDocument.getMetadataCollector().getEntityBinding( entityName );
|
||||||
final IndexBackref ib = new IndexBackref();
|
final IndexBackref backref = new IndexBackref();
|
||||||
ib.setName( '_' + collectionBinding.getOwnerEntityName() + "." + pluralAttributeSource.getName() + "IndexBackref" );
|
backref.setName( '_' + collectionBinding.getOwnerEntityName() + "." + pluralAttributeSource.getName() + "IndexBackref" );
|
||||||
ib.setUpdateable( false );
|
backref.setOptional( true );
|
||||||
ib.setSelectable( false );
|
backref.setUpdateable( false );
|
||||||
ib.setCollectionRole( collectionBinding.getRole() );
|
backref.setSelectable( false );
|
||||||
ib.setEntityName( collectionBinding.getOwner().getEntityName() );
|
backref.setCollectionRole( collectionBinding.getRole() );
|
||||||
ib.setValue( collectionBinding.getIndex() );
|
backref.setEntityName( collectionBinding.getOwner().getEntityName() );
|
||||||
referenced.addProperty( ib );
|
backref.setValue( collectionBinding.getIndex() );
|
||||||
|
referenced.addProperty( backref );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,6 @@ package org.hibernate.loader.ast.internal;
|
||||||
|
|
||||||
import java.util.AbstractMap;
|
import java.util.AbstractMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -31,7 +29,6 @@ import org.hibernate.graph.GraphSemantic;
|
||||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||||
import org.hibernate.loader.ast.spi.Loadable;
|
import org.hibernate.loader.ast.spi.Loadable;
|
||||||
import org.hibernate.loader.ast.spi.Loader;
|
import org.hibernate.loader.ast.spi.Loader;
|
||||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
|
||||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
|
@ -56,7 +53,6 @@ import org.hibernate.sql.ast.spi.SimpleFromClauseAccessImpl;
|
||||||
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
|
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||||
import org.hibernate.sql.ast.spi.SqlAstQueryPartProcessingState;
|
|
||||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
@ -89,8 +85,8 @@ import org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
import static org.hibernate.query.results.ResultsHelper.attributeName;
|
import static org.hibernate.query.results.ResultsHelper.attributeName;
|
||||||
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder for SQL AST trees used by {@link Loader} implementations.
|
* Builder for SQL AST trees used by {@link Loader} implementations.
|
||||||
|
@ -128,7 +124,7 @@ public class LoaderSelectBuilder {
|
||||||
sessionFactory,
|
sessionFactory,
|
||||||
loadable,
|
loadable,
|
||||||
partsToSelect,
|
partsToSelect,
|
||||||
Collections.singletonList( restrictedPart ),
|
singletonList( restrictedPart ),
|
||||||
cachedDomainResult,
|
cachedDomainResult,
|
||||||
numberOfKeysToLoad,
|
numberOfKeysToLoad,
|
||||||
loadQueryInfluencers,
|
loadQueryInfluencers,
|
||||||
|
@ -220,7 +216,7 @@ public class LoaderSelectBuilder {
|
||||||
public static SelectStatement createSubSelectFetchSelect(
|
public static SelectStatement createSubSelectFetchSelect(
|
||||||
PluralAttributeMapping attributeMapping,
|
PluralAttributeMapping attributeMapping,
|
||||||
SubselectFetch subselect,
|
SubselectFetch subselect,
|
||||||
DomainResult cachedDomainResult,
|
DomainResult<?> cachedDomainResult,
|
||||||
LoadQueryInfluencers loadQueryInfluencers,
|
LoadQueryInfluencers loadQueryInfluencers,
|
||||||
LockOptions lockOptions,
|
LockOptions lockOptions,
|
||||||
Consumer<JdbcParameter> jdbcParameterConsumer,
|
Consumer<JdbcParameter> jdbcParameterConsumer,
|
||||||
|
@ -244,7 +240,7 @@ public class LoaderSelectBuilder {
|
||||||
private final Loadable loadable;
|
private final Loadable loadable;
|
||||||
private final List<? extends ModelPart> partsToSelect;
|
private final List<? extends ModelPart> partsToSelect;
|
||||||
private final List<ModelPart> restrictedParts;
|
private final List<ModelPart> restrictedParts;
|
||||||
private final DomainResult cachedDomainResult;
|
private final DomainResult<?> cachedDomainResult;
|
||||||
private final int numberOfKeysToLoad;
|
private final int numberOfKeysToLoad;
|
||||||
private final boolean forceIdentifierSelection;
|
private final boolean forceIdentifierSelection;
|
||||||
private final LoadQueryInfluencers loadQueryInfluencers;
|
private final LoadQueryInfluencers loadQueryInfluencers;
|
||||||
|
@ -262,7 +258,7 @@ public class LoaderSelectBuilder {
|
||||||
Loadable loadable,
|
Loadable loadable,
|
||||||
List<? extends ModelPart> partsToSelect,
|
List<? extends ModelPart> partsToSelect,
|
||||||
List<ModelPart> restrictedParts,
|
List<ModelPart> restrictedParts,
|
||||||
DomainResult cachedDomainResult,
|
DomainResult<?> cachedDomainResult,
|
||||||
int numberOfKeysToLoad,
|
int numberOfKeysToLoad,
|
||||||
LoadQueryInfluencers loadQueryInfluencers,
|
LoadQueryInfluencers loadQueryInfluencers,
|
||||||
LockOptions lockOptions,
|
LockOptions lockOptions,
|
||||||
|
@ -287,7 +283,7 @@ public class LoaderSelectBuilder {
|
||||||
Loadable loadable,
|
Loadable loadable,
|
||||||
List<? extends ModelPart> partsToSelect,
|
List<? extends ModelPart> partsToSelect,
|
||||||
List<ModelPart> restrictedParts,
|
List<ModelPart> restrictedParts,
|
||||||
DomainResult cachedDomainResult,
|
DomainResult<?> cachedDomainResult,
|
||||||
int numberOfKeysToLoad,
|
int numberOfKeysToLoad,
|
||||||
LoadQueryInfluencers loadQueryInfluencers,
|
LoadQueryInfluencers loadQueryInfluencers,
|
||||||
LockOptions lockOptions,
|
LockOptions lockOptions,
|
||||||
|
@ -312,7 +308,7 @@ public class LoaderSelectBuilder {
|
||||||
Loadable loadable,
|
Loadable loadable,
|
||||||
List<? extends ModelPart> partsToSelect,
|
List<? extends ModelPart> partsToSelect,
|
||||||
ModelPart restrictedPart,
|
ModelPart restrictedPart,
|
||||||
DomainResult cachedDomainResult,
|
DomainResult<?> cachedDomainResult,
|
||||||
int numberOfKeysToLoad,
|
int numberOfKeysToLoad,
|
||||||
LoadQueryInfluencers loadQueryInfluencers,
|
LoadQueryInfluencers loadQueryInfluencers,
|
||||||
LockOptions lockOptions,
|
LockOptions lockOptions,
|
||||||
|
@ -321,7 +317,7 @@ public class LoaderSelectBuilder {
|
||||||
creationContext,
|
creationContext,
|
||||||
loadable,
|
loadable,
|
||||||
partsToSelect,
|
partsToSelect,
|
||||||
Arrays.asList( restrictedPart ),
|
singletonList( restrictedPart ),
|
||||||
cachedDomainResult,
|
cachedDomainResult,
|
||||||
numberOfKeysToLoad,
|
numberOfKeysToLoad,
|
||||||
loadQueryInfluencers,
|
loadQueryInfluencers,
|
||||||
|
@ -356,7 +352,7 @@ public class LoaderSelectBuilder {
|
||||||
final EffectiveEntityGraph effectiveEntityGraph = loadQueryInfluencers.getEffectiveEntityGraph();
|
final EffectiveEntityGraph effectiveEntityGraph = loadQueryInfluencers.getEffectiveEntityGraph();
|
||||||
if ( effectiveEntityGraph != null ) {
|
if ( effectiveEntityGraph != null ) {
|
||||||
final GraphSemantic graphSemantic = effectiveEntityGraph.getSemantic();
|
final GraphSemantic graphSemantic = effectiveEntityGraph.getSemantic();
|
||||||
final RootGraphImplementor rootGraphImplementor = effectiveEntityGraph.getGraph();
|
final RootGraphImplementor<?> rootGraphImplementor = effectiveEntityGraph.getGraph();
|
||||||
if ( graphSemantic != null && rootGraphImplementor != null ) {
|
if ( graphSemantic != null && rootGraphImplementor != null ) {
|
||||||
return new StandardEntityGraphTraversalStateImpl( graphSemantic, rootGraphImplementor );
|
return new StandardEntityGraphTraversalStateImpl( graphSemantic, rootGraphImplementor );
|
||||||
}
|
}
|
||||||
|
@ -458,7 +454,7 @@ public class LoaderSelectBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
domainResults = Collections.singletonList( domainResult );
|
domainResults = singletonList( domainResult );
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( ModelPart restrictedPart : restrictedParts ) {
|
for ( ModelPart restrictedPart : restrictedParts ) {
|
||||||
|
@ -655,11 +651,7 @@ public class LoaderSelectBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
final ImmutableFetchList.Builder fetches = new ImmutableFetchList.Builder( fetchParent.getReferencedMappingContainer() );
|
final ImmutableFetchList.Builder fetches = new ImmutableFetchList.Builder( fetchParent.getReferencedMappingContainer() );
|
||||||
final BiConsumer<Fetchable, Boolean> processor = createFetchableBiConsumer(
|
final BiConsumer<Fetchable, Boolean> processor = createFetchableBiConsumer( fetchParent, creationState, fetches );
|
||||||
fetchParent,
|
|
||||||
creationState,
|
|
||||||
fetches
|
|
||||||
);
|
|
||||||
|
|
||||||
final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer();
|
final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer();
|
||||||
if ( fetchParent.getNavigablePath().getParent() != null ) {
|
if ( fetchParent.getNavigablePath().getParent() != null ) {
|
||||||
|
@ -759,7 +751,7 @@ public class LoaderSelectBuilder {
|
||||||
else if ( loadQueryInfluencers.getEnabledCascadingFetchProfile() != null ) {
|
else if ( loadQueryInfluencers.getEnabledCascadingFetchProfile() != null ) {
|
||||||
final CascadeStyle cascadeStyle = fetchable.asAttributeMapping().getAttributeMetadata()
|
final CascadeStyle cascadeStyle = fetchable.asAttributeMapping().getAttributeMetadata()
|
||||||
.getCascadeStyle();
|
.getCascadeStyle();
|
||||||
final CascadingAction cascadingAction = loadQueryInfluencers.getEnabledCascadingFetchProfile()
|
final CascadingAction<?> cascadingAction = loadQueryInfluencers.getEnabledCascadingFetchProfile()
|
||||||
.getCascadingAction();
|
.getCascadingAction();
|
||||||
if ( cascadeStyle == null || cascadeStyle.doCascade( cascadingAction ) ) {
|
if ( cascadeStyle == null || cascadeStyle.doCascade( cascadingAction ) ) {
|
||||||
fetchTiming = FetchTiming.IMMEDIATE;
|
fetchTiming = FetchTiming.IMMEDIATE;
|
||||||
|
@ -853,7 +845,6 @@ public class LoaderSelectBuilder {
|
||||||
creationState
|
creationState
|
||||||
);
|
);
|
||||||
applyOrdering(
|
applyOrdering(
|
||||||
querySpec,
|
|
||||||
fetchablePath,
|
fetchablePath,
|
||||||
pluralAttributeMapping,
|
pluralAttributeMapping,
|
||||||
creationState
|
creationState
|
||||||
|
@ -901,7 +892,6 @@ public class LoaderSelectBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyOrdering(
|
private void applyOrdering(
|
||||||
QuerySpec ast,
|
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
PluralAttributeMapping pluralAttributeMapping,
|
PluralAttributeMapping pluralAttributeMapping,
|
||||||
LoaderSqlAstCreationState sqlAstCreationState) {
|
LoaderSqlAstCreationState sqlAstCreationState) {
|
||||||
|
@ -988,7 +978,7 @@ public class LoaderSelectBuilder {
|
||||||
|
|
||||||
return new SelectStatement(
|
return new SelectStatement(
|
||||||
rootQuerySpec,
|
rootQuerySpec,
|
||||||
List.of(
|
singletonList(
|
||||||
new CollectionDomainResult(
|
new CollectionDomainResult(
|
||||||
rootNavigablePath,
|
rootNavigablePath,
|
||||||
attributeMapping,
|
attributeMapping,
|
||||||
|
@ -1006,9 +996,6 @@ public class LoaderSelectBuilder {
|
||||||
TableGroup rootTableGroup,
|
TableGroup rootTableGroup,
|
||||||
SubselectFetch subselect,
|
SubselectFetch subselect,
|
||||||
LoaderSqlAstCreationState sqlAstCreationState) {
|
LoaderSqlAstCreationState sqlAstCreationState) {
|
||||||
final SqlAstCreationContext sqlAstCreationContext = sqlAstCreationState.getCreationContext();
|
|
||||||
final SessionFactoryImplementor sessionFactory = sqlAstCreationContext.getSessionFactory();
|
|
||||||
|
|
||||||
assert loadable instanceof PluralAttributeMapping;
|
assert loadable instanceof PluralAttributeMapping;
|
||||||
|
|
||||||
final PluralAttributeMapping attributeMapping = (PluralAttributeMapping) loadable;
|
final PluralAttributeMapping attributeMapping = (PluralAttributeMapping) loadable;
|
||||||
|
@ -1053,11 +1040,8 @@ public class LoaderSelectBuilder {
|
||||||
fkExpression,
|
fkExpression,
|
||||||
generateSubSelect(
|
generateSubSelect(
|
||||||
attributeMapping,
|
attributeMapping,
|
||||||
rootTableGroup,
|
|
||||||
subselect,
|
subselect,
|
||||||
jdbcTypeCount,
|
sqlAstCreationState
|
||||||
sqlAstCreationState,
|
|
||||||
sessionFactory
|
|
||||||
),
|
),
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
@ -1066,11 +1050,8 @@ public class LoaderSelectBuilder {
|
||||||
|
|
||||||
private QueryPart generateSubSelect(
|
private QueryPart generateSubSelect(
|
||||||
PluralAttributeMapping attributeMapping,
|
PluralAttributeMapping attributeMapping,
|
||||||
TableGroup rootTableGroup,
|
|
||||||
SubselectFetch subselect,
|
SubselectFetch subselect,
|
||||||
int jdbcTypeCount,
|
LoaderSqlAstCreationState creationState) {
|
||||||
LoaderSqlAstCreationState creationState,
|
|
||||||
SessionFactoryImplementor sessionFactory) {
|
|
||||||
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();
|
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();
|
||||||
|
|
||||||
final QuerySpec subQuery = new QuerySpec( false );
|
final QuerySpec subQuery = new QuerySpec( false );
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
package org.hibernate.loader.ast.internal;
|
package org.hibernate.loader.ast.internal;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.query.spi.QueryParameterBindings;
|
|
||||||
import org.hibernate.sql.exec.internal.BaseExecutionContext;
|
import org.hibernate.sql.exec.internal.BaseExecutionContext;
|
||||||
import org.hibernate.sql.exec.spi.Callback;
|
import org.hibernate.sql.exec.spi.Callback;
|
||||||
|
|
||||||
|
@ -19,7 +18,8 @@ public class NoCallbackExecutionContext extends BaseExecutionContext {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Callback getCallback() {
|
public Callback getCallback() {
|
||||||
throw new UnsupportedOperationException( "Follow-on locking not supported yet" );
|
return null;
|
||||||
|
// throw new UnsupportedOperationException( "Follow-on locking not supported yet" );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import java.util.StringTokenizer;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.Internal;
|
import org.hibernate.Internal;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.PropertyNotFoundException;
|
|
||||||
import org.hibernate.boot.model.relational.Database;
|
import org.hibernate.boot.model.relational.Database;
|
||||||
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
|
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
|
||||||
import org.hibernate.engine.spi.CascadeStyle;
|
import org.hibernate.engine.spi.CascadeStyle;
|
||||||
|
@ -138,12 +137,16 @@ public class Property implements Serializable, MetaAttributable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPrimitive(Class clazz) {
|
/**
|
||||||
return getGetter(clazz).getReturnTypeClass().isPrimitive();
|
* @deprecated this method is no longer used
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "6", forRemoval = true)
|
||||||
|
public boolean isPrimitive(Class<?> clazz) {
|
||||||
|
return getGetter( clazz ).getReturnTypeClass().isPrimitive();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CascadeStyle getCascadeStyle() throws MappingException {
|
public CascadeStyle getCascadeStyle() throws MappingException {
|
||||||
Type type = value.getType();
|
final Type type = value.getType();
|
||||||
if ( type.isComponentType() ) {
|
if ( type.isComponentType() ) {
|
||||||
return getCompositeCascadeStyle( (CompositeType) type, cascade );
|
return getCompositeCascadeStyle( (CompositeType) type, cascade );
|
||||||
}
|
}
|
||||||
|
@ -292,28 +295,27 @@ public class Property implements Serializable, MetaAttributable {
|
||||||
/**
|
/**
|
||||||
* Is this property lazy in the "bytecode" sense?
|
* Is this property lazy in the "bytecode" sense?
|
||||||
* <p>
|
* <p>
|
||||||
* Lazy here means whether we should push *something* to the entity
|
* Lazy here means whether we initialize this field of the entity
|
||||||
* instance for this field in its "base fetch group". Mainly it affects
|
* instance in its "base fetch group". It affects whether we list
|
||||||
* whether we should list this property's columns in the SQL select
|
* this property's columns in the SQL select for the owning entity
|
||||||
* for the owning entity when we load its "base fetch group".
|
* when we load its "base fetch group". The actual value that is set
|
||||||
* <p>
|
* varies based on the nature (basic, etc) of the property.
|
||||||
* The "something" we push varies based on the nature (basic, etc) of
|
|
||||||
* the property.
|
|
||||||
*
|
*
|
||||||
* @apiNote This form reports whether the property is considered part of the
|
* @apiNote This method reports whether the property is considered
|
||||||
* base fetch group based solely on the mapping information. However,
|
* part of the base fetch group based solely on the information in
|
||||||
* {@link EnhancementHelper#includeInBaseFetchGroup} is used internally to make that
|
* the mapping but {@link EnhancementHelper#includeInBaseFetchGroup}
|
||||||
* decision to account for other details
|
* is also accounts for other details.
|
||||||
*/
|
*/
|
||||||
public boolean isLazy() {
|
public boolean isLazy() {
|
||||||
if ( value instanceof ToOne ) {
|
if ( value instanceof ToOne ) {
|
||||||
// For a many-to-one, this is always false. Whether the
|
// For a many-to-one, this is always false. Whether the
|
||||||
// association is EAGER, PROXY or NO-PROXY we want the fk
|
// association is EAGER, PROXY or NO-PROXY we always want
|
||||||
// selected
|
// to select the foreign key
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
return lazy;
|
return lazy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLazyGroup() {
|
public String getLazyGroup() {
|
||||||
|
@ -333,7 +335,7 @@ public class Property implements Serializable, MetaAttributable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOptional() {
|
public boolean isOptional() {
|
||||||
return optional || isNullable();
|
return optional;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOptional(boolean optional) {
|
public void setOptional(boolean optional) {
|
||||||
|
@ -361,12 +363,12 @@ public class Property implements Serializable, MetaAttributable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo : remove
|
// todo : remove
|
||||||
public Getter getGetter(Class clazz) throws PropertyNotFoundException, MappingException {
|
public Getter getGetter(Class clazz) throws MappingException {
|
||||||
return getPropertyAccessStrategy( clazz ).buildPropertyAccess( clazz, name, true ).getGetter();
|
return getPropertyAccessStrategy( clazz ).buildPropertyAccess( clazz, name, true ).getGetter();
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo : remove
|
// todo : remove
|
||||||
public Setter getSetter(Class clazz) throws PropertyNotFoundException, MappingException {
|
public Setter getSetter(Class clazz) throws MappingException {
|
||||||
return getPropertyAccessStrategy( clazz ).buildPropertyAccess( clazz, name, true ).getSetter();
|
return getPropertyAccessStrategy( clazz ).buildPropertyAccess( clazz, name, true ).getSetter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,27 +456,27 @@ public class Property implements Serializable, MetaAttributable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Property copy() {
|
public Property copy() {
|
||||||
final Property prop = new Property();
|
final Property property = new Property();
|
||||||
prop.setName( getName() );
|
property.setName( getName() );
|
||||||
prop.setValue( getValue() );
|
property.setValue( getValue() );
|
||||||
prop.setCascade( getCascade() );
|
property.setCascade( getCascade() );
|
||||||
prop.setUpdateable( isUpdateable() );
|
property.setUpdateable( isUpdateable() );
|
||||||
prop.setInsertable( isInsertable() );
|
property.setInsertable( isInsertable() );
|
||||||
prop.setSelectable( isSelectable() );
|
property.setSelectable( isSelectable() );
|
||||||
prop.setOptimisticLocked( isOptimisticLocked() );
|
property.setOptimisticLocked( isOptimisticLocked() );
|
||||||
prop.setValueGeneratorCreator( getValueGeneratorCreator() );
|
property.setValueGeneratorCreator( getValueGeneratorCreator() );
|
||||||
prop.setPropertyAccessorName( getPropertyAccessorName() );
|
property.setPropertyAccessorName( getPropertyAccessorName() );
|
||||||
prop.setPropertyAccessStrategy( getPropertyAccessStrategy() );
|
property.setPropertyAccessStrategy( getPropertyAccessStrategy() );
|
||||||
prop.setLazy( isLazy() );
|
property.setLazy( isLazy() );
|
||||||
prop.setLazyGroup( getLazyGroup() );
|
property.setLazyGroup( getLazyGroup() );
|
||||||
prop.setOptional( isOptional() );
|
property.setOptional( isOptional() );
|
||||||
prop.setMetaAttributes( getMetaAttributes() );
|
property.setMetaAttributes( getMetaAttributes() );
|
||||||
prop.setPersistentClass( getPersistentClass() );
|
property.setPersistentClass( getPersistentClass() );
|
||||||
prop.setNaturalIdentifier( isNaturalIdentifier() );
|
property.setNaturalIdentifier( isNaturalIdentifier() );
|
||||||
prop.setLob( isLob() );
|
property.setLob( isLob() );
|
||||||
prop.addCallbackDefinitions( getCallbackDefinitions() );
|
property.addCallbackDefinitions( getCallbackDefinitions() );
|
||||||
prop.setReturnedClassName( getReturnedClassName() );
|
property.setReturnedClassName( getReturnedClassName() );
|
||||||
return prop;
|
return property;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PropertyGeneratorCreationContext implements GeneratorCreationContext {
|
private class PropertyGeneratorCreationContext implements GeneratorCreationContext {
|
||||||
|
|
|
@ -554,7 +554,7 @@ public abstract class AbstractEntityPersister
|
||||||
throw new IllegalArgumentException( "Could not resolve named load-query [" + getEntityName()
|
throw new IllegalArgumentException( "Could not resolve named load-query [" + getEntityName()
|
||||||
+ "] : " + bootDescriptor.getLoaderName() );
|
+ "] : " + bootDescriptor.getLoaderName() );
|
||||||
}
|
}
|
||||||
singleIdEntityLoader = new SingleIdEntityLoaderProvidedQueryImpl<>(this, namedQueryMemento );
|
singleIdEntityLoader = new SingleIdEntityLoaderProvidedQueryImpl<>( this, namedQueryMemento );
|
||||||
}
|
}
|
||||||
else if ( batchSize > 1 ) {
|
else if ( batchSize > 1 ) {
|
||||||
singleIdEntityLoader = createBatchingIdEntityLoader( this, batchSize, factory );
|
singleIdEntityLoader = createBatchingIdEntityLoader( this, batchSize, factory );
|
||||||
|
@ -4723,17 +4723,17 @@ public abstract class AbstractEntityPersister
|
||||||
creationProcess.registerInitializationCallback(
|
creationProcess.registerInitializationCallback(
|
||||||
"Entity(" + getEntityName() + ") `staticFetchableList` generator",
|
"Entity(" + getEntityName() + ") `staticFetchableList` generator",
|
||||||
() -> {
|
() -> {
|
||||||
|
final ImmutableAttributeMappingList.Builder builder =
|
||||||
|
new ImmutableAttributeMappingList.Builder( attributeMappings.size() );
|
||||||
|
visitSubTypeAttributeMappings( builder::add );
|
||||||
|
assert superMappingType != null || builder.assertFetchableIndexes();
|
||||||
|
staticFetchableList = builder.build();
|
||||||
if ( hasInsertGeneratedProperties() ) {
|
if ( hasInsertGeneratedProperties() ) {
|
||||||
insertGeneratedValuesProcessor = createGeneratedValuesProcessor( INSERT );
|
insertGeneratedValuesProcessor = createGeneratedValuesProcessor( INSERT );
|
||||||
}
|
}
|
||||||
if ( hasUpdateGeneratedProperties() ) {
|
if ( hasUpdateGeneratedProperties() ) {
|
||||||
updateGeneratedValuesProcessor = createGeneratedValuesProcessor( UPDATE );
|
updateGeneratedValuesProcessor = createGeneratedValuesProcessor( UPDATE );
|
||||||
}
|
}
|
||||||
final ImmutableAttributeMappingList.Builder builder =
|
|
||||||
new ImmutableAttributeMappingList.Builder( attributeMappings.size() );
|
|
||||||
visitSubTypeAttributeMappings( builder::add );
|
|
||||||
assert superMappingType != null || builder.assertFetchableIndexes();
|
|
||||||
staticFetchableList = builder.build();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -21,12 +21,10 @@ import org.hibernate.sql.ast.tree.AbstractStatement;
|
||||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||||
import org.hibernate.sql.ast.tree.cte.CteContainer;
|
import org.hibernate.sql.ast.tree.cte.CteContainer;
|
||||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
import org.hibernate.sql.results.graph.DomainResult;
|
||||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
|
||||||
import org.hibernate.type.spi.TypeConfiguration;
|
import org.hibernate.type.spi.TypeConfiguration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -10,10 +10,8 @@ import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.OneToOne;
|
||||||
import jakarta.persistence.PrimaryKeyJoinColumn;
|
import jakarta.persistence.PrimaryKeyJoinColumn;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.orm.test.mapping.naturalid.nullable;
|
package org.hibernate.orm.test.mapping.naturalid.nullable;
|
||||||
|
|
||||||
|
import jakarta.persistence.Basic;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
|
|
Loading…
Reference in New Issue