mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-17 08:35:13 +00:00
preliminary support for collections
This commit is contained in:
parent
cf09e47d40
commit
093f410953
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.boot.model.process.internal;
|
||||
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.spi.EnumValueConverter;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CustomType;
|
||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EnumeratedValueResolution<E extends Enum<E>> implements BasicValue.Resolution<E> {
|
||||
private final CustomType enumTypeMapping;
|
||||
private final JavaTypeDescriptor<E> domainJtd;
|
||||
private final JavaTypeDescriptor<?> jdbcJtd;
|
||||
private final SqlTypeDescriptor std;
|
||||
private final EnumValueConverter<E,?> valueConverter;
|
||||
|
||||
public EnumeratedValueResolution(
|
||||
CustomType enumTypeMapping,
|
||||
JavaTypeDescriptor<E> domainJtd,
|
||||
JavaTypeDescriptor<?> jdbcJtd,
|
||||
SqlTypeDescriptor std,
|
||||
EnumValueConverter<E, ?> valueConverter) {
|
||||
this.enumTypeMapping = enumTypeMapping;
|
||||
this.domainJtd = domainJtd;
|
||||
this.jdbcJtd = jdbcJtd;
|
||||
this.std = std;
|
||||
this.valueConverter = valueConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicType getResolvedBasicType() {
|
||||
return enumTypeMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<E> getDomainJavaDescriptor() {
|
||||
return domainJtd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor<?> getRelationalJavaDescriptor() {
|
||||
return jdbcJtd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlTypeDescriptor getRelationalSqlTypeDescriptor() {
|
||||
return std;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicValueConverter getValueConverter() {
|
||||
return valueConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutabilityPlan<E> getMutabilityPlan() {
|
||||
return ImmutableMutabilityPlan.instance();
|
||||
}
|
||||
}
|
@ -49,6 +49,7 @@
|
||||
import org.hibernate.type.CharacterArrayClobType;
|
||||
import org.hibernate.type.CharacterArrayNClobType;
|
||||
import org.hibernate.type.CharacterNCharType;
|
||||
import org.hibernate.type.EnumType;
|
||||
import org.hibernate.type.PrimitiveCharacterArrayClobType;
|
||||
import org.hibernate.type.PrimitiveCharacterArrayNClobType;
|
||||
import org.hibernate.type.SerializableToBlobType;
|
||||
@ -162,15 +163,15 @@ public void setType(XProperty property, XClass returnedClass, String declaringCl
|
||||
}
|
||||
|
||||
Type annType = null;
|
||||
if ( (!key && property.isAnnotationPresent( Type.class ))
|
||||
|| (key && property.isAnnotationPresent( MapKeyType.class )) ) {
|
||||
if ( key ) {
|
||||
MapKeyType ann = property.getAnnotation( MapKeyType.class );
|
||||
|
||||
if ( key ) {
|
||||
final MapKeyType ann = property.getAnnotation( MapKeyType.class );
|
||||
if ( ann != null ) {
|
||||
annType = ann.value();
|
||||
}
|
||||
else {
|
||||
annType = property.getAnnotation( Type.class );
|
||||
}
|
||||
}
|
||||
else {
|
||||
annType = property.getAnnotation( Type.class );
|
||||
}
|
||||
|
||||
if ( annType != null ) {
|
||||
@ -313,7 +314,8 @@ else if ( buildingContext.getBootstrapContext().getReflectionManager().equals( r
|
||||
}
|
||||
|
||||
if ( BinderHelper.ANNOTATION_STRING_DEFAULT.equals( type ) ) {
|
||||
if ( returnedClassOrElement.isEnum() ) {
|
||||
if ( this.enumerationStyle == null && returnedClassOrElement.isEnum() ) {
|
||||
type = EnumType.class.getName();
|
||||
this.enumerationStyle = determineEnumType( property, key );
|
||||
}
|
||||
}
|
||||
@ -439,15 +441,17 @@ public SimpleValue make() {
|
||||
simpleValue = new BasicValue( buildingContext, table );
|
||||
|
||||
if ( enumerationStyle != null ) {
|
||||
simpleValue.setEnumerationStyle( enumerationStyle );
|
||||
simpleValue.setEnumerationStyle( enumerationStyle, returnedClassName );
|
||||
}
|
||||
|
||||
if ( isVersion ) {
|
||||
simpleValue.makeVersion();
|
||||
}
|
||||
|
||||
if ( isNationalized ) {
|
||||
simpleValue.makeNationalized();
|
||||
}
|
||||
|
||||
if ( isLob ) {
|
||||
simpleValue.makeLob();
|
||||
}
|
||||
@ -503,9 +507,6 @@ public void fillSimpleValue() {
|
||||
);
|
||||
simpleValue.setJpaAttributeConverterDescriptor( attributeConverterDescriptor );
|
||||
}
|
||||
else if ( enumerationStyle != null ) {
|
||||
simpleValue.setEnumerationStyle( enumerationStyle );
|
||||
}
|
||||
else {
|
||||
|
||||
String type;
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
package org.hibernate.mapping;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
@ -17,6 +18,7 @@
|
||||
import org.hibernate.boot.model.TypeDefinition;
|
||||
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
||||
import org.hibernate.boot.model.convert.spi.JpaAttributeConverterCreationContext;
|
||||
import org.hibernate.boot.model.process.internal.EnumeratedValueResolution;
|
||||
import org.hibernate.boot.model.process.internal.InferredBasicValueResolution;
|
||||
import org.hibernate.boot.model.process.internal.InferredBasicValueResolver;
|
||||
import org.hibernate.boot.model.process.internal.NamedBasicTypeResolution;
|
||||
@ -29,6 +31,7 @@
|
||||
import org.hibernate.metamodel.model.convert.internal.NamedEnumValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.internal.OrdinalEnumValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.convert.spi.EnumValueConverter;
|
||||
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.type.BasicType;
|
||||
@ -42,8 +45,10 @@
|
||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.RowVersionTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.TemporalJavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
||||
import org.hibernate.type.descriptor.sql.spi.SqlTypeDescriptorRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
@ -118,10 +123,15 @@ public void setTypeUsingReflection(String className, String propertyName) throws
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public void setEnumerationStyle(EnumType enumerationStyle) {
|
||||
public void setEnumerationStyle(EnumType enumerationStyle, String enumJavaTypeName) {
|
||||
this.enumerationStyle = enumerationStyle;
|
||||
this.resolvedJavaClass = getBuildingContext().getBootstrapContext()
|
||||
.getServiceRegistry()
|
||||
.getService( ClassLoaderService.class )
|
||||
.classForName( enumJavaTypeName );
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public EnumType getEnumerationStyle() {
|
||||
return enumerationStyle;
|
||||
}
|
||||
@ -157,6 +167,8 @@ public Resolution<?> resolve() {
|
||||
if ( explicitTypeName != null ) {
|
||||
resolution = interpretExplicitlyNamedType(
|
||||
explicitTypeName,
|
||||
enumerationStyle,
|
||||
resolvedJavaClass,
|
||||
explicitJavaTypeAccess,
|
||||
explicitSqlTypeAccess,
|
||||
attributeConverterDescriptor,
|
||||
@ -178,6 +190,7 @@ public Resolution<?> resolve() {
|
||||
this,
|
||||
() -> {
|
||||
if ( resolvedJavaClass != null ) {
|
||||
//noinspection unchecked
|
||||
return getBuildingContext().getBootstrapContext()
|
||||
.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
@ -200,6 +213,7 @@ else if ( ownerName != null && propertyName != null ) {
|
||||
return basicType.getJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return getBuildingContext().getBootstrapContext()
|
||||
.getTypeConfiguration()
|
||||
.getJavaTypeDescriptorRegistry()
|
||||
@ -228,8 +242,10 @@ else if ( dependentValue != null ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Resolution interpretExplicitlyNamedType(
|
||||
String name,
|
||||
Function<TypeConfiguration,JavaTypeDescriptor<?>> explicitJtdAccess,
|
||||
Function<TypeConfiguration,SqlTypeDescriptor> explicitStdAccess,
|
||||
EnumType enumerationStyle,
|
||||
Class resolvedJavaClass,
|
||||
Function<TypeConfiguration, JavaTypeDescriptor<?>> explicitJtdAccess,
|
||||
Function<TypeConfiguration, SqlTypeDescriptor> explicitStdAccess,
|
||||
ConverterDescriptor converterDescriptor,
|
||||
MutabilityPlan explicitMutabilityPlan,
|
||||
Properties localTypeParams,
|
||||
@ -272,6 +288,45 @@ public TypeConfiguration getTypeConfiguration() {
|
||||
);
|
||||
}
|
||||
|
||||
if ( enumerationStyle != null ) {
|
||||
assert resolvedJavaClass != null;
|
||||
assert resolvedJavaClass.isEnum();
|
||||
|
||||
final JavaTypeDescriptorRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
|
||||
final SqlTypeDescriptorRegistry stdRegistry = typeConfiguration.getSqlTypeDescriptorRegistry();
|
||||
|
||||
final EnumJavaTypeDescriptor domainJtd = (EnumJavaTypeDescriptor) jtdRegistry.getDescriptor( resolvedJavaClass );
|
||||
|
||||
final JavaTypeDescriptor jdbcJtd;
|
||||
final SqlTypeDescriptor std;
|
||||
final EnumValueConverter<?,?> valueConverter;
|
||||
|
||||
if ( enumerationStyle == EnumType.ORDINAL ) {
|
||||
jdbcJtd = jtdRegistry.getDescriptor( Integer.class );
|
||||
final SqlTypeDescriptor explicitStd = explicitStdAccess == null ? null : explicitStdAccess.apply( typeConfiguration );
|
||||
std = explicitStd != null ? explicitStd : stdRegistry.getDescriptor( Types.INTEGER );
|
||||
valueConverter = new OrdinalEnumValueConverter( domainJtd, std, jdbcJtd );
|
||||
}
|
||||
else {
|
||||
jdbcJtd = jtdRegistry.getDescriptor( String.class );
|
||||
std = jdbcJtd.getJdbcRecommendedSqlType( stdIndicators );
|
||||
valueConverter = new NamedEnumValueConverter( domainJtd, std, jdbcJtd );
|
||||
}
|
||||
|
||||
final CustomType valueMapper = new CustomType(
|
||||
new org.hibernate.type.EnumType( resolvedJavaClass, valueConverter, typeConfiguration ),
|
||||
typeConfiguration
|
||||
);
|
||||
|
||||
return new EnumeratedValueResolution(
|
||||
valueMapper,
|
||||
domainJtd,
|
||||
jdbcJtd,
|
||||
std,
|
||||
valueConverter
|
||||
);
|
||||
}
|
||||
|
||||
// see if it is a named basic type
|
||||
final BasicType basicTypeByName = typeConfiguration.getBasicTypeRegistry().getRegisteredType( name );
|
||||
if ( basicTypeByName != null ) {
|
||||
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.metamodel.mapping;
|
||||
|
||||
import org.hibernate.collection.spi.CollectionSemantics;
|
||||
|
||||
/**
|
||||
* MappingType for collections. Not that this is the descriptor for
|
||||
* the collection Java type (List, Set, etc)
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CollectionMappingType<C> extends MappingType {
|
||||
CollectionSemantics<C> getCCollectionSemantics();
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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.metamodel.mapping.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.results.internal.domain.basic.BasicFetch;
|
||||
import org.hibernate.sql.results.internal.domain.basic.BasicResult;
|
||||
import org.hibernate.sql.results.spi.DomainResult;
|
||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.spi.Fetch;
|
||||
import org.hibernate.sql.results.spi.FetchParent;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Models a basic collection element/value or index/key
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class BasicValuedCollectionPart implements BasicValuedModelPart {
|
||||
public BasicValuedCollectionPart(
|
||||
Nature nature,
|
||||
BasicType mapper,
|
||||
BasicValueConverter valueConverter,
|
||||
String tableExpression,
|
||||
String columnExpression) {
|
||||
this.nature = nature;
|
||||
this.mapper = mapper;
|
||||
this.valueConverter = valueConverter;
|
||||
this.tableExpression = tableExpression;
|
||||
this.columnExpression = columnExpression;
|
||||
}
|
||||
|
||||
enum Nature { ELEMENT, INDEX }
|
||||
|
||||
private final Nature nature;
|
||||
private final BasicType mapper;
|
||||
private final BasicValueConverter valueConverter;
|
||||
|
||||
private final String tableExpression;
|
||||
private final String columnExpression;
|
||||
|
||||
@Override
|
||||
public String getContainingTableExpression() {
|
||||
return tableExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMappedColumnExpression() {
|
||||
return columnExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicValueConverter getConverter() {
|
||||
return valueConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getJavaTypeDescriptor() {
|
||||
return mapper.getMappedJavaTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DomainResult<T> createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
final SqlSelection sqlSelection = resolveSqlSelection( tableGroup, creationState );
|
||||
|
||||
//noinspection unchecked
|
||||
return new BasicResult(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
resultVariable,
|
||||
getJavaTypeDescriptor()
|
||||
);
|
||||
}
|
||||
|
||||
private SqlSelection resolveSqlSelection(TableGroup tableGroup, DomainResultCreationState creationState) {
|
||||
final SqlExpressionResolver exprResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
|
||||
|
||||
return exprResolver.resolveSqlSelection(
|
||||
exprResolver.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey( tableExpression, columnExpression ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
tableGroup.resolveTableReference( tableExpression ).getIdentificationVariable(),
|
||||
columnExpression,
|
||||
mapper,
|
||||
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
|
||||
)
|
||||
),
|
||||
getJavaTypeDescriptor(),
|
||||
creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySqlSelections(
|
||||
NavigablePath navigablePath, TableGroup tableGroup, DomainResultCreationState creationState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcMapping getJdbcMapping() {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingType getMappedTypeDescriptor() {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFetchableName() {
|
||||
return nature == Nature.ELEMENT ? "{value}" : "{key}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStrategy getMappedFetchStrategy() {
|
||||
return FetchStrategy.IMMEDIATE_JOIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch generateFetch(
|
||||
FetchParent fetchParent,
|
||||
NavigablePath fetchablePath,
|
||||
FetchTiming fetchTiming,
|
||||
boolean selected,
|
||||
LockMode lockMode,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
final SqlSelection sqlSelection = resolveSqlSelection(
|
||||
creationState.getSqlAstCreationState().getFromClauseAccess().findTableGroup( fetchablePath.getParent() ),
|
||||
creationState
|
||||
);
|
||||
|
||||
return new BasicFetch(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
fetchParent,
|
||||
fetchablePath,
|
||||
this,
|
||||
false,
|
||||
valueConverter,
|
||||
FetchTiming.IMMEDIATE,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCount(TypeConfiguration typeConfiguration) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JdbcMapping> getJdbcMappings(TypeConfiguration typeConfiguration) {
|
||||
return Collections.singletonList( getJdbcMapping() );
|
||||
}
|
||||
}
|
@ -10,29 +10,55 @@
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.collection.internal.StandardArraySemantics;
|
||||
import org.hibernate.collection.internal.StandardBagSemantics;
|
||||
import org.hibernate.collection.internal.StandardIdentifierBagSemantics;
|
||||
import org.hibernate.collection.internal.StandardListSemantics;
|
||||
import org.hibernate.collection.internal.StandardMapSemantics;
|
||||
import org.hibernate.collection.internal.StandardOrderedMapSemantics;
|
||||
import org.hibernate.collection.internal.StandardOrderedSetSemantics;
|
||||
import org.hibernate.collection.internal.StandardSetSemantics;
|
||||
import org.hibernate.collection.internal.StandardSortedMapSemantics;
|
||||
import org.hibernate.collection.internal.StandardSortedSetSemantics;
|
||||
import org.hibernate.collection.spi.CollectionSemantics;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.Array;
|
||||
import org.hibernate.mapping.Bag;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.IdentifierBag;
|
||||
import org.hibernate.mapping.List;
|
||||
import org.hibernate.mapping.Map;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.PrimitiveArray;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Set;
|
||||
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.CollectionMappingType;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.persister.walking.internal.FetchStrategyHelper;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
||||
@ -41,8 +67,8 @@
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.results.internal.domain.basic.BasicFetch;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.results.internal.domain.basic.BasicFetch;
|
||||
import org.hibernate.sql.results.internal.domain.basic.BasicResult;
|
||||
import org.hibernate.sql.results.spi.DomainResult;
|
||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||
@ -53,6 +79,7 @@
|
||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
@ -580,4 +607,180 @@ public CascadeStyle getCascadeStyle() {
|
||||
|
||||
return (EmbeddedAttributeMapping) embeddableMappingType.getEmbeddedValueMapping();
|
||||
}
|
||||
|
||||
public static PluralAttributeMapping buildPluralAttributeMapping(
|
||||
String attrName,
|
||||
int stateArrayPosition,
|
||||
Property bootProperty,
|
||||
ManagedMappingType declaringType,
|
||||
String tableExpression,
|
||||
String[] attrColumnExpressions,
|
||||
PropertyAccess propertyAccess,
|
||||
CascadeStyle cascadeStyle,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
|
||||
final Collection bootValueMapping = (Collection) bootProperty.getValue();
|
||||
|
||||
final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext();
|
||||
final CollectionPersister collectionDescriptor = creationContext.getDomainModel().findCollectionDescriptor( bootValueMapping.getRole() );
|
||||
assert collectionDescriptor != null;
|
||||
|
||||
final CollectionMappingType<?> collectionMappingType;
|
||||
final JavaTypeDescriptorRegistry jtdRegistry = creationContext.getJavaTypeDescriptorRegistry();
|
||||
|
||||
if ( bootValueMapping instanceof Array ) {
|
||||
if ( bootValueMapping instanceof PrimitiveArray ) {
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
else {
|
||||
collectionMappingType = new CollectionMappingTypeImpl(
|
||||
jtdRegistry.getDescriptor( Object[].class ),
|
||||
StandardArraySemantics.INSTANCE
|
||||
);
|
||||
}
|
||||
}
|
||||
else if ( bootValueMapping instanceof Bag ) {
|
||||
collectionMappingType = new CollectionMappingTypeImpl(
|
||||
jtdRegistry.getDescriptor( java.util.Collection.class ),
|
||||
StandardBagSemantics.INSTANCE
|
||||
);
|
||||
}
|
||||
else if ( bootValueMapping instanceof IdentifierBag ) {
|
||||
collectionMappingType = new CollectionMappingTypeImpl(
|
||||
jtdRegistry.getDescriptor( java.util.Collection.class ),
|
||||
StandardIdentifierBagSemantics.INSTANCE
|
||||
);
|
||||
}
|
||||
else if ( bootValueMapping instanceof List ) {
|
||||
collectionMappingType = new CollectionMappingTypeImpl(
|
||||
jtdRegistry.getDescriptor( java.util.List.class ),
|
||||
StandardListSemantics.INSTANCE
|
||||
);
|
||||
}
|
||||
else if ( bootValueMapping instanceof Map ) {
|
||||
if ( bootValueMapping.isSorted() ) {
|
||||
collectionMappingType = new CollectionMappingTypeImpl(
|
||||
jtdRegistry.getDescriptor( java.util.SortedMap.class ),
|
||||
StandardSortedMapSemantics.INSTANCE
|
||||
);
|
||||
}
|
||||
else {
|
||||
collectionMappingType = new CollectionMappingTypeImpl(
|
||||
jtdRegistry.getDescriptor( java.util.Map.class ),
|
||||
bootValueMapping.hasOrder()
|
||||
? StandardOrderedMapSemantics.INSTANCE
|
||||
: StandardMapSemantics.INSTANCE
|
||||
);
|
||||
}
|
||||
}
|
||||
else if ( bootValueMapping instanceof Set ) {
|
||||
if ( bootValueMapping.isSorted() ) {
|
||||
collectionMappingType = new CollectionMappingTypeImpl(
|
||||
jtdRegistry.getDescriptor( java.util.SortedSet.class ),
|
||||
StandardSortedSetSemantics.INSTANCE
|
||||
);
|
||||
}
|
||||
else {
|
||||
collectionMappingType = new CollectionMappingTypeImpl(
|
||||
jtdRegistry.getDescriptor( java.util.Set.class ),
|
||||
bootValueMapping.hasOrder()
|
||||
? StandardOrderedSetSemantics.INSTANCE
|
||||
: StandardSetSemantics.INSTANCE
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new MappingException( "Unexpected org.hibernate.mapping.Collection impl : " + bootValueMapping );
|
||||
}
|
||||
|
||||
final StateArrayContributorMetadata contributorMetadata = new StateArrayContributorMetadata() {
|
||||
@Override
|
||||
public PropertyAccess getPropertyAccess() {
|
||||
return propertyAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutabilityPlan getMutabilityPlan() {
|
||||
return ImmutableMutabilityPlan.instance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return bootProperty.isOptional();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInsertable() {
|
||||
return bootProperty.isInsertable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdatable() {
|
||||
return bootProperty.isUpdateable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInDirtyChecking() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludedInOptimisticLocking() {
|
||||
return bootProperty.isOptimisticLocked();
|
||||
}
|
||||
};
|
||||
|
||||
final FetchStyle style = FetchStrategyHelper.determineFetchStyleByMetadata(
|
||||
( (OuterJoinLoadable) declaringType ).getFetchMode( stateArrayPosition ),
|
||||
collectionDescriptor.getCollectionType(),
|
||||
creationContext.getSessionFactory()
|
||||
);
|
||||
|
||||
return new PluralAttributeMappingImpl(
|
||||
attrName,
|
||||
propertyAccess,
|
||||
entityMappingType -> contributorMetadata,
|
||||
collectionMappingType,
|
||||
stateArrayPosition,
|
||||
tableExpression,
|
||||
attrColumnExpressions,
|
||||
null,
|
||||
null,
|
||||
new FetchStrategy(
|
||||
FetchStrategyHelper.determineFetchTiming(
|
||||
style,
|
||||
collectionDescriptor.getCollectionType(),
|
||||
creationContext.getSessionFactory()
|
||||
),
|
||||
style
|
||||
),
|
||||
cascadeStyle,
|
||||
declaringType,
|
||||
collectionDescriptor
|
||||
);
|
||||
}
|
||||
|
||||
private static class CollectionMappingTypeImpl implements CollectionMappingType {
|
||||
private final JavaTypeDescriptor collectionJtd;
|
||||
private final CollectionSemantics semantics;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public CollectionMappingTypeImpl(
|
||||
JavaTypeDescriptor collectionJtd,
|
||||
CollectionSemantics semantics) {
|
||||
this.collectionJtd = collectionJtd;
|
||||
this.semantics = semantics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionSemantics getCCollectionSemantics() {
|
||||
return semantics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaTypeDescriptor getMappedJavaTypeDescriptor() {
|
||||
return collectionJtd;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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.metamodel.mapping.internal;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.metamodel.mapping.CollectionMappingType;
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.results.spi.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.spi.Fetch;
|
||||
import org.hibernate.sql.results.spi.FetchParent;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PluralAttributeMappingImpl extends AbstractAttributeMapping implements PluralAttributeMapping {
|
||||
private final int stateArrayPosition;
|
||||
private final PropertyAccess propertyAccess;
|
||||
private final StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess;
|
||||
|
||||
private final FetchStrategy fetchStrategy;
|
||||
|
||||
private final String tableExpression;
|
||||
private final String[] attrColumnExpressions;
|
||||
|
||||
private final ModelPart elementDescriptor;
|
||||
private final ModelPart indexDescriptor;
|
||||
|
||||
private final CascadeStyle cascadeStyle;
|
||||
private final CollectionPersister collectionDescriptor;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public PluralAttributeMappingImpl(
|
||||
String attributeName,
|
||||
PropertyAccess propertyAccess,
|
||||
StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess,
|
||||
CollectionMappingType collectionMappingType,
|
||||
int stateArrayPosition,
|
||||
String tableExpression,
|
||||
String[] attrColumnExpressions,
|
||||
ModelPart elementDescriptor,
|
||||
ModelPart indexDescriptor,
|
||||
FetchStrategy fetchStrategy,
|
||||
CascadeStyle cascadeStyle,
|
||||
ManagedMappingType declaringType,
|
||||
CollectionPersister collectionDescriptor) {
|
||||
super( attributeName, collectionMappingType, declaringType );
|
||||
this.propertyAccess = propertyAccess;
|
||||
this.stateArrayContributorMetadataAccess = stateArrayContributorMetadataAccess;
|
||||
this.stateArrayPosition = stateArrayPosition;
|
||||
this.tableExpression = tableExpression;
|
||||
this.attrColumnExpressions = attrColumnExpressions;
|
||||
this.elementDescriptor = elementDescriptor;
|
||||
this.indexDescriptor = indexDescriptor;
|
||||
this.fetchStrategy = fetchStrategy;
|
||||
this.cascadeStyle = cascadeStyle;
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CollectionMappingType getMappedTypeDescriptor() {
|
||||
return (CollectionMappingType) super.getMappedTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionPersister getCollectionDescriptor() {
|
||||
return collectionDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPart getValueDescriptor() {
|
||||
return elementDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPart getIndexDescriptor() {
|
||||
return indexDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStateArrayPosition() {
|
||||
return stateArrayPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateArrayContributorMetadataAccess getAttributeMetadataAccess() {
|
||||
return stateArrayContributorMetadataAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyAccess getPropertyAccess() {
|
||||
return propertyAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFetchableName() {
|
||||
return getAttributeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStrategy getMappedFetchStrategy() {
|
||||
return fetchStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch generateFetch(
|
||||
FetchParent fetchParent,
|
||||
NavigablePath fetchablePath,
|
||||
FetchTiming fetchTiming,
|
||||
boolean selected,
|
||||
LockMode lockMode,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||
final TableGroup collectionTableGroup = sqlAstCreationState.getFromClauseAccess().getTableGroup( fetchablePath );
|
||||
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
}
|
@ -5338,12 +5338,25 @@ public Object[] getPropertyValues(Object object) {
|
||||
|
||||
@Override
|
||||
public Object getPropertyValue(Object object, int i) {
|
||||
return getEntityTuplizer().getPropertyValue( object, i );
|
||||
return attributeMappings.get( i ).getAttributeMetadataAccess()
|
||||
.resolveAttributeMetadata( this )
|
||||
.getPropertyAccess()
|
||||
.getGetter()
|
||||
.get( object );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPropertyValue(Object object, String propertyName) {
|
||||
return getEntityTuplizer().getPropertyValue( object, propertyName );
|
||||
for ( int i = 0; i < attributeMappings.size(); i++ ) {
|
||||
if ( attributeMappings.get( i ).getAttributeName().equals( propertyName ) ) {
|
||||
return attributeMappings.get( i ).getAttributeMetadataAccess()
|
||||
.resolveAttributeMetadata( this )
|
||||
.getPropertyAccess()
|
||||
.getGetter()
|
||||
.get( object );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -6316,6 +6329,19 @@ else if ( attrType instanceof CompositeType ) {
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
else if ( attrType instanceof CollectionType ) {
|
||||
return MappingModelCreationHelper.buildPluralAttributeMapping(
|
||||
attrName,
|
||||
stateArrayPosition,
|
||||
bootProperty,
|
||||
declaringType,
|
||||
tableExpression,
|
||||
attrColumnNames,
|
||||
propertyAccess,
|
||||
tupleAttrDefinition.getCascadeStyle(),
|
||||
creationProcess
|
||||
);
|
||||
}
|
||||
|
||||
// todo (6.0) : for now ignore any non basic-typed attributes
|
||||
|
||||
|
@ -36,6 +36,7 @@ public class StandardRowReader<T> implements RowReader<T> {
|
||||
|
||||
private final Object[] resultRow;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public StandardRowReader(
|
||||
List<DomainResultAssembler> resultAssemblers,
|
||||
List<Initializer> initializers,
|
||||
@ -123,23 +124,23 @@ private void coordinateInitializers(
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// old
|
||||
|
||||
for ( Initializer initializer : initializers ) {
|
||||
initializer.resolveKey( rowProcessingState );
|
||||
for ( int i = 0; i < initializers.size(); i++ ) {
|
||||
initializers.get( i ).resolveKey( rowProcessingState );
|
||||
}
|
||||
|
||||
for ( Initializer initializer : initializers ) {
|
||||
initializer.resolveInstance( rowProcessingState );
|
||||
for ( int i = 0; i < initializers.size(); i++ ) {
|
||||
initializers.get( i ).resolveInstance( rowProcessingState );
|
||||
}
|
||||
|
||||
for ( Initializer initializer : initializers ) {
|
||||
initializer.initializeInstance( rowProcessingState );
|
||||
for ( int i = 0; i < initializers.size(); i++ ) {
|
||||
initializers.get( i ).initializeInstance( rowProcessingState );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishUp(JdbcValuesSourceProcessingState processingState) {
|
||||
for ( Initializer initializer : initializers ) {
|
||||
initializer.endLoading( processingState.getExecutionContext() );
|
||||
for ( int i = 0; i < initializers.size(); i++ ) {
|
||||
initializers.get( i ).endLoading( processingState.getExecutionContext() );
|
||||
}
|
||||
|
||||
// todo : use Callback to execute AfterLoadActions
|
||||
|
@ -6,12 +6,7 @@
|
||||
*/
|
||||
package org.hibernate.sql.results.internal.domain.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
@ -37,8 +32,7 @@ public abstract class AbstractEntityResultNode extends AbstractFetchParent imple
|
||||
|
||||
private final EntityMappingType targetType;
|
||||
|
||||
private final List<DomainResult> attributeDomainResults;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public AbstractEntityResultNode(
|
||||
EntityValuedModelPart referencedModelPart,
|
||||
LockMode lockMode,
|
||||
@ -47,6 +41,7 @@ public AbstractEntityResultNode(
|
||||
this( referencedModelPart, lockMode, navigablePath, null, creationState );
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public AbstractEntityResultNode(
|
||||
EntityValuedModelPart referencedModelPart,
|
||||
LockMode lockMode,
|
||||
@ -93,21 +88,6 @@ public AbstractEntityResultNode(
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
||||
// todo (6.0) : handle other special navigables such as discriminator, row-id, tenant-id, etc
|
||||
|
||||
attributeDomainResults = CollectionHelper.arrayList( entityDescriptor.getNumberOfAttributeMappings() );
|
||||
|
||||
entityDescriptor.visitAttributeMappings(
|
||||
mapping -> attributeDomainResults.add(
|
||||
mapping.createDomainResult(
|
||||
navigablePath.append( mapping.getAttributeName() ),
|
||||
entityTableGroup,
|
||||
null,
|
||||
creationState
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -129,14 +109,17 @@ public LockMode getLockMode() {
|
||||
return lockMode;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected DomainResult getIdentifierResult() {
|
||||
return identifierResult;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected DomainResult getDiscriminatorResult() {
|
||||
return discriminatorResult;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected DomainResult getVersionResult() {
|
||||
return versionResult;
|
||||
}
|
||||
|
@ -16,6 +16,11 @@
|
||||
public class ImmutableMutabilityPlan<T> implements MutabilityPlan<T> {
|
||||
public static final ImmutableMutabilityPlan INSTANCE = new ImmutableMutabilityPlan();
|
||||
|
||||
public static <X> ImmutableMutabilityPlan<X> instance() {
|
||||
//noinspection unchecked
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
|
@ -0,0 +1,330 @@
|
||||
/*
|
||||
* 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.metamodel.mapping;
|
||||
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.Table;
|
||||
|
||||
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.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@DomainModel(
|
||||
annotatedClasses = {
|
||||
PluralAttributeTests.SimpleEntity.class,
|
||||
PluralAttributeTests.EntityContainingLists.class,
|
||||
PluralAttributeTests.Component.class
|
||||
}
|
||||
)
|
||||
@ServiceRegistry
|
||||
@SessionFactory
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class PluralAttributeTests {
|
||||
|
||||
@Test
|
||||
public void testLists(SessionFactoryScope scope) {
|
||||
System.out.println( "test" );
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public void createTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final EntityContainingLists entityContainingLists = new EntityContainingLists( 1, "first" );
|
||||
|
||||
entityContainingLists.addBasic( "abc" );
|
||||
entityContainingLists.addBasic( "def" );
|
||||
entityContainingLists.addBasic( "ghi" );
|
||||
|
||||
entityContainingLists.addConvertedBasic( EnumValue.TWO );
|
||||
|
||||
entityContainingLists.addEnum( EnumValue.ONE );
|
||||
entityContainingLists.addEnum( EnumValue.THREE );
|
||||
|
||||
entityContainingLists.addComponent( new Component( "first-a1", "first-another-a1" ) );
|
||||
entityContainingLists.addComponent( new Component( "first-a2", "first-another-a2" ) );
|
||||
|
||||
entityContainingLists.addSimpleEntity( new SimpleEntity( 1, "simple-1" ) );
|
||||
entityContainingLists.addSimpleEntity( new SimpleEntity( 2, "simple-2" ) );
|
||||
|
||||
session.save( entityContainingLists );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public void deleteTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> session.doWork(
|
||||
conn -> {
|
||||
try ( Statement stmnt = conn.createStatement() ) {
|
||||
stmnt.execute( "delete from EntityContainingLists_listOfEnums" );
|
||||
stmnt.execute( "delete from EntityContainingLists_listOfConvertedBasics" );
|
||||
stmnt.execute( "delete from EntityContainingLists_listOfComponents" );
|
||||
stmnt.execute( "delete from EntityContainingLists_listOfBasics" );
|
||||
stmnt.execute( "delete from entity_containing_lists_simple_entity" );
|
||||
stmnt.execute( "delete from entity_containing_lists" );
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public enum EnumValue {
|
||||
ONE( "first" ),
|
||||
TWO( "second" ),
|
||||
THREE( "third" );
|
||||
|
||||
private final String code;
|
||||
|
||||
EnumValue(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public static EnumValue fromCode(String code) {
|
||||
if ( code == null || code.isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch ( code ) {
|
||||
case "first" : {
|
||||
return ONE;
|
||||
}
|
||||
case "second" : {
|
||||
return TWO;
|
||||
}
|
||||
case "third" : {
|
||||
return THREE;
|
||||
}
|
||||
default: {
|
||||
throw new RuntimeException( "Could not convert enum code : " + code );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Converter implements AttributeConverter<EnumValue,String> {
|
||||
@Override
|
||||
public String convertToDatabaseColumn(EnumValue domainValue) {
|
||||
return domainValue == null ? null : domainValue.getCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumValue convertToEntityAttribute(String dbData) {
|
||||
return EnumValue.fromCode( dbData );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity( name = "EntityContainingLists" )
|
||||
@Table( name = "entity_containing_lists" )
|
||||
public static class EntityContainingLists {
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
private List<String> listOfBasics;
|
||||
private List<EnumValue> listOfConvertedBasics;
|
||||
private List<EnumValue> listOfEnums;
|
||||
private List<Component> listOfComponents;
|
||||
private List<SimpleEntity> listOfEntities;
|
||||
|
||||
public EntityContainingLists() {
|
||||
}
|
||||
|
||||
public EntityContainingLists(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@ElementCollection
|
||||
@OrderColumn
|
||||
public List<String> getListOfBasics() {
|
||||
return listOfBasics;
|
||||
}
|
||||
|
||||
public void setListOfBasics(List<String> listOfBasics) {
|
||||
this.listOfBasics = listOfBasics;
|
||||
}
|
||||
|
||||
public void addBasic(String basic) {
|
||||
if ( listOfBasics == null ) {
|
||||
listOfBasics = new ArrayList<>();
|
||||
}
|
||||
listOfBasics.add( basic );
|
||||
}
|
||||
|
||||
@ElementCollection
|
||||
@OrderColumn
|
||||
public List<EnumValue> getListOfConvertedBasics() {
|
||||
return listOfConvertedBasics;
|
||||
}
|
||||
|
||||
public void setListOfConvertedBasics(List<EnumValue> listOfConvertedBasics) {
|
||||
this.listOfConvertedBasics = listOfConvertedBasics;
|
||||
}
|
||||
|
||||
public void addConvertedBasic(EnumValue value) {
|
||||
if ( listOfConvertedBasics == null ) {
|
||||
listOfConvertedBasics = new ArrayList<>();
|
||||
}
|
||||
listOfConvertedBasics.add( value );
|
||||
}
|
||||
|
||||
@ElementCollection
|
||||
@Enumerated( EnumType.STRING )
|
||||
@OrderColumn
|
||||
public List<EnumValue> getListOfEnums() {
|
||||
return listOfEnums;
|
||||
}
|
||||
|
||||
public void setListOfEnums(List<EnumValue> listOfEnums) {
|
||||
this.listOfEnums = listOfEnums;
|
||||
}
|
||||
|
||||
public void addEnum(EnumValue value) {
|
||||
if ( listOfEnums == null ) {
|
||||
listOfEnums = new ArrayList<>();
|
||||
}
|
||||
listOfEnums.add( value );
|
||||
}
|
||||
|
||||
@ElementCollection
|
||||
@OrderColumn
|
||||
public List<Component> getListOfComponents() {
|
||||
return listOfComponents;
|
||||
}
|
||||
|
||||
public void setListOfComponents(List<Component> listOfComponents) {
|
||||
this.listOfComponents = listOfComponents;
|
||||
}
|
||||
|
||||
public void addComponent(Component value) {
|
||||
if ( listOfComponents == null ) {
|
||||
listOfComponents = new ArrayList<>();
|
||||
}
|
||||
listOfComponents.add( value );
|
||||
}
|
||||
|
||||
@OneToMany( cascade = CascadeType.ALL )
|
||||
@OrderColumn
|
||||
public List<SimpleEntity> getListOfEntities() {
|
||||
return listOfEntities;
|
||||
}
|
||||
|
||||
public void setListOfEntities(List<SimpleEntity> listOfEntities) {
|
||||
this.listOfEntities = listOfEntities;
|
||||
}
|
||||
|
||||
public void addSimpleEntity(SimpleEntity value) {
|
||||
if ( listOfEntities == null ) {
|
||||
listOfEntities = new ArrayList<>();
|
||||
}
|
||||
listOfEntities.add( value );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity( name = "SimpleEntity" )
|
||||
@Table( name = "simple_entity" )
|
||||
public static class SimpleEntity {
|
||||
private Integer id;
|
||||
private String name;
|
||||
|
||||
public SimpleEntity() {
|
||||
}
|
||||
|
||||
public SimpleEntity(Integer id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class Component {
|
||||
private String anAttribute;
|
||||
private String anotherAttribute;
|
||||
|
||||
public Component() {
|
||||
}
|
||||
|
||||
public Component(String anAttribute, String anotherAttribute) {
|
||||
this.anAttribute = anAttribute;
|
||||
this.anotherAttribute = anotherAttribute;
|
||||
}
|
||||
|
||||
public String getAnAttribute() {
|
||||
return anAttribute;
|
||||
}
|
||||
|
||||
public void setAnAttribute(String anAttribute) {
|
||||
this.anAttribute = anAttribute;
|
||||
}
|
||||
|
||||
public String getAnotherAttribute() {
|
||||
return anotherAttribute;
|
||||
}
|
||||
|
||||
public void setAnotherAttribute(String anotherAttribute) {
|
||||
this.anotherAttribute = anotherAttribute;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user