preliminary support for collections - lists and sets tested (excluding entity-valued elements and map-key)

This commit is contained in:
Steve Ebersole 2019-10-31 17:43:54 -05:00
parent 093f410953
commit c89ee3761a
76 changed files with 3249 additions and 402 deletions

View File

@ -36,7 +36,8 @@ public class EnumeratedValueResolution<E extends Enum<E>> implements BasicValue.
this.domainJtd = domainJtd; this.domainJtd = domainJtd;
this.jdbcJtd = jdbcJtd; this.jdbcJtd = jdbcJtd;
this.std = std; this.std = std;
this.valueConverter = valueConverter; // this.valueConverter = valueConverter;
this.valueConverter = null;
} }
@Override @Override

View File

@ -25,6 +25,7 @@ import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cfg.MetadataSourceType; import org.hibernate.cfg.MetadataSourceType;
import org.hibernate.collection.internal.StandardCollectionSemanticsResolver;
import org.hibernate.collection.spi.CollectionSemanticsResolver; import org.hibernate.collection.spi.CollectionSemanticsResolver;
import org.hibernate.dialect.function.SQLFunction; import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.metamodel.internal.StandardManagedTypeRepresentationResolver; import org.hibernate.metamodel.internal.StandardManagedTypeRepresentationResolver;
@ -61,7 +62,8 @@ public interface MetadataBuildingOptions {
} }
default CollectionSemanticsResolver getPersistentCollectionRepresentationResolver() { default CollectionSemanticsResolver getPersistentCollectionRepresentationResolver() {
throw new NotYetImplementedFor6Exception( getClass() ); // for now always return the standard one
return StandardCollectionSemanticsResolver.INSTANCE;
} }
/** /**

View File

@ -21,6 +21,8 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.loader.CollectionAliases; import org.hibernate.loader.CollectionAliases;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.RowProcessingState;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -190,6 +192,31 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
return element; return element;
} }
@Override
public Object readFrom(
RowProcessingState rowProcessingState,
DomainResultAssembler elementAssembler,
DomainResultAssembler indexAssembler,
DomainResultAssembler identifierAssembler,
Object owner) throws HibernateException {
assert elementAssembler != null;
assert indexAssembler != null;
assert identifierAssembler == null;
final Object element = elementAssembler.assemble( rowProcessingState );
final int index = (int) indexAssembler.assemble( rowProcessingState );
for ( int i = tempList.size(); i<=index; i++) {
//noinspection unchecked
tempList.add( i, null );
}
//noinspection unchecked
tempList.set( index, element );
return element;
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Iterator entries(CollectionPersister persister) { public Iterator entries(CollectionPersister persister) {

View File

@ -22,6 +22,8 @@ import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.CollectionAliases; import org.hibernate.loader.CollectionAliases;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.RowProcessingState;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
@ -133,6 +135,24 @@ public class PersistentBag extends AbstractPersistentCollection implements List
return element; return element;
} }
@Override
public Object readFrom(
RowProcessingState rowProcessingState,
DomainResultAssembler elementAssembler,
DomainResultAssembler indexAssembler,
DomainResultAssembler identifierAssembler,
Object owner) throws HibernateException {
assert indexAssembler == null;
assert identifierAssembler == null;
final Object element = elementAssembler.assemble( rowProcessingState );
if ( element != null ) {
//noinspection unchecked
bag.add( element );
}
return element;
}
@Override @Override
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
this.bag = (List) persister.getCollectionType().instantiate( anticipatedSize ); this.bag = (List) persister.getCollectionType().instantiate( anticipatedSize );

View File

@ -22,6 +22,8 @@ import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.CollectionAliases; import org.hibernate.loader.CollectionAliases;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.RowProcessingState;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
@ -372,6 +374,30 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
return element; return element;
} }
@Override
public Object readFrom(
RowProcessingState rowProcessingState,
DomainResultAssembler elementAssembler,
DomainResultAssembler indexAssembler,
DomainResultAssembler identifierAssembler,
Object owner) throws HibernateException {
assert indexAssembler == null;
final Object element = elementAssembler.assemble( rowProcessingState );
final Object identifier = identifierAssembler.assemble( rowProcessingState );
final Object old = identifiers.put(
values.size(),
identifier
);
if ( old == null ) {
//maintain correct duplication if loaded in a cartesian product
values.add( element );
}
return element;
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException { public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {

View File

@ -20,6 +20,8 @@ import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.CollectionAliases; import org.hibernate.loader.CollectionAliases;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.RowProcessingState;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
@ -206,9 +208,9 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
@Override @Override
@SuppressWarnings("unchecked")
public boolean containsAll(Collection coll) { public boolean containsAll(Collection coll) {
read(); read();
//noinspection unchecked
return list.containsAll( coll ); return list.containsAll( coll );
} }
@ -262,9 +264,9 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
@Override @Override
@SuppressWarnings("unchecked")
public boolean retainAll(Collection coll) { public boolean retainAll(Collection coll) {
initialize( true ); initialize( true );
//noinspection unchecked
if ( list.retainAll( coll ) ) { if ( list.retainAll( coll ) ) {
dirty(); dirty();
return true; return true;
@ -275,7 +277,6 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
@Override @Override
@SuppressWarnings("unchecked")
public void clear() { public void clear() {
if ( isClearQueueEnabled() ) { if ( isClearQueueEnabled() ) {
queueOperation( new Clear() ); queueOperation( new Clear() );
@ -290,7 +291,6 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
@Override @Override
@SuppressWarnings("unchecked")
public Object get(int index) { public Object get(int index) {
if ( index < 0 ) { if ( index < 0 ) {
throw new ArrayIndexOutOfBoundsException( "negative index" ); throw new ArrayIndexOutOfBoundsException( "negative index" );
@ -300,7 +300,6 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
@Override @Override
@SuppressWarnings("unchecked")
public Object set(int index, Object value) { public Object set(int index, Object value) {
if (index<0) { if (index<0) {
throw new ArrayIndexOutOfBoundsException("negative index"); throw new ArrayIndexOutOfBoundsException("negative index");
@ -310,6 +309,7 @@ public class PersistentList extends AbstractPersistentCollection implements List
if ( old==UNKNOWN ) { if ( old==UNKNOWN ) {
write(); write();
//noinspection unchecked
return list.set( index, value ); return list.set( index, value );
} }
else { else {
@ -319,7 +319,6 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
@Override @Override
@SuppressWarnings("unchecked")
public Object remove(int index) { public Object remove(int index) {
if ( index < 0 ) { if ( index < 0 ) {
throw new ArrayIndexOutOfBoundsException( "negative index" ); throw new ArrayIndexOutOfBoundsException( "negative index" );
@ -338,45 +337,40 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
@Override @Override
@SuppressWarnings("unchecked")
public void add(int index, Object value) { public void add(int index, Object value) {
if ( index < 0 ) { if ( index < 0 ) {
throw new ArrayIndexOutOfBoundsException( "negative index" ); throw new ArrayIndexOutOfBoundsException( "negative index" );
} }
write(); write();
//noinspection unchecked
list.add( index, value ); list.add( index, value );
} }
@Override @Override
@SuppressWarnings("unchecked")
public int indexOf(Object value) { public int indexOf(Object value) {
read(); read();
return list.indexOf( value ); return list.indexOf( value );
} }
@Override @Override
@SuppressWarnings("unchecked")
public int lastIndexOf(Object value) { public int lastIndexOf(Object value) {
read(); read();
return list.lastIndexOf( value ); return list.lastIndexOf( value );
} }
@Override @Override
@SuppressWarnings("unchecked")
public ListIterator listIterator() { public ListIterator listIterator() {
read(); read();
return new ListIteratorProxy( list.listIterator() ); return new ListIteratorProxy( list.listIterator() );
} }
@Override @Override
@SuppressWarnings("unchecked")
public ListIterator listIterator(int index) { public ListIterator listIterator(int index) {
read(); read();
return new ListIteratorProxy( list.listIterator( index ) ); return new ListIteratorProxy( list.listIterator( index ) );
} }
@Override @Override
@SuppressWarnings("unchecked")
public java.util.List subList(int from, int to) { public java.util.List subList(int from, int to) {
read(); read();
return new ListProxy( list.subList( from, to ) ); return new ListProxy( list.subList( from, to ) );
@ -409,6 +403,32 @@ public class PersistentList extends AbstractPersistentCollection implements List
return element; return element;
} }
@Override
public Object readFrom(
RowProcessingState rowProcessingState,
DomainResultAssembler elementAssembler,
DomainResultAssembler indexAssembler,
DomainResultAssembler identifierAssembler,
Object owner) throws HibernateException {
assert elementAssembler != null;
assert indexAssembler != null;
assert identifierAssembler == null;
final Object element = elementAssembler.assemble( rowProcessingState );
final int index = (int) indexAssembler.assemble( rowProcessingState );
//pad with nulls from the current last element up to the new index
for ( int i = list.size(); i<=index; i++) {
//noinspection unchecked
list.add( i, null );
}
//noinspection unchecked
list.set( index, element );
return element;
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Iterator entries(CollectionPersister persister) { public Iterator entries(CollectionPersister persister) {

View File

@ -22,6 +22,8 @@ import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.CollectionAliases; import org.hibernate.loader.CollectionAliases;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.RowProcessingState;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -176,7 +178,6 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
} }
@Override @Override
@SuppressWarnings("unchecked")
public Object put(Object key, Object value) { public Object put(Object key, Object value) {
if ( isPutQueueEnabled() ) { if ( isPutQueueEnabled() ) {
final Object old = readElementByIndex( key ); final Object old = readElementByIndex( key );
@ -186,6 +187,7 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
} }
} }
initialize( true ); initialize( true );
//noinspection unchecked
final Object old = map.put( key, value ); final Object old = map.put( key, value );
// would be better to use the element-type to determine // would be better to use the element-type to determine
// whether the old and the new are equal here; the problem being // whether the old and the new are equal here; the problem being
@ -198,7 +200,6 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
} }
@Override @Override
@SuppressWarnings("unchecked")
public Object remove(Object key) { public Object remove(Object key) {
if ( isPutQueueEnabled() ) { if ( isPutQueueEnabled() ) {
final Object old = readElementByIndex( key ); final Object old = readElementByIndex( key );
@ -218,7 +219,6 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
} }
@Override @Override
@SuppressWarnings("unchecked")
public void putAll(Map puts) { public void putAll(Map puts) {
if ( puts.size() > 0 ) { if ( puts.size() > 0 ) {
initialize( true ); initialize( true );
@ -230,7 +230,6 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
} }
@Override @Override
@SuppressWarnings("unchecked")
public void clear() { public void clear() {
if ( isClearQueueEnabled() ) { if ( isClearQueueEnabled() ) {
queueOperation( new Clear() ); queueOperation( new Clear() );
@ -245,34 +244,29 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
} }
@Override @Override
@SuppressWarnings("unchecked")
public Set keySet() { public Set keySet() {
read(); read();
return new SetProxy( map.keySet() ); return new SetProxy( map.keySet() );
} }
@Override @Override
@SuppressWarnings("unchecked")
public Collection values() { public Collection values() {
read(); read();
return new SetProxy( map.values() ); return new SetProxy( map.values() );
} }
@Override @Override
@SuppressWarnings("unchecked")
public Set entrySet() { public Set entrySet() {
read(); read();
return new EntrySetProxy( map.entrySet() ); return new EntrySetProxy( map.entrySet() );
} }
@Override @Override
@SuppressWarnings("unchecked")
public boolean empty() { public boolean empty() {
return map.isEmpty(); return map.isEmpty();
} }
@Override @Override
@SuppressWarnings("unchecked")
public String toString() { public String toString() {
read(); read();
return map.toString(); return map.toString();
@ -281,7 +275,6 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
private transient List<Object[]> loadingEntries; private transient List<Object[]> loadingEntries;
@Override @Override
@SuppressWarnings("unchecked")
public Object readFrom( public Object readFrom(
ResultSet rs, ResultSet rs,
CollectionPersister persister, CollectionPersister persister,
@ -298,6 +291,30 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
return element; return element;
} }
@Override
public Object readFrom(
RowProcessingState rowProcessingState,
DomainResultAssembler elementAssembler,
DomainResultAssembler indexAssembler,
DomainResultAssembler identifierAssembler,
Object owner) throws HibernateException {
assert elementAssembler != null;
assert indexAssembler != null;
assert identifierAssembler == null;
final Object element = elementAssembler.assemble( rowProcessingState );
if ( element != null ) {
final Object index = indexAssembler.assemble( rowProcessingState );
if ( loadingEntries == null ) {
loadingEntries = new ArrayList<>();
}
loadingEntries.add( new Object[] { index, element } );
}
return element;
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public boolean endRead() { public boolean endRead() {

View File

@ -21,6 +21,8 @@ import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.CollectionAliases; import org.hibernate.loader.CollectionAliases;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.RowProcessingState;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -342,6 +344,27 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
return element; return element;
} }
@Override
public Object readFrom(
RowProcessingState rowProcessingState,
DomainResultAssembler elementAssembler,
DomainResultAssembler indexAssembler,
DomainResultAssembler identifierAssembler,
Object owner) throws HibernateException {
assert elementAssembler != null;
assert indexAssembler == null;
assert identifierAssembler == null;
final Object element = elementAssembler.assemble( rowProcessingState );
if ( element != null ) {
//noinspection unchecked
tempList.add( element );
}
return element;
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void beginRead() { public void beginRead() {

View File

@ -0,0 +1,84 @@
/*
* 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.collection.internal;
import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.collection.spi.CollectionSemanticsResolver;
import org.hibernate.mapping.Array;
import org.hibernate.mapping.Bag;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.IdentifierBag;
import org.hibernate.mapping.List;
import org.hibernate.mapping.Map;
import org.hibernate.mapping.PrimitiveArray;
import org.hibernate.mapping.Set;
/**
* Standard implementation of CollectionSemanticsResolver
*
* @author Steve Ebersole
*/
public class StandardCollectionSemanticsResolver implements CollectionSemanticsResolver {
/**
* Singleton access
*/
public static final StandardCollectionSemanticsResolver INSTANCE = new StandardCollectionSemanticsResolver();
@Override
public CollectionSemantics resolveRepresentation(Collection bootDescriptor) {
if ( bootDescriptor instanceof PrimitiveArray ) {
throw new NotYetImplementedFor6Exception();
}
if ( bootDescriptor instanceof Array ) {
return StandardArraySemantics.INSTANCE;
}
if ( bootDescriptor instanceof Bag ) {
return StandardBagSemantics.INSTANCE;
}
if ( bootDescriptor instanceof IdentifierBag ) {
return StandardIdentifierBagSemantics.INSTANCE;
}
if ( bootDescriptor instanceof List ) {
return StandardListSemantics.INSTANCE;
}
if ( bootDescriptor instanceof Map ) {
if ( bootDescriptor.isSorted() ) {
return StandardSortedMapSemantics.INSTANCE;
}
if ( bootDescriptor.hasOrder() ) {
return StandardOrderedMapSemantics.INSTANCE;
}
return StandardMapSemantics.INSTANCE;
}
if ( bootDescriptor instanceof Set ) {
if ( bootDescriptor.isSorted() ) {
return StandardSortedSetSemantics.INSTANCE;
}
if ( bootDescriptor.hasOrder() ) {
return StandardOrderedSetSemantics.INSTANCE;
}
return StandardSetSemantics.INSTANCE;
}
throw new MappingException(
"Unexpected org.hibernate.mapping.Collection impl ["
+ bootDescriptor + "]; unknown CollectionSemantics"
);
}
}

View File

@ -9,6 +9,7 @@ package org.hibernate.collection.spi;
import java.util.Iterator; import java.util.Iterator;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.Incubating;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.CollectionClassification; import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
@ -22,6 +23,7 @@ import org.hibernate.persister.collection.CollectionPersister;
* @author Steve Ebersole * @author Steve Ebersole
* @author Gavin King * @author Gavin King
*/ */
@Incubating
public interface CollectionSemantics<C> { public interface CollectionSemantics<C> {
/** /**
* Get the classification of collections described by this semantic * Get the classification of collections described by this semantic

View File

@ -6,9 +6,12 @@
*/ */
package org.hibernate.collection.spi; package org.hibernate.collection.spi;
import org.hibernate.Incubating;
import org.hibernate.mapping.Collection; import org.hibernate.mapping.Collection;
/** /**
* Resolve the collection semantics for the given mapped collection
*
* todo (6.0) ... * todo (6.0) ...
* *
* Ideally would act as the contract that allows pluggable resolution of * Ideally would act as the contract that allows pluggable resolution of
@ -17,6 +20,7 @@ import org.hibernate.mapping.Collection;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@Incubating
public interface CollectionSemanticsResolver { public interface CollectionSemanticsResolver {
// really need some form of access to the attribute site // really need some form of access to the attribute site
CollectionSemantics resolveRepresentation(Collection bootDescriptor); CollectionSemantics resolveRepresentation(Collection bootDescriptor);

View File

@ -16,6 +16,8 @@ import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.loader.CollectionAliases; import org.hibernate.loader.CollectionAliases;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.RowProcessingState;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
@ -173,6 +175,13 @@ public interface PersistentCollection {
Object readFrom(ResultSet rs, CollectionPersister role, CollectionAliases descriptor, Object owner) Object readFrom(ResultSet rs, CollectionPersister role, CollectionAliases descriptor, Object owner)
throws HibernateException, SQLException; throws HibernateException, SQLException;
Object readFrom(
RowProcessingState rowProcessingState,
DomainResultAssembler elementAssembler,
DomainResultAssembler indexAssembler,
DomainResultAssembler identifierAssembler,
Object owner) throws HibernateException;
/** /**
* Get the identifier of the given collection entry. This refers to the collection identifier, not the * Get the identifier of the given collection entry. This refers to the collection identifier, not the
* identifier of the (possibly) entity elements. This is only valid for invocation on the * identifier of the (possibly) entity elements. This is only valid for invocation on the

View File

@ -0,0 +1,25 @@
/*
* 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.metamodel.CollectionClassification;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultCreationState;
/**
* Descriptor for the collection identifier. Only used with {@link CollectionClassification#IDBAG} collections
*
* @author Steve Ebersole
*/
public interface CollectionIdentifierDescriptor {
DomainResult createDomainResult(
NavigablePath collectionPath,
TableGroup tableGroup,
DomainResultCreationState creationState);
}

View File

@ -15,5 +15,5 @@ import org.hibernate.collection.spi.CollectionSemantics;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface CollectionMappingType<C> extends MappingType { public interface CollectionMappingType<C> extends MappingType {
CollectionSemantics<C> getCCollectionSemantics(); CollectionSemantics<C> getCollectionSemantics();
} }

View File

@ -0,0 +1,48 @@
/*
* 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.sql.results.spi.Fetchable;
/**
* @author Steve Ebersole
*/
public interface CollectionPart extends ModelPart, Fetchable {
enum Nature {
ELEMENT( "{element}" ),
INDEX( "{index}" );
private final String name;
Nature(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static Nature fromName(String name) {
if ( ELEMENT.name.equals( name ) ) {
return ELEMENT;
}
else if ( INDEX.name.equals( name ) ) {
return INDEX;
}
throw new IllegalArgumentException(
"Unrecognized CollectionPart Nature name [" + name
+ "]; expecting `" + ELEMENT.name + "` or `"
+ INDEX.name + "`"
);
}
}
Nature getNature();
ModelPart getPartTypeDescriptor();
}

View File

@ -102,6 +102,7 @@ public class EmbeddableMappingType implements ManagedMappingType {
CompositeType compositeType, CompositeType compositeType,
MappingModelCreationProcess creationProcess) { MappingModelCreationProcess creationProcess) {
final String containingTableExpression = valueMapping.getContainingTableExpression(); final String containingTableExpression = valueMapping.getContainingTableExpression();
final List<String> mappedColumnExpressions = valueMapping.getMappedColumnExpressions(); final List<String> mappedColumnExpressions = valueMapping.getMappedColumnExpressions();
final Type[] subtypes = compositeType.getSubtypes(); final Type[] subtypes = compositeType.getSubtypes();
@ -196,6 +197,11 @@ public class EmbeddableMappingType implements ManagedMappingType {
throw new NotYetImplementedFor6Exception( getClass() ); throw new NotYetImplementedFor6Exception( getClass() );
} }
@Override
public int getNumberOfFetchables() {
return attributeMappings.size();
}
@Override @Override
public void visitFetchables( public void visitFetchables(
Consumer<Fetchable> fetchableConsumer, Consumer<Fetchable> fetchableConsumer,

View File

@ -14,12 +14,13 @@ import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer; import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
import org.hibernate.sql.results.spi.Fetchable;
import org.hibernate.sql.results.spi.FetchableContainer; import org.hibernate.sql.results.spi.FetchableContainer;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface EmbeddableValuedModelPart extends ModelPart, FetchableContainer, TableGroupJoinProducer { public interface EmbeddableValuedModelPart extends ModelPart, Fetchable, FetchableContainer, TableGroupJoinProducer {
EmbeddableMappingType getEmbeddableTypeDescriptor(); EmbeddableMappingType getEmbeddableTypeDescriptor();
/** /**

View File

@ -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.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultCreationState;
/**
* @author Steve Ebersole
*/
public interface ForeignKeyDescriptor {
DomainResult createDomainResult(NavigablePath collectionPath, TableGroup tableGroup, DomainResultCreationState creationState);
}

View File

@ -6,15 +6,39 @@
*/ */
package org.hibernate.metamodel.mapping; package org.hibernate.metamodel.mapping;
import java.util.function.Consumer;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
import org.hibernate.sql.results.spi.Fetchable;
import org.hibernate.sql.results.spi.FetchableContainer;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface PluralAttributeMapping extends AttributeMapping, StateArrayContributorMapping { public interface PluralAttributeMapping
extends AttributeMapping, StateArrayContributorMapping, TableGroupJoinProducer, FetchableContainer {
CollectionPersister getCollectionDescriptor(); CollectionPersister getCollectionDescriptor();
ModelPart getValueDescriptor(); ForeignKeyDescriptor getKeyDescriptor();
ModelPart getIndexDescriptor(); CollectionPart getIndexDescriptor();
CollectionPart getElementDescriptor();
CollectionIdentifierDescriptor getIdentifierDescriptor();
@Override
default void visitKeyFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
final CollectionPart indexDescriptor = getIndexDescriptor();
if ( indexDescriptor != null ) {
fetchableConsumer.accept( indexDescriptor );
}
}
@Override
default void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
fetchableConsumer.accept( getElementDescriptor() );
}
} }

View File

@ -13,14 +13,17 @@ import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.BasicValuedModelPart; import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter; import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.sql.SqlExpressionResolver; import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.SqlResultsLogger;
import org.hibernate.sql.results.internal.domain.basic.BasicFetch; import org.hibernate.sql.results.internal.domain.basic.BasicFetch;
import org.hibernate.sql.results.internal.domain.basic.BasicResult; import org.hibernate.sql.results.internal.domain.basic.BasicResult;
import org.hibernate.sql.results.spi.DomainResult; import org.hibernate.sql.results.spi.DomainResult;
@ -36,13 +39,24 @@ import org.hibernate.type.spi.TypeConfiguration;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class BasicValuedCollectionPart implements BasicValuedModelPart { public class BasicValuedCollectionPart implements CollectionPart, BasicValuedModelPart {
private final CollectionPersister collectionDescriptor;
private final Nature nature;
private final BasicType mapper;
private final BasicValueConverter valueConverter;
private final String tableExpression;
private final String columnExpression;
public BasicValuedCollectionPart( public BasicValuedCollectionPart(
CollectionPersister collectionDescriptor,
Nature nature, Nature nature,
BasicType mapper, BasicType mapper,
BasicValueConverter valueConverter, BasicValueConverter valueConverter,
String tableExpression, String tableExpression,
String columnExpression) { String columnExpression) {
this.collectionDescriptor = collectionDescriptor;
this.nature = nature; this.nature = nature;
this.mapper = mapper; this.mapper = mapper;
this.valueConverter = valueConverter; this.valueConverter = valueConverter;
@ -50,14 +64,15 @@ public class BasicValuedCollectionPart implements BasicValuedModelPart {
this.columnExpression = columnExpression; this.columnExpression = columnExpression;
} }
enum Nature { ELEMENT, INDEX } @Override
public Nature getNature() {
return nature;
}
private final Nature nature; @Override
private final BasicType mapper; public BasicType getPartTypeDescriptor() {
private final BasicValueConverter valueConverter; return mapper;
}
private final String tableExpression;
private final String columnExpression;
@Override @Override
public String getContainingTableExpression() { public String getContainingTableExpression() {
@ -91,7 +106,9 @@ public class BasicValuedCollectionPart implements BasicValuedModelPart {
return new BasicResult( return new BasicResult(
sqlSelection.getValuesArrayPosition(), sqlSelection.getValuesArrayPosition(),
resultVariable, resultVariable,
getJavaTypeDescriptor() getJavaTypeDescriptor(),
valueConverter,
navigablePath
); );
} }
@ -100,9 +117,9 @@ public class BasicValuedCollectionPart implements BasicValuedModelPart {
return exprResolver.resolveSqlSelection( return exprResolver.resolveSqlSelection(
exprResolver.resolveSqlExpression( exprResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( tableExpression, columnExpression ), SqlExpressionResolver.createColumnReferenceKey( tableGroup.getPrimaryTableReference(), columnExpression ),
sqlAstProcessingState -> new ColumnReference( sqlAstProcessingState -> new ColumnReference(
tableGroup.resolveTableReference( tableExpression ).getIdentificationVariable(), tableGroup.getPrimaryTableReference().getIdentificationVariable(),
columnExpression, columnExpression,
mapper, mapper,
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory() creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
@ -148,6 +165,12 @@ public class BasicValuedCollectionPart implements BasicValuedModelPart {
LockMode lockMode, LockMode lockMode,
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
SqlResultsLogger.INSTANCE.debugf(
"Generating Fetch for collection-part : `%s` -> `%s`",
collectionDescriptor.getRole(),
nature.getName()
);
final SqlSelection sqlSelection = resolveSqlSelection( final SqlSelection sqlSelection = resolveSqlSelection(
creationState.getSqlAstCreationState().getFromClauseAccess().findTableGroup( fetchablePath.getParent() ), creationState.getSqlAstCreationState().getFromClauseAccess().findTableGroup( fetchablePath.getParent() ),
creationState creationState

View File

@ -0,0 +1,83 @@
/*
* 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.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
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.BasicResult;
import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultCreationState;
import org.hibernate.type.BasicType;
/**
* @author Steve Ebersole
*/
public class CollectionIdentifierDescriptorImpl implements CollectionIdentifierDescriptor {
private final CollectionPersister collectionDescriptor;
private final String columnName;
private final BasicType type;
public CollectionIdentifierDescriptorImpl(
CollectionPersister collectionDescriptor,
String columnName,
BasicType type) {
this.collectionDescriptor = collectionDescriptor;
this.columnName = columnName;
this.type = type;
}
@Override
public DomainResult createDomainResult(
NavigablePath collectionPath,
TableGroup tableGroup,
DomainResultCreationState creationState) {
final SqlAstCreationState astCreationState = creationState.getSqlAstCreationState();
final SqlAstCreationContext astCreationContext = astCreationState.getCreationContext();
final SessionFactoryImplementor sessionFactory = astCreationContext.getSessionFactory();
final SqlExpressionResolver sqlExpressionResolver = astCreationState.getSqlExpressionResolver();
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
tableGroup.getPrimaryTableReference(),
columnName
),
p -> new ColumnReference(
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
columnName,
type,
sessionFactory
)
),
type.getJavaTypeDescriptor(),
sessionFactory.getTypeConfiguration()
);
//noinspection unchecked
return new BasicResult(
sqlSelection.getValuesArrayPosition(),
null,
type.getJavaTypeDescriptor(),
collectionPath
);
}
@Override
public String toString() {
return getClass().getSimpleName() + "(" + collectionDescriptor.getRole() + ")";
}
}

View File

@ -31,6 +31,7 @@ import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.JoinType; import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator; import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
@ -39,7 +40,9 @@ import org.hibernate.sql.ast.tree.expression.SqlTuple;
import org.hibernate.sql.ast.tree.from.CompositeTableGroup; import org.hibernate.sql.ast.tree.from.CompositeTableGroup;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin; import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableGroupProducer;
import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
import org.hibernate.sql.results.internal.domain.composite.CompositeFetch; import org.hibernate.sql.results.internal.domain.composite.CompositeFetch;
import org.hibernate.sql.results.internal.domain.composite.CompositeResult; import org.hibernate.sql.results.internal.domain.composite.CompositeResult;
import org.hibernate.sql.results.spi.DomainResult; import org.hibernate.sql.results.spi.DomainResult;
@ -162,6 +165,7 @@ public class EmbeddedAttributeMapping
this, this,
fetchParent, fetchParent,
fetchTiming, fetchTiming,
getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
creationState creationState
); );
} }
@ -245,8 +249,44 @@ public class EmbeddedAttributeMapping
); );
} }
@Override
public void applyTableReferences(
SqlAliasBase sqlAliasBase,
JoinType baseJoinType,
TableReferenceCollector collector,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
getEmbeddableTypeDescriptor().visitAttributeMappings(
attrMapping -> {
if ( attrMapping instanceof TableGroupProducer ) {
( (TableGroupProducer) attrMapping ).applyTableReferences(
sqlAliasBase,
baseJoinType,
collector,
sqlExpressionResolver,
creationContext
);
}
else if ( attrMapping.getMappedTypeDescriptor() instanceof TableGroupProducer ) {
( (TableGroupProducer) attrMapping.getMappedTypeDescriptor() ).applyTableReferences(
sqlAliasBase,
baseJoinType,
collector,
sqlExpressionResolver,
creationContext
);
}
}
);
}
@Override @Override
public String getSqlAliasStem() { public String getSqlAliasStem() {
return getAttributeName(); return getAttributeName();
} }
@Override
public int getNumberOfFetchables() {
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
}
} }

View File

@ -0,0 +1,189 @@
/*
* 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.List;
import java.util.function.Consumer;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
import org.hibernate.sql.results.internal.domain.composite.CompositeFetch;
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.descriptor.java.JavaTypeDescriptor;
/**
* @author Steve Ebersole
*/
public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedModelPart {
private final CollectionPersister collectionDescriptor;
private final Nature nature;
private final EmbeddableMappingType embeddableMappingType;
private final String containingTableExpression;
private final SingularAttributeMapping parentInjectionAttribute;
private final List<String> columnExpressions;
private final String sqlAliasStem;
@SuppressWarnings("WeakerAccess")
public EmbeddedCollectionPart(
CollectionPersister collectionDescriptor,
Nature nature,
EmbeddableMappingType embeddableMappingType,
SingularAttributeMapping parentInjectionAttribute,
String containingTableExpression,
List<String> columnExpressions,
String sqlAliasStem) {
this.collectionDescriptor = collectionDescriptor;
this.nature = nature;
this.embeddableMappingType = embeddableMappingType;
this.parentInjectionAttribute = parentInjectionAttribute;
this.containingTableExpression = containingTableExpression;
this.columnExpressions = columnExpressions;
this.sqlAliasStem = sqlAliasStem;
}
@Override
public Nature getNature() {
return nature;
}
@Override
public EmbeddableMappingType getEmbeddableTypeDescriptor() {
return embeddableMappingType;
}
@Override
public EmbeddableMappingType getPartTypeDescriptor() {
return getEmbeddableTypeDescriptor();
}
@Override
public String getContainingTableExpression() {
return containingTableExpression;
}
@Override
public List<String> getMappedColumnExpressions() {
return columnExpressions;
}
@Override
public SingularAttributeMapping getParentInjectionAttributeMapping() {
return parentInjectionAttribute;
}
@Override
public String getFetchableName() {
return getNature().getName();
}
@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) {
return new CompositeFetch(
fetchablePath,
this,
fetchParent,
FetchTiming.IMMEDIATE,
false,
creationState
);
}
@Override
public Expression toSqlExpression(
TableGroup tableGroup,
Clause clause,
SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) {
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
public TableGroupJoin createTableGroupJoin(
NavigablePath navigablePath,
TableGroup lhs,
String explicitSourceAlias,
JoinType joinType,
LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
public void applyTableReferences(
SqlAliasBase sqlAliasBase,
JoinType baseJoinType,
TableReferenceCollector collector,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
public String getSqlAliasStem() {
return sqlAliasStem;
}
@Override
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
return getEmbeddableTypeDescriptor().findSubPart( name, treatTargetType );
}
@Override
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
getEmbeddableTypeDescriptor().visitSubParts( consumer, treatTargetType );
}
@Override
public JavaTypeDescriptor getJavaTypeDescriptor() {
return getEmbeddableTypeDescriptor().getJavaTypeDescriptor();
}
@Override
public int getNumberOfFetchables() {
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
}
}

View File

@ -0,0 +1,81 @@
/*
* 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.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.query.NavigablePath;
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.descriptor.java.JavaTypeDescriptor;
/**
* @author Steve Ebersole
*/
public class EntityCollectionPart implements CollectionPart, EntityValuedModelPart {
private final Nature nature;
private final EntityMappingType entityMappingType;
@SuppressWarnings("WeakerAccess")
public EntityCollectionPart(Nature nature, EntityMappingType entityMappingType) {
this.nature = nature;
this.entityMappingType = entityMappingType;
}
@Override
public Nature getNature() {
return nature;
}
@Override
public EntityMappingType getPartTypeDescriptor() {
return getEntityMappingType();
}
@Override
public EntityMappingType getEntityMappingType() {
return entityMappingType;
}
@Override
public JavaTypeDescriptor getJavaTypeDescriptor() {
return getEntityMappingType().getJavaTypeDescriptor();
}
@Override
public String getFetchableName() {
return nature.getName();
}
@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) {
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
public int getNumberOfFetchables() {
return entityMappingType.getNumberOfFetchables();
}
}

View File

@ -7,6 +7,10 @@
package org.hibernate.metamodel.mapping.internal; package org.hibernate.metamodel.mapping.internal;
import java.io.Serializable; import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.LockMode; import org.hibernate.LockMode;
@ -16,36 +20,35 @@ import org.hibernate.collection.internal.StandardArraySemantics;
import org.hibernate.collection.internal.StandardBagSemantics; import org.hibernate.collection.internal.StandardBagSemantics;
import org.hibernate.collection.internal.StandardIdentifierBagSemantics; import org.hibernate.collection.internal.StandardIdentifierBagSemantics;
import org.hibernate.collection.internal.StandardListSemantics; 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.collection.spi.CollectionSemantics;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.Array; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.Bag;
import org.hibernate.mapping.BasicValue; import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Collection; import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Component; import org.hibernate.mapping.Component;
import org.hibernate.mapping.IdentifierBag; import org.hibernate.mapping.IndexedCollection;
import org.hibernate.mapping.List; import org.hibernate.mapping.OneToMany;
import org.hibernate.mapping.Map;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.PrimitiveArray;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.mapping.Set; import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping; import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
import org.hibernate.metamodel.mapping.BasicValuedMapping; import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.BasicValuedModelPart; import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
import org.hibernate.metamodel.mapping.CollectionMappingType; import org.hibernate.metamodel.mapping.CollectionMappingType;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ManagedMappingType; import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.mapping.MappingType;
@ -54,15 +57,19 @@ import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.StateArrayContributorMetadata; import org.hibernate.metamodel.mapping.StateArrayContributorMetadata;
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess; import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter; import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.metamodel.spi.DomainMetamodel;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.SQLLoadableCollection;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.persister.walking.internal.FetchStrategyHelper; import org.hibernate.persister.walking.internal.FetchStrategyHelper;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.sql.SqlExpressionResolver; import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.spi.SqlSelection;
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;
@ -76,6 +83,7 @@ import org.hibernate.sql.results.spi.Fetch;
import org.hibernate.sql.results.spi.FetchParent; import org.hibernate.sql.results.spi.FetchParent;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan; import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.MutabilityPlan;
@ -622,75 +630,152 @@ public class MappingModelCreationHelper {
final Collection bootValueMapping = (Collection) bootProperty.getValue(); final Collection bootValueMapping = (Collection) bootProperty.getValue();
final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext(); final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext();
final CollectionPersister collectionDescriptor = creationContext.getDomainModel().findCollectionDescriptor( bootValueMapping.getRole() ); final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
final Dialect dialect = sessionFactory.getJdbcServices().getJdbcEnvironment().getDialect();
final DomainMetamodel domainModel = creationContext.getDomainModel();
final CollectionPersister collectionDescriptor = domainModel.findCollectionDescriptor( bootValueMapping.getRole() );
assert collectionDescriptor != null; assert collectionDescriptor != null;
tableExpression = ( (Joinable) collectionDescriptor ).getTableName();
final String sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( bootProperty.getName() );
final CollectionMappingType<?> collectionMappingType; final CollectionMappingType<?> collectionMappingType;
final JavaTypeDescriptorRegistry jtdRegistry = creationContext.getJavaTypeDescriptorRegistry(); final JavaTypeDescriptorRegistry jtdRegistry = creationContext.getJavaTypeDescriptorRegistry();
if ( bootValueMapping instanceof Array ) { final ForeignKeyDescriptor keyDescriptor = interpretKeyDescriptor(
if ( bootValueMapping instanceof PrimitiveArray ) { bootProperty,
throw new NotYetImplementedFor6Exception(); bootValueMapping,
} dialect,
else { creationProcess
);
final CollectionPart elementDescriptor = interpretElement(
bootValueMapping,
tableExpression,
collectionDescriptor,
sqlAliasStem,
dialect,
creationProcess
);
final CollectionPart indexDescriptor;
CollectionIdentifierDescriptor identifierDescriptor = null;
final CollectionSemantics collectionSemantics = collectionDescriptor.getCollectionSemantics();
switch ( collectionSemantics.getCollectionClassification() ) {
case ARRAY: {
collectionMappingType = new CollectionMappingTypeImpl( collectionMappingType = new CollectionMappingTypeImpl(
jtdRegistry.getDescriptor( Object[].class ), jtdRegistry.getDescriptor( Object[].class ),
StandardArraySemantics.INSTANCE StandardArraySemantics.INSTANCE
); );
final BasicValue index = (BasicValue) ( (IndexedCollection) bootValueMapping ).getIndex();
indexDescriptor = new BasicValuedCollectionPart(
collectionDescriptor,
CollectionPart.Nature.INDEX,
creationContext.getTypeConfiguration().getBasicTypeForJavaType( Integer.class ),
// no converter
null,
tableExpression,
index.getColumnIterator().next().getText( dialect )
);
break;
} }
} case BAG: {
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( collectionMappingType = new CollectionMappingTypeImpl(
jtdRegistry.getDescriptor( java.util.SortedMap.class ), jtdRegistry.getDescriptor( java.util.Collection.class ),
StandardSortedMapSemantics.INSTANCE StandardBagSemantics.INSTANCE
);
indexDescriptor = null;
break;
}
case IDBAG: {
collectionMappingType = new CollectionMappingTypeImpl(
jtdRegistry.getDescriptor( java.util.Collection.class ),
StandardIdentifierBagSemantics.INSTANCE
);
indexDescriptor = null;
assert collectionDescriptor instanceof SQLLoadableCollection;
final SQLLoadableCollection loadableCollection = (SQLLoadableCollection) collectionDescriptor;
final String identifierColumnName = loadableCollection.getIdentifierColumnName();
assert identifierColumnName != null;
identifierDescriptor = new CollectionIdentifierDescriptorImpl(
collectionDescriptor,
identifierColumnName,
(BasicType) loadableCollection.getIdentifierType()
);
break;
}
case LIST: {
final BasicValue index = (BasicValue) ( (IndexedCollection) bootValueMapping ).getIndex();
indexDescriptor = new BasicValuedCollectionPart(
collectionDescriptor,
CollectionPart.Nature.INDEX,
creationContext.getTypeConfiguration().getBasicTypeForJavaType( Integer.class ),
// no converter
null,
tableExpression,
index.getColumnIterator().next().getText( dialect )
);
collectionMappingType = new CollectionMappingTypeImpl(
jtdRegistry.getDescriptor( java.util.List.class ),
StandardListSemantics.INSTANCE
);
break;
}
case MAP:
case ORDERED_MAP:
case SORTED_MAP: {
final Class<? extends java.util.Map> mapJavaType = collectionSemantics.getCollectionClassification() == CollectionClassification.SORTED_MAP
? SortedMap.class
: java.util.Map.class;
collectionMappingType = new CollectionMappingTypeImpl(
jtdRegistry.getDescriptor( mapJavaType ),
collectionSemantics
);
indexDescriptor = interpretMapKey(
bootValueMapping,
collectionDescriptor,
tableExpression,
sqlAliasStem,
dialect,
creationProcess
);
break;
}
case SET:
case ORDERED_SET:
case SORTED_SET: {
final Class<? extends java.util.Set> setJavaType = collectionSemantics.getCollectionClassification() == CollectionClassification.SORTED_MAP
? SortedSet.class
: java.util.Set.class;
collectionMappingType = new CollectionMappingTypeImpl(
jtdRegistry.getDescriptor( setJavaType ),
collectionSemantics
);
indexDescriptor = null;
break;
}
default: {
throw new MappingException(
"Unexpected CollectionClassification : " + collectionSemantics.getCollectionClassification()
); );
} }
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() { final StateArrayContributorMetadata contributorMetadata = new StateArrayContributorMetadata() {
@ -733,7 +818,7 @@ public class MappingModelCreationHelper {
final FetchStyle style = FetchStrategyHelper.determineFetchStyleByMetadata( final FetchStyle style = FetchStrategyHelper.determineFetchStyleByMetadata(
( (OuterJoinLoadable) declaringType ).getFetchMode( stateArrayPosition ), ( (OuterJoinLoadable) declaringType ).getFetchMode( stateArrayPosition ),
collectionDescriptor.getCollectionType(), collectionDescriptor.getCollectionType(),
creationContext.getSessionFactory() sessionFactory
); );
return new PluralAttributeMappingImpl( return new PluralAttributeMappingImpl(
@ -742,15 +827,15 @@ public class MappingModelCreationHelper {
entityMappingType -> contributorMetadata, entityMappingType -> contributorMetadata,
collectionMappingType, collectionMappingType,
stateArrayPosition, stateArrayPosition,
tableExpression, keyDescriptor,
attrColumnExpressions, elementDescriptor,
null, indexDescriptor,
null, identifierDescriptor,
new FetchStrategy( new FetchStrategy(
FetchStrategyHelper.determineFetchTiming( FetchStrategyHelper.determineFetchTiming(
style, style,
collectionDescriptor.getCollectionType(), collectionDescriptor.getCollectionType(),
creationContext.getSessionFactory() sessionFactory
), ),
style style
), ),
@ -760,6 +845,156 @@ public class MappingModelCreationHelper {
); );
} }
private static ForeignKeyDescriptor interpretKeyDescriptor(
Property bootProperty,
Collection bootValueMapping,
Dialect dialect,
MappingModelCreationProcess creationProcess) {
final Type keyType = bootValueMapping.getKey().getType();
if ( keyType instanceof BasicType ) {
assert bootValueMapping.getKey().getColumnSpan() == 1;
return new SimpleForeignKeyDescriptor(
bootValueMapping.getKey().getColumnIterator().next().getText( dialect ),
(BasicType) keyType
);
}
throw new NotYetImplementedFor6Exception(
"Support for composite collection foreign-keys not yet implemented: " + bootValueMapping.getRole()
);
}
private static CollectionPart interpretMapKey(
Collection bootValueMapping,
CollectionPersister collectionDescriptor,
String tableExpression,
String sqlAliasStem,
Dialect dialect,
MappingModelCreationProcess creationProcess) {
assert bootValueMapping instanceof IndexedCollection;
final IndexedCollection indexedCollection = (IndexedCollection) bootValueMapping;
final Value bootMapKeyDescriptor = indexedCollection.getIndex();
if ( bootMapKeyDescriptor instanceof BasicValue ) {
final BasicValue basicValue = (BasicValue) bootMapKeyDescriptor;
return new BasicValuedCollectionPart(
collectionDescriptor,
CollectionPart.Nature.INDEX,
basicValue.resolve().getResolvedBasicType(),
basicValue.resolve().getValueConverter(),
tableExpression,
basicValue.getColumnIterator().next().getText( dialect )
);
}
if ( bootMapKeyDescriptor instanceof Component ) {
final Component component = (Component) bootMapKeyDescriptor;
final CompositeType compositeType = (CompositeType) component.getType();
final List<String> columnExpressions = CollectionHelper.arrayList( component.getColumnSpan() );
final Iterator<Selectable> columnIterator = component.getColumnIterator();
while ( columnIterator.hasNext() ) {
columnExpressions.add( columnIterator.next().getText( dialect ) );
}
final EmbeddableMappingType mappingType = EmbeddableMappingType.from(
component,
compositeType,
inflightDescriptor -> new EmbeddedCollectionPart(
collectionDescriptor,
CollectionPart.Nature.INDEX,
inflightDescriptor,
// parent-injection
null,
tableExpression,
columnExpressions,
sqlAliasStem
),
creationProcess
);
return (CollectionPart) mappingType.getEmbeddedValueMapping();
}
throw new NotYetImplementedFor6Exception(
"Support for plural attributes with index type [" + bootMapKeyDescriptor + "] not yet implemented"
);
}
private static CollectionPart interpretElement(
Collection bootDescriptor,
String tableExpression,
CollectionPersister collectionDescriptor,
String sqlAliasStem,
Dialect dialect,
MappingModelCreationProcess creationProcess) {
final Value element = bootDescriptor.getElement();
if ( element instanceof BasicValue ) {
final BasicValue basicElement = (BasicValue) element;
return new BasicValuedCollectionPart(
collectionDescriptor,
CollectionPart.Nature.ELEMENT,
basicElement.resolve().getResolvedBasicType(),
basicElement.resolve().getValueConverter(),
tableExpression,
basicElement.getColumnIterator().next().getText( dialect )
);
}
if ( element instanceof Component ) {
final Component component = (Component) element;
final CompositeType compositeType = (CompositeType) collectionDescriptor.getElementType();
final List<String> columnExpressions = CollectionHelper.arrayList( component.getColumnSpan() );
final Iterator<Selectable> columnIterator = component.getColumnIterator();
while ( columnIterator.hasNext() ) {
columnExpressions.add( columnIterator.next().getText( dialect ) );
}
final EmbeddableMappingType mappingType = EmbeddableMappingType.from(
component,
compositeType,
embeddableMappingType -> new EmbeddedCollectionPart(
collectionDescriptor,
CollectionPart.Nature.ELEMENT,
embeddableMappingType,
// parent-injection
null,
tableExpression,
columnExpressions,
sqlAliasStem
),
creationProcess
);
return (CollectionPart) mappingType.getEmbeddedValueMapping();
}
if ( element instanceof OneToMany || element instanceof ToOne ) {
final EntityPersister associatedEntity;
if ( element instanceof OneToMany ) {
associatedEntity = creationProcess.getEntityPersister(
( (OneToMany) element ).getReferencedEntityName()
);
}
else {
// many-to-many
associatedEntity = creationProcess.getEntityPersister(
( (ToOne) element ).getReferencedEntityName()
);
}
return new EntityCollectionPart( CollectionPart.Nature.ELEMENT, associatedEntity );
}
throw new NotYetImplementedFor6Exception(
"Support for plural attributes with element type [" + element + "] not yet implemented"
);
}
private static class CollectionMappingTypeImpl implements CollectionMappingType { private static class CollectionMappingTypeImpl implements CollectionMappingType {
private final JavaTypeDescriptor collectionJtd; private final JavaTypeDescriptor collectionJtd;
private final CollectionSemantics semantics; private final CollectionSemantics semantics;
@ -773,7 +1008,7 @@ public class MappingModelCreationHelper {
} }
@Override @Override
public CollectionSemantics getCCollectionSemantics() { public CollectionSemantics getCollectionSemantics() {
return semantics; return semantics;
} }

View File

@ -6,12 +6,17 @@
*/ */
package org.hibernate.metamodel.mapping.internal; package org.hibernate.metamodel.mapping.internal;
import java.util.function.Consumer;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
import org.hibernate.metamodel.mapping.CollectionMappingType; import org.hibernate.metamodel.mapping.CollectionMappingType;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ManagedMappingType; import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
@ -20,7 +25,18 @@ import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.sql.SqlAstCreationState; import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
import org.hibernate.sql.results.internal.domain.collection.DelayedCollectionFetch;
import org.hibernate.sql.results.internal.domain.collection.EagerCollectionFetch;
import org.hibernate.sql.results.spi.DomainResultCreationState; import org.hibernate.sql.results.spi.DomainResultCreationState;
import org.hibernate.sql.results.spi.Fetch; import org.hibernate.sql.results.spi.Fetch;
import org.hibernate.sql.results.spi.FetchParent; import org.hibernate.sql.results.spi.FetchParent;
@ -33,17 +49,18 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
private final PropertyAccess propertyAccess; private final PropertyAccess propertyAccess;
private final StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess; private final StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess;
private final ForeignKeyDescriptor fkDescriptor;
private final CollectionPart elementDescriptor;
private final CollectionPart indexDescriptor;
private final CollectionIdentifierDescriptor identifierDescriptor;
private final FetchStrategy fetchStrategy; 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 CascadeStyle cascadeStyle;
private final CollectionPersister collectionDescriptor; private final CollectionPersister collectionDescriptor;
private final String sqlAliasStem;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public PluralAttributeMappingImpl( public PluralAttributeMappingImpl(
String attributeName, String attributeName,
@ -51,10 +68,10 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess, StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess,
CollectionMappingType collectionMappingType, CollectionMappingType collectionMappingType,
int stateArrayPosition, int stateArrayPosition,
String tableExpression, ForeignKeyDescriptor fkDescriptor,
String[] attrColumnExpressions, CollectionPart elementDescriptor,
ModelPart elementDescriptor, CollectionPart indexDescriptor,
ModelPart indexDescriptor, CollectionIdentifierDescriptor identifierDescriptor,
FetchStrategy fetchStrategy, FetchStrategy fetchStrategy,
CascadeStyle cascadeStyle, CascadeStyle cascadeStyle,
ManagedMappingType declaringType, ManagedMappingType declaringType,
@ -63,36 +80,47 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
this.propertyAccess = propertyAccess; this.propertyAccess = propertyAccess;
this.stateArrayContributorMetadataAccess = stateArrayContributorMetadataAccess; this.stateArrayContributorMetadataAccess = stateArrayContributorMetadataAccess;
this.stateArrayPosition = stateArrayPosition; this.stateArrayPosition = stateArrayPosition;
this.tableExpression = tableExpression; this.fkDescriptor = fkDescriptor;
this.attrColumnExpressions = attrColumnExpressions;
this.elementDescriptor = elementDescriptor; this.elementDescriptor = elementDescriptor;
this.indexDescriptor = indexDescriptor; this.indexDescriptor = indexDescriptor;
this.identifierDescriptor = identifierDescriptor;
this.fetchStrategy = fetchStrategy; this.fetchStrategy = fetchStrategy;
this.cascadeStyle = cascadeStyle; this.cascadeStyle = cascadeStyle;
this.collectionDescriptor = collectionDescriptor; this.collectionDescriptor = collectionDescriptor;
}
this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( attributeName );
}
@Override @Override
public CollectionMappingType getMappedTypeDescriptor() { public CollectionMappingType getMappedTypeDescriptor() {
return (CollectionMappingType) super.getMappedTypeDescriptor(); return (CollectionMappingType) super.getMappedTypeDescriptor();
} }
@Override
public ForeignKeyDescriptor getKeyDescriptor() {
return fkDescriptor;
}
@Override @Override
public CollectionPersister getCollectionDescriptor() { public CollectionPersister getCollectionDescriptor() {
return collectionDescriptor; return collectionDescriptor;
} }
@Override @Override
public ModelPart getValueDescriptor() { public CollectionPart getElementDescriptor() {
return elementDescriptor; return elementDescriptor;
} }
@Override @Override
public ModelPart getIndexDescriptor() { public CollectionPart getIndexDescriptor() {
return indexDescriptor; return indexDescriptor;
} }
@Override
public CollectionIdentifierDescriptor getIdentifierDescriptor() {
return identifierDescriptor;
}
@Override @Override
public int getStateArrayPosition() { public int getStateArrayPosition() {
return stateArrayPosition; return stateArrayPosition;
@ -128,8 +156,119 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final TableGroup collectionTableGroup = sqlAstCreationState.getFromClauseAccess().getTableGroup( fetchablePath );
throw new NotYetImplementedFor6Exception( getClass() ); if ( fetchTiming == FetchTiming.IMMEDIATE || selected ) {
final TableGroup collectionTableGroup = sqlAstCreationState.getFromClauseAccess().resolveTableGroup(
fetchablePath,
p -> {
final TableGroupJoin tableGroupJoin = createTableGroupJoin(
fetchablePath,
sqlAstCreationState.getFromClauseAccess().getTableGroup( fetchParent.getNavigablePath() ),
null,
JoinType.LEFT,
lockMode,
creationState.getSqlAliasBaseManager(),
creationState.getSqlAstCreationState().getSqlExpressionResolver(),
creationState.getSqlAstCreationState().getCreationContext()
);
return tableGroupJoin.getJoinedGroup();
}
);
return new EagerCollectionFetch(
fetchablePath,
this,
fkDescriptor.createDomainResult( fetchablePath, collectionTableGroup, creationState ),
getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
fetchParent,
creationState
);
}
return new DelayedCollectionFetch(
fetchablePath,
this,
true,
fetchParent
);
}
@Override
public String getSqlAliasStem() {
return sqlAliasStem;
}
@Override
public TableGroupJoin createTableGroupJoin(
NavigablePath navigablePath,
TableGroup lhs,
String explicitSourceAlias,
JoinType joinType,
LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
final String aliasRoot = explicitSourceAlias == null ? sqlAliasStem : explicitSourceAlias;
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( aliasRoot );
final TableGroupBuilder tableGroupBuilder = TableGroupBuilder.builder(
navigablePath,
this,
lockMode,
sqlAliasBase,
creationContext.getSessionFactory()
);
applyTableReferences(
sqlAliasBase,
joinType,
tableGroupBuilder,
sqlExpressionResolver,
creationContext
);
return new TableGroupJoin( navigablePath, joinType, tableGroupBuilder.build() );
}
@Override
public void applyTableReferences(
SqlAliasBase sqlAliasBase,
JoinType baseJoinType,
TableReferenceCollector collector,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
getCollectionDescriptor().applyTableReferences( sqlAliasBase, baseJoinType, collector, sqlExpressionResolver, creationContext );
}
@Override
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
final CollectionPart.Nature nature = CollectionPart.Nature.fromName( name );
if ( nature == CollectionPart.Nature.ELEMENT ) {
return elementDescriptor;
}
else if ( nature == CollectionPart.Nature.INDEX ) {
return indexDescriptor;
}
return null;
}
@Override
public void visitSubParts(Consumer<ModelPart> consumer, EntityMappingType treatTargetType) {
consumer.accept( elementDescriptor );
if ( indexDescriptor != null ) {
consumer.accept( indexDescriptor );
}
}
@Override
public int getNumberOfFetchables() {
return indexDescriptor == null ? 1 : 2;
}
@Override
public String toString() {
return "PluralAttribute(" + getCollectionDescriptor().getRole() + ")";
} }
} }

View File

@ -0,0 +1,64 @@
/*
* 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.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.sql.SqlAstCreationState;
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.BasicResult;
import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultCreationState;
/**
* @author Steve Ebersole
*/
public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor {
private final String keyColumnExpression;
private final JdbcMapping jdbcMapping;
public SimpleForeignKeyDescriptor(String keyColumnExpression, JdbcMapping jdbcMapping) {
this.keyColumnExpression = keyColumnExpression;
this.jdbcMapping = jdbcMapping;
}
@Override
public DomainResult createDomainResult(
NavigablePath collectionPath,
TableGroup tableGroup,
DomainResultCreationState creationState) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
tableGroup.getPrimaryTableReference(),
keyColumnExpression
),
s -> new ColumnReference(
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
keyColumnExpression,
jdbcMapping,
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
)
),
jdbcMapping.getJavaTypeDescriptor(),
sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration()
);
//noinspection unchecked
return new BasicResult(
sqlSelection.getValuesArrayPosition(),
null,
jdbcMapping.getJavaTypeDescriptor()
);
}
}

View File

@ -7,12 +7,12 @@
package org.hibernate.metamodel.mapping.internal; package org.hibernate.metamodel.mapping.internal;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ManagedMappingType; import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess; import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
@ -29,7 +29,7 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
int stateArrayPosition, int stateArrayPosition,
StateArrayContributorMetadataAccess attributeMetadataAccess, StateArrayContributorMetadataAccess attributeMetadataAccess,
FetchStrategy mappedFetchStrategy, FetchStrategy mappedFetchStrategy,
MappingType type, EntityMappingType type,
ManagedMappingType declaringType, ManagedMappingType declaringType,
PropertyAccess propertyAccess) { PropertyAccess propertyAccess) {
super( super(
@ -43,9 +43,14 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
); );
} }
@Override
public EntityMappingType getMappedTypeDescriptor() {
return (EntityMappingType) super.getMappedTypeDescriptor();
}
@Override @Override
public EntityMappingType getEntityMappingType() { public EntityMappingType getEntityMappingType() {
return null; return getMappedTypeDescriptor();
} }
@Override @Override
@ -57,6 +62,11 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
LockMode lockMode, LockMode lockMode,
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
return null; throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
public int getNumberOfFetchables() {
return getEntityMappingType().getNumberOfFetchables();
} }
} }

View File

@ -16,7 +16,6 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.FetchMode; import org.hibernate.FetchMode;
@ -33,6 +32,7 @@ import org.hibernate.cache.spi.entry.CacheEntryStructure;
import org.hibernate.cache.spi.entry.StructuredCollectionCacheEntry; import org.hibernate.cache.spi.entry.StructuredCollectionCacheEntry;
import org.hibernate.cache.spi.entry.StructuredMapCacheEntry; import org.hibernate.cache.spi.entry.StructuredMapCacheEntry;
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry; import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey; import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
@ -56,6 +56,7 @@ import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.Expectations; import org.hibernate.jdbc.Expectations;
import org.hibernate.loader.collection.CollectionInitializer; import org.hibernate.loader.collection.CollectionInitializer;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Collection; import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Column; import org.hibernate.mapping.Column;
import org.hibernate.mapping.Formula; import org.hibernate.mapping.Formula;
@ -64,9 +65,9 @@ import org.hibernate.mapping.IndexedCollection;
import org.hibernate.mapping.List; import org.hibernate.mapping.List;
import org.hibernate.mapping.Selectable; import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
import org.hibernate.mapping.Value;
import org.hibernate.metadata.CollectionMetadata; import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.persister.entity.PropertyMapping;
@ -84,18 +85,23 @@ import org.hibernate.persister.walking.spi.CompositeCollectionElementDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.sql.Alias; import org.hibernate.sql.Alias;
import org.hibernate.sql.SelectFragment; import org.hibernate.sql.SelectFragment;
import org.hibernate.sql.SimpleSelect; import org.hibernate.sql.SimpleSelect;
import org.hibernate.sql.Template; import org.hibernate.sql.Template;
import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
import org.hibernate.type.AnyType; import org.hibernate.type.AnyType;
import org.hibernate.type.AssociationType; import org.hibernate.type.AssociationType;
import org.hibernate.type.BasicType;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType; import org.hibernate.type.EntityType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -234,10 +240,26 @@ public abstract class AbstractCollectionPersister
private final Comparator comparator; private final Comparator comparator;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// "mapping model"
private final CollectionSemantics collectionSemantics;
private final BasicValueConverter elementConverter;
private final BasicValueConverter indexConverter;
// temprary
private final BasicType convertedElementType;
private final BasicType convertedIndexType;
public AbstractCollectionPersister( public AbstractCollectionPersister(
Collection collectionBinding, Collection collectionBootDescriptor,
CollectionDataAccess cacheAccessStrategy, CollectionDataAccess cacheAccessStrategy,
PersisterCreationContext creationContext) throws MappingException, CacheException { PersisterCreationContext creationContext) throws MappingException, CacheException {
final Value elementBootDescriptor = collectionBootDescriptor.getElement();
final Value indexBootDescriptor = collectionBootDescriptor instanceof IndexedCollection
? ( (IndexedCollection) collectionBootDescriptor ).getIndex()
: null;
final Database database = creationContext.getMetadata().getDatabase(); final Database database = creationContext.getMetadata().getDatabase();
final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment(); final JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment();
@ -245,7 +267,7 @@ public abstract class AbstractCollectionPersister
this.factory = creationContext.getSessionFactory(); this.factory = creationContext.getSessionFactory();
this.cacheAccessStrategy = cacheAccessStrategy; this.cacheAccessStrategy = cacheAccessStrategy;
if ( factory.getSessionFactoryOptions().isStructuredCacheEntriesEnabled() ) { if ( factory.getSessionFactoryOptions().isStructuredCacheEntriesEnabled() ) {
cacheEntryStructure = collectionBinding.isMap() cacheEntryStructure = collectionBootDescriptor.isMap()
? StructuredMapCacheEntry.INSTANCE ? StructuredMapCacheEntry.INSTANCE
: StructuredCollectionCacheEntry.INSTANCE; : StructuredCollectionCacheEntry.INSTANCE;
} }
@ -255,54 +277,54 @@ public abstract class AbstractCollectionPersister
dialect = factory.getDialect(); dialect = factory.getDialect();
sqlExceptionHelper = factory.getSQLExceptionHelper(); sqlExceptionHelper = factory.getSQLExceptionHelper();
collectionType = collectionBinding.getCollectionType(); collectionType = collectionBootDescriptor.getCollectionType();
navigableRole = new NavigableRole( collectionBinding.getRole() ); navigableRole = new NavigableRole( collectionBootDescriptor.getRole() );
entityName = collectionBinding.getOwnerEntityName(); entityName = collectionBootDescriptor.getOwnerEntityName();
ownerPersister = factory.getEntityPersister( entityName ); ownerPersister = factory.getEntityPersister( entityName );
queryLoaderName = collectionBinding.getLoaderName(); queryLoaderName = collectionBootDescriptor.getLoaderName();
isMutable = collectionBinding.isMutable(); isMutable = collectionBootDescriptor.isMutable();
mappedByProperty = collectionBinding.getMappedByProperty(); mappedByProperty = collectionBootDescriptor.getMappedByProperty();
Table table = collectionBinding.getCollectionTable(); Table table = collectionBootDescriptor.getCollectionTable();
fetchMode = collectionBinding.getElement().getFetchMode(); fetchMode = elementBootDescriptor.getFetchMode();
elementType = collectionBinding.getElement().getType(); elementType = elementBootDescriptor.getType();
// isSet = collectionBinding.isSet(); // isSet = collectionBinding.isSet();
// isSorted = collectionBinding.isSorted(); // isSorted = collectionBinding.isSorted();
isPrimitiveArray = collectionBinding.isPrimitiveArray(); isPrimitiveArray = collectionBootDescriptor.isPrimitiveArray();
isArray = collectionBinding.isArray(); isArray = collectionBootDescriptor.isArray();
subselectLoadable = collectionBinding.isSubselectLoadable(); subselectLoadable = collectionBootDescriptor.isSubselectLoadable();
qualifiedTableName = determineTableName( table, jdbcEnvironment ); qualifiedTableName = determineTableName( table, jdbcEnvironment );
int spacesSize = 1 + collectionBinding.getSynchronizedTables().size(); int spacesSize = 1 + collectionBootDescriptor.getSynchronizedTables().size();
spaces = new String[spacesSize]; spaces = new String[spacesSize];
spaces[0] = qualifiedTableName; spaces[0] = qualifiedTableName;
Iterator iter = collectionBinding.getSynchronizedTables().iterator(); Iterator iter = collectionBootDescriptor.getSynchronizedTables().iterator();
for ( int i = 1; i < spacesSize; i++ ) { for ( int i = 1; i < spacesSize; i++ ) {
spaces[i] = (String) iter.next(); spaces[i] = (String) iter.next();
} }
sqlWhereString = StringHelper.isNotEmpty( collectionBinding.getWhere() ) ? "( " + collectionBinding.getWhere() + ") " : null; sqlWhereString = StringHelper.isNotEmpty( collectionBootDescriptor.getWhere() ) ? "( " + collectionBootDescriptor.getWhere() + ") " : null;
hasWhere = sqlWhereString != null; hasWhere = sqlWhereString != null;
sqlWhereStringTemplate = hasWhere ? sqlWhereStringTemplate = hasWhere ?
Template.renderWhereStringTemplate( sqlWhereString, dialect, factory.getSqlFunctionRegistry() ) : Template.renderWhereStringTemplate( sqlWhereString, dialect, factory.getSqlFunctionRegistry() ) :
null; null;
hasOrphanDelete = collectionBinding.hasOrphanDelete(); hasOrphanDelete = collectionBootDescriptor.hasOrphanDelete();
int batch = collectionBinding.getBatchSize(); int batch = collectionBootDescriptor.getBatchSize();
if ( batch == -1 ) { if ( batch == -1 ) {
batch = factory.getSessionFactoryOptions().getDefaultBatchFetchSize(); batch = factory.getSessionFactoryOptions().getDefaultBatchFetchSize();
} }
batchSize = batch; batchSize = batch;
isVersioned = collectionBinding.isOptimisticLocked(); isVersioned = collectionBootDescriptor.isOptimisticLocked();
// KEY // KEY
keyType = collectionBinding.getKey().getType(); keyType = collectionBootDescriptor.getKey().getType();
iter = collectionBinding.getKey().getColumnIterator(); iter = collectionBootDescriptor.getKey().getColumnIterator();
int keySpan = collectionBinding.getKey().getColumnSpan(); int keySpan = collectionBootDescriptor.getKey().getColumnSpan();
keyColumnNames = new String[keySpan]; keyColumnNames = new String[keySpan];
keyColumnAliases = new String[keySpan]; keyColumnAliases = new String[keySpan];
int k = 0; int k = 0;
@ -328,7 +350,7 @@ public abstract class AbstractCollectionPersister
elementPersister = null; elementPersister = null;
} }
int elementSpan = collectionBinding.getElement().getColumnSpan(); int elementSpan = elementBootDescriptor.getColumnSpan();
elementColumnAliases = new String[elementSpan]; elementColumnAliases = new String[elementSpan];
elementColumnNames = new String[elementSpan]; elementColumnNames = new String[elementSpan];
elementColumnWriters = new String[elementSpan]; elementColumnWriters = new String[elementSpan];
@ -341,13 +363,13 @@ public abstract class AbstractCollectionPersister
elementColumnIsInPrimaryKey = new boolean[elementSpan]; elementColumnIsInPrimaryKey = new boolean[elementSpan];
boolean isPureFormula = true; boolean isPureFormula = true;
boolean hasNotNullableColumns = false; boolean hasNotNullableColumns = false;
boolean oneToMany = collectionBinding.isOneToMany(); boolean oneToMany = collectionBootDescriptor.isOneToMany();
boolean[] columnInsertability = null; boolean[] columnInsertability = null;
if ( !oneToMany ) { if ( !oneToMany ) {
columnInsertability = collectionBinding.getElement().getColumnInsertability(); columnInsertability = elementBootDescriptor.getColumnInsertability();
} }
int j = 0; int j = 0;
iter = collectionBinding.getElement().getColumnIterator(); iter = elementBootDescriptor.getColumnIterator();
while ( iter.hasNext() ) { while ( iter.hasNext() ) {
Selectable selectable = (Selectable) iter.next(); Selectable selectable = (Selectable) iter.next();
elementColumnAliases[j] = selectable.getAlias( dialect, table ); elementColumnAliases[j] = selectable.getAlias( dialect, table );
@ -390,10 +412,10 @@ public abstract class AbstractCollectionPersister
// INDEX AND ROW SELECT // INDEX AND ROW SELECT
hasIndex = collectionBinding.isIndexed(); hasIndex = collectionBootDescriptor.isIndexed();
if ( hasIndex ) { if ( hasIndex ) {
// NativeSQL: collect index column and auto-aliases // NativeSQL: collect index column and auto-aliases
IndexedCollection indexedCollection = (IndexedCollection) collectionBinding; IndexedCollection indexedCollection = (IndexedCollection) collectionBootDescriptor;
indexType = indexedCollection.getIndex().getType(); indexType = indexedCollection.getIndex().getType();
int indexSpan = indexedCollection.getIndex().getColumnSpan(); int indexSpan = indexedCollection.getIndex().getColumnSpan();
boolean[] indexColumnInsertability = indexedCollection.getIndex().getColumnInsertability(); boolean[] indexColumnInsertability = indexedCollection.getIndex().getColumnInsertability();
@ -440,12 +462,12 @@ public abstract class AbstractCollectionPersister
baseIndex = 0; baseIndex = 0;
} }
hasIdentifier = collectionBinding.isIdentified(); hasIdentifier = collectionBootDescriptor.isIdentified();
if ( hasIdentifier ) { if ( hasIdentifier ) {
if ( collectionBinding.isOneToMany() ) { if ( collectionBootDescriptor.isOneToMany() ) {
throw new MappingException( "one-to-many collections with identifiers are not supported" ); throw new MappingException( "one-to-many collections with identifiers are not supported" );
} }
IdentifierCollection idColl = (IdentifierCollection) collectionBinding; IdentifierCollection idColl = (IdentifierCollection) collectionBootDescriptor;
identifierType = idColl.getIdentifier().getType(); identifierType = idColl.getIdentifier().getType();
iter = idColl.getIdentifier().getColumnIterator(); iter = idColl.getIdentifier().getColumnIterator();
Column col = (Column) iter.next(); Column col = (Column) iter.next();
@ -473,68 +495,68 @@ public abstract class AbstractCollectionPersister
// sqlSelectString = sqlSelectString(); // sqlSelectString = sqlSelectString();
// sqlSelectRowString = sqlSelectRowString(); // sqlSelectRowString = sqlSelectRowString();
if ( collectionBinding.getCustomSQLInsert() == null ) { if ( collectionBootDescriptor.getCustomSQLInsert() == null ) {
sqlInsertRowString = generateInsertRowString(); sqlInsertRowString = generateInsertRowString();
insertCallable = false; insertCallable = false;
insertCheckStyle = ExecuteUpdateResultCheckStyle.COUNT; insertCheckStyle = ExecuteUpdateResultCheckStyle.COUNT;
} }
else { else {
sqlInsertRowString = collectionBinding.getCustomSQLInsert(); sqlInsertRowString = collectionBootDescriptor.getCustomSQLInsert();
insertCallable = collectionBinding.isCustomInsertCallable(); insertCallable = collectionBootDescriptor.isCustomInsertCallable();
insertCheckStyle = collectionBinding.getCustomSQLInsertCheckStyle() == null insertCheckStyle = collectionBootDescriptor.getCustomSQLInsertCheckStyle() == null
? ExecuteUpdateResultCheckStyle.determineDefault( collectionBinding.getCustomSQLInsert(), insertCallable ) ? ExecuteUpdateResultCheckStyle.determineDefault( collectionBootDescriptor.getCustomSQLInsert(), insertCallable )
: collectionBinding.getCustomSQLInsertCheckStyle(); : collectionBootDescriptor.getCustomSQLInsertCheckStyle();
} }
if ( collectionBinding.getCustomSQLUpdate() == null ) { if ( collectionBootDescriptor.getCustomSQLUpdate() == null ) {
sqlUpdateRowString = generateUpdateRowString(); sqlUpdateRowString = generateUpdateRowString();
updateCallable = false; updateCallable = false;
updateCheckStyle = ExecuteUpdateResultCheckStyle.COUNT; updateCheckStyle = ExecuteUpdateResultCheckStyle.COUNT;
} }
else { else {
sqlUpdateRowString = collectionBinding.getCustomSQLUpdate(); sqlUpdateRowString = collectionBootDescriptor.getCustomSQLUpdate();
updateCallable = collectionBinding.isCustomUpdateCallable(); updateCallable = collectionBootDescriptor.isCustomUpdateCallable();
updateCheckStyle = collectionBinding.getCustomSQLUpdateCheckStyle() == null updateCheckStyle = collectionBootDescriptor.getCustomSQLUpdateCheckStyle() == null
? ExecuteUpdateResultCheckStyle.determineDefault( collectionBinding.getCustomSQLUpdate(), insertCallable ) ? ExecuteUpdateResultCheckStyle.determineDefault( collectionBootDescriptor.getCustomSQLUpdate(), insertCallable )
: collectionBinding.getCustomSQLUpdateCheckStyle(); : collectionBootDescriptor.getCustomSQLUpdateCheckStyle();
} }
if ( collectionBinding.getCustomSQLDelete() == null ) { if ( collectionBootDescriptor.getCustomSQLDelete() == null ) {
sqlDeleteRowString = generateDeleteRowString(); sqlDeleteRowString = generateDeleteRowString();
deleteCallable = false; deleteCallable = false;
deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE; deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
} }
else { else {
sqlDeleteRowString = collectionBinding.getCustomSQLDelete(); sqlDeleteRowString = collectionBootDescriptor.getCustomSQLDelete();
deleteCallable = collectionBinding.isCustomDeleteCallable(); deleteCallable = collectionBootDescriptor.isCustomDeleteCallable();
deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE; deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
} }
if ( collectionBinding.getCustomSQLDeleteAll() == null ) { if ( collectionBootDescriptor.getCustomSQLDeleteAll() == null ) {
sqlDeleteString = generateDeleteString(); sqlDeleteString = generateDeleteString();
deleteAllCallable = false; deleteAllCallable = false;
deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE; deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
} }
else { else {
sqlDeleteString = collectionBinding.getCustomSQLDeleteAll(); sqlDeleteString = collectionBootDescriptor.getCustomSQLDeleteAll();
deleteAllCallable = collectionBinding.isCustomDeleteAllCallable(); deleteAllCallable = collectionBootDescriptor.isCustomDeleteAllCallable();
deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE; deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
} }
sqlSelectSizeString = generateSelectSizeString( collectionBinding.isIndexed() && !collectionBinding.isMap() ); sqlSelectSizeString = generateSelectSizeString( collectionBootDescriptor.isIndexed() && !collectionBootDescriptor.isMap() );
sqlDetectRowByIndexString = generateDetectRowByIndexString(); sqlDetectRowByIndexString = generateDetectRowByIndexString();
sqlDetectRowByElementString = generateDetectRowByElementString(); sqlDetectRowByElementString = generateDetectRowByElementString();
sqlSelectRowByIndexString = generateSelectRowByIndexString(); sqlSelectRowByIndexString = generateSelectRowByIndexString();
logStaticSQL(); logStaticSQL();
isLazy = collectionBinding.isLazy(); isLazy = collectionBootDescriptor.isLazy();
isExtraLazy = collectionBinding.isExtraLazy(); isExtraLazy = collectionBootDescriptor.isExtraLazy();
isInverse = collectionBinding.isInverse(); isInverse = collectionBootDescriptor.isInverse();
if ( collectionBinding.isArray() ) { if ( collectionBootDescriptor.isArray() ) {
elementClass = ( (org.hibernate.mapping.Array) collectionBinding ).getElementClass(); elementClass = ( (org.hibernate.mapping.Array) collectionBootDescriptor ).getElementClass();
} }
else { else {
// for non-arrays, we don't need to know the element class // for non-arrays, we don't need to know the element class
@ -569,9 +591,9 @@ public abstract class AbstractCollectionPersister
} }
} }
hasOrder = collectionBinding.getOrderBy() != null; hasOrder = collectionBootDescriptor.getOrderBy() != null;
if ( hasOrder ) { if ( hasOrder ) {
LOG.debugf( "Translating order-by fragment [%s] for collection role : %s", collectionBinding.getOrderBy(), getRole() ); LOG.debugf( "Translating order-by fragment [%s] for collection role : %s", collectionBootDescriptor.getOrderBy(), getRole() );
// orderByTranslation = Template.translateOrderBy( // orderByTranslation = Template.translateOrderBy(
// collectionBinding.getOrderBy(), // collectionBinding.getOrderBy(),
// new ColumnMapperImpl(), // new ColumnMapperImpl(),
@ -587,20 +609,20 @@ public abstract class AbstractCollectionPersister
} }
// Handle any filters applied to this collectionBinding // Handle any filters applied to this collectionBinding
filterHelper = new FilterHelper( collectionBinding.getFilters(), factory); filterHelper = new FilterHelper( collectionBootDescriptor.getFilters(), factory);
// Handle any filters applied to this collectionBinding for many-to-many // Handle any filters applied to this collectionBinding for many-to-many
manyToManyFilterHelper = new FilterHelper( collectionBinding.getManyToManyFilters(), factory); manyToManyFilterHelper = new FilterHelper( collectionBootDescriptor.getManyToManyFilters(), factory);
manyToManyWhereString = StringHelper.isNotEmpty( collectionBinding.getManyToManyWhere() ) ? manyToManyWhereString = StringHelper.isNotEmpty( collectionBootDescriptor.getManyToManyWhere() ) ?
"( " + collectionBinding.getManyToManyWhere() + ")" : "( " + collectionBootDescriptor.getManyToManyWhere() + ")" :
null; null;
manyToManyWhereTemplate = manyToManyWhereString == null ? manyToManyWhereTemplate = manyToManyWhereString == null ?
null : null :
Template.renderWhereStringTemplate( manyToManyWhereString, factory.getDialect(), factory.getSqlFunctionRegistry() ); Template.renderWhereStringTemplate( manyToManyWhereString, factory.getDialect(), factory.getSqlFunctionRegistry() );
hasManyToManyOrder = collectionBinding.getManyToManyOrdering() != null; hasManyToManyOrder = collectionBootDescriptor.getManyToManyOrdering() != null;
if ( hasManyToManyOrder ) { if ( hasManyToManyOrder ) {
LOG.debugf( "Translating many-to-many order-by fragment [%s] for collection role : %s", collectionBinding.getOrderBy(), getRole() ); LOG.debugf( "Translating many-to-many order-by fragment [%s] for collection role : %s", collectionBootDescriptor.getOrderBy(), getRole() );
// manyToManyOrderByTranslation = Template.translateOrderBy( // manyToManyOrderByTranslation = Template.translateOrderBy(
// collectionBinding.getManyToManyOrdering(), // collectionBinding.getManyToManyOrdering(),
// new ColumnMapperImpl(), // new ColumnMapperImpl(),
@ -614,9 +636,37 @@ public abstract class AbstractCollectionPersister
// manyToManyOrderByTranslation = null; // manyToManyOrderByTranslation = null;
} }
comparator = collectionBinding.getComparator(); comparator = collectionBootDescriptor.getComparator();
initCollectionPropertyMap(); initCollectionPropertyMap();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// "mapping model"
this.collectionSemantics = creationContext.getBootstrapContext()
.getMetadataBuildingOptions()
.getPersistentCollectionRepresentationResolver()
.resolveRepresentation( collectionBootDescriptor );
if ( elementBootDescriptor instanceof BasicValue ) {
final BasicValue.Resolution<?> basicTypeResolution = ( (BasicValue) elementBootDescriptor ).resolve();
this.elementConverter = basicTypeResolution.getValueConverter();
this.convertedElementType = basicTypeResolution.getResolvedBasicType();
}
else {
this.elementConverter = null;
this.convertedElementType = null;
}
if ( indexBootDescriptor instanceof BasicValue ) {
final BasicValue.Resolution<?> basicTypeResolution = ( (BasicValue) indexBootDescriptor ).resolve();
this.indexConverter = basicTypeResolution.getValueConverter();
this.convertedIndexType = basicTypeResolution.getResolvedBasicType();
}
else {
this.indexConverter = null;
this.convertedIndexType = null;
}
} }
@Override @Override
@ -872,6 +922,16 @@ public abstract class AbstractCollectionPersister
return elementType; return elementType;
} }
@Override
public BasicValueConverter getElementConverter() {
return elementConverter;
}
@Override
public BasicValueConverter getIndexConverter() {
return indexConverter;
}
/** /**
* Return the element class of an array, or null otherwise. needed by arrays * Return the element class of an array, or null otherwise. needed by arrays
*/ */
@ -947,7 +1007,14 @@ public abstract class AbstractCollectionPersister
*/ */
protected int writeElement(PreparedStatement st, Object elt, int i, SharedSessionContractImplementor session) protected int writeElement(PreparedStatement st, Object elt, int i, SharedSessionContractImplementor session)
throws HibernateException, SQLException { throws HibernateException, SQLException {
getElementType().nullSafeSet( st, elt, i, elementColumnIsSettable, session ); if ( elementConverter != null ) {
//noinspection unchecked
final Object converted = elementConverter.toRelationalValue( elt );
convertedElementType.getJdbcValueBinder().bind( st, converted, i, session );
}
else {
getElementType().nullSafeSet( st, elt, i, elementColumnIsSettable, session );
}
return i + ArrayHelper.countTrue( elementColumnIsSettable ); return i + ArrayHelper.countTrue( elementColumnIsSettable );
} }
@ -957,7 +1024,16 @@ public abstract class AbstractCollectionPersister
*/ */
protected int writeIndex(PreparedStatement st, Object index, int i, SharedSessionContractImplementor session) protected int writeIndex(PreparedStatement st, Object index, int i, SharedSessionContractImplementor session)
throws HibernateException, SQLException { throws HibernateException, SQLException {
getIndexType().nullSafeSet( st, incrementIndexByBase( index ), i, indexColumnIsSettable, session ); if ( indexConverter != null ) {
//noinspection unchecked
final Object converted = indexConverter.toRelationalValue( index );
//noinspection unchecked
convertedIndexType.getJdbcValueBinder().bind( st, converted, i, session );
}
else {
getIndexType().nullSafeSet( st, incrementIndexByBase( index ), i, indexColumnIsSettable, session );
}
return i + ArrayHelper.countTrue( indexColumnIsSettable ); return i + ArrayHelper.countTrue( indexColumnIsSettable );
} }
@ -976,7 +1052,13 @@ public abstract class AbstractCollectionPersister
if ( elementIsPureFormula ) { if ( elementIsPureFormula ) {
throw new AssertionFailure( "cannot use a formula-based element in the where condition" ); throw new AssertionFailure( "cannot use a formula-based element in the where condition" );
} }
getElementType().nullSafeSet( st, elt, i, elementColumnIsInPrimaryKey, session ); if ( elementConverter != null ) {
final Object converted = elementConverter.toRelationalValue( elt );
convertedElementType.getJdbcValueBinder().bind( st, converted, i, session );
}
else {
getElementType().nullSafeSet( st, elt, i, elementColumnIsInPrimaryKey, session );
}
return i + elementColumnAliases.length; return i + elementColumnAliases.length;
} }
@ -989,7 +1071,13 @@ public abstract class AbstractCollectionPersister
if ( indexContainsFormula ) { if ( indexContainsFormula ) {
throw new AssertionFailure( "cannot use a formula-based index in the where condition" ); throw new AssertionFailure( "cannot use a formula-based index in the where condition" );
} }
getIndexType().nullSafeSet( st, incrementIndexByBase( index ), i, session ); if ( indexConverter != null ) {
final Object converted = indexConverter.toRelationalValue( index );
convertedIndexType.getJdbcValueBinder().bind( st, converted, i, session );
}
else {
getIndexType().nullSafeSet( st, incrementIndexByBase( index ), i, session );
}
return i + indexColumnAliases.length; return i + indexColumnAliases.length;
} }
@ -2297,4 +2385,51 @@ public abstract class AbstractCollectionPersister
} }
}; };
} }
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// "mapping model"
@Override
public void applyTableReferences(
SqlAliasBase sqlAliasBase,
JoinType baseJoinType,
TableReferenceCollector collector,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
if ( isOneToMany() ) {
// one-to-many does not define a "collection table"
assert elementPersister != null;
}
else {
// we do have a "collection table" - apply it first
collector.applySecondaryTableReferences(
new TableReference( qualifiedTableName, sqlAliasBase.generateNewAlias(), false, getFactory() ),
baseJoinType,
(lhs, rhs, joinType) -> {
// create the join-predicate between the owner table and the collection table
throw new NotYetImplementedFor6Exception( getClass() );
}
);
}
if ( elementPersister != null ) {
elementPersister.applyTableReferences(
sqlAliasBase,
// todo (6.0) : determine the proper join-type to use
JoinType.LEFT,
collector,
sqlExpressionResolver,
creationContext
);
}
}
@Override
public CollectionSemantics getCollectionSemantics() {
return collectionSemantics;
}
} }

View File

@ -32,6 +32,7 @@ import org.hibernate.loader.collection.BatchingCollectionInitializerBuilder;
import org.hibernate.loader.collection.CollectionInitializer; import org.hibernate.loader.collection.CollectionInitializer;
import org.hibernate.loader.collection.SubselectCollectionLoader; import org.hibernate.loader.collection.SubselectCollectionLoader;
import org.hibernate.mapping.Collection; import org.hibernate.mapping.Collection;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.persister.entity.Joinable; import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.spi.PersisterCreationContext; import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.pretty.MessageHelper; import org.hibernate.pretty.MessageHelper;

View File

@ -14,17 +14,26 @@ import java.util.Map;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.cache.spi.access.CollectionDataAccess; import org.hibernate.cache.spi.access.CollectionDataAccess;
import org.hibernate.cache.spi.entry.CacheEntryStructure; import org.hibernate.cache.spi.entry.CacheEntryStructure;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGenerator; import org.hibernate.id.IdentifierGenerator;
import org.hibernate.metadata.CollectionMetadata; import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.metamodel.CollectionClassification; import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.walking.spi.CollectionDefinition; import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
import org.hibernate.sql.ast.tree.from.TableReferenceContributor;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -62,7 +71,7 @@ import org.hibernate.type.Type;
* @see org.hibernate.collection.spi.PersistentCollection * @see org.hibernate.collection.spi.PersistentCollection
* @author Gavin King * @author Gavin King
*/ */
public interface CollectionPersister extends CollectionDefinition { public interface CollectionPersister extends CollectionDefinition, TableReferenceContributor {
/** /**
* Initialize the given collection with the given key * Initialize the given collection with the given key
* TODO: add owner argument!! * TODO: add owner argument!!
@ -103,6 +112,21 @@ public interface CollectionPersister extends CollectionDefinition {
* Return the element class of an array, or null otherwise * Return the element class of an array, or null otherwise
*/ */
Class getElementClass(); Class getElementClass();
/**
* The value converter for the element values of this collection
*/
default BasicValueConverter getElementConverter() {
return null;
}
/**
* The value converter for index values of this collection (effectively map keys only)
*/
default BasicValueConverter getIndexConverter() {
return null;
}
/** /**
* Read the key from a row of the JDBC <tt>ResultSet</tt> * Read the key from a row of the JDBC <tt>ResultSet</tt>
*/ */
@ -332,4 +356,30 @@ public interface CollectionPersister extends CollectionDefinition {
* @see CollectionClassification#SORTED_SET * @see CollectionClassification#SORTED_SET
*/ */
Comparator<?> getSortingComparator(); Comparator<?> getSortingComparator();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// mapping model
@Override
default void applyTableReferences(
SqlAliasBase sqlAliasBase,
JoinType baseJoinType,
TableReferenceCollector collector,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
throw new NotYetImplementedFor6Exception(
"The persister used for this collection [" + getNavigableRole()
+ "] does not yet implement support for use in SQL AST creation;"
+ " should implement `TableReferenceContributor#applyTableReferences`"
);
}
default CollectionSemantics getCollectionSemantics() {
throw new NotYetImplementedFor6Exception(
"The persister used for this collection [" + getNavigableRole()
+ "] does not yet implement support for `"
+ CollectionSemantics.class.getName() + "`"
);
}
} }

View File

@ -184,7 +184,9 @@ import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.QueryLiteral; import org.hibernate.sql.ast.tree.expression.QueryLiteral;
import org.hibernate.sql.ast.tree.from.StandardTableGroup; import org.hibernate.sql.ast.tree.from.StandardTableGroup;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupBuilder;
import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
import org.hibernate.sql.ast.tree.from.TableReferenceJoin; import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate; import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
import org.hibernate.sql.ast.tree.predicate.Junction; import org.hibernate.sql.ast.tree.predicate.Junction;
@ -1187,20 +1189,23 @@ public abstract class AbstractEntityPersister
SqlAstCreationContext creationContext) { SqlAstCreationContext creationContext) {
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() ); final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
final TableReference primaryTableReference = resolvePrimaryTableReference( sqlAliasBase, sqlExpressionResolver ); final TableGroupBuilder builder = TableGroupBuilder.builder(
final List<TableReferenceJoin> joins = new ArrayList<>( );
resolveTableReferenceJoins( primaryTableReference, sqlAliasBase, tableReferenceJoinType, joins::add, sqlExpressionResolver );
return new StandardTableGroup(
navigablePath, navigablePath,
this, this,
lockMode, lockMode,
primaryTableReference,
joins,
sqlAliasBase, sqlAliasBase,
getFactory() creationContext.getSessionFactory()
); );
applyTableReferences(
sqlAliasBase,
tableReferenceJoinType,
builder,
sqlExpressionResolver,
creationContext
);
return builder.build();
} }
protected TableReference resolvePrimaryTableReference( protected TableReference resolvePrimaryTableReference(
@ -1228,6 +1233,33 @@ public abstract class AbstractEntityPersister
} }
} }
@Override
public void applyTableReferences(
SqlAliasBase sqlAliasBase,
org.hibernate.sql.ast.JoinType baseJoinType,
TableReferenceCollector collector,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
final TableReference primaryTableReference = resolvePrimaryTableReference(
sqlAliasBase,
sqlExpressionResolver
);
collector.applyPrimaryReference( primaryTableReference );
for ( int i = 1; i < getSubclassTableSpan(); i++ ) {
collector.addTableReferenceJoin(
createTableReferenceJoin(
i,
primaryTableReference,
baseJoinType,
sqlAliasBase,
sqlExpressionResolver
)
);
}
}
protected TableReferenceJoin createTableReferenceJoin( protected TableReferenceJoin createTableReferenceJoin(
int subClassTablePosition, int subClassTablePosition,
TableReference rootTableReference, TableReference rootTableReference,
@ -6483,6 +6515,11 @@ public abstract class AbstractEntityPersister
// otherwise, nothing to do // otherwise, nothing to do
} }
@Override
public int getNumberOfFetchables() {
return attributeMappings.size();
}
@Override @Override
public void visitFetchables( public void visitFetchables(
Consumer<Fetchable> fetchableConsumer, Consumer<Fetchable> fetchableConsumer,

View File

@ -38,8 +38,13 @@ import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.metamodel.spi.EntityRepresentationStrategy; import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy; import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAliasStemHelper; import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.tree.from.RootTableGroupProducer; import org.hibernate.sql.ast.tree.from.RootTableGroupProducer;
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -93,6 +98,11 @@ public interface EntityPersister extends EntityDefinition, EntityValuedModelPart
@Deprecated @Deprecated
void generateEntityDefinition(); void generateEntityDefinition();
@Override
default int getNumberOfFetchables() {
return getNumberOfAttributeMappings();
}
/** /**
* Finish the initialization of this object. {@link #prepareMappingModel} * Finish the initialization of this object. {@link #prepareMappingModel}
* must be called for all entity persisters before calling this method. * must be called for all entity persisters before calling this method.
@ -906,6 +916,4 @@ public interface EntityPersister extends EntityDefinition, EntityValuedModelPart
default boolean canIdentityInsertBeDelayed() { default boolean canIdentityInsertBeDelayed() {
return false; return false;
} }
} }

View File

@ -499,6 +499,7 @@ public abstract class BaseSqmToSqlAstConverter
creationContext creationContext
); );
lhsTableGroup.addTableGroupJoin( tableGroupJoin );
fromClauseIndex.register( sqmJoin, tableGroupJoin.getJoinedGroup() ); fromClauseIndex.register( sqmJoin, tableGroupJoin.getJoinedGroup() );
// add any additional join restrictions // add any additional join restrictions

View File

@ -37,7 +37,6 @@ public class FromClauseIndex extends SimpleFromClauseAccessImpl {
* Holds *explicitly* fetched joins * Holds *explicitly* fetched joins
*/ */
private Map<NavigablePath, SqmAttributeJoin> fetchesByPath; private Map<NavigablePath, SqmAttributeJoin> fetchesByPath;
private Map<NavigablePath, Map<NavigablePath, SqmAttributeJoin>> fetchesByParentPath;
private final Set<String> affectedTableNames = new HashSet<>(); private final Set<String> affectedTableNames = new HashSet<>();
@ -61,6 +60,20 @@ public class FromClauseIndex extends SimpleFromClauseAccessImpl {
); );
} }
} }
if ( sqmPath instanceof SqmAttributeJoin ) {
final SqmAttributeJoin sqmJoin = (SqmAttributeJoin) sqmPath;
if ( sqmJoin.isFetched() ) {
registerJoinFetch( sqmJoin );
}
}
}
private void registerJoinFetch(SqmAttributeJoin sqmJoin) {
if ( fetchesByPath == null ) {
fetchesByPath = new HashMap<>();
}
fetchesByPath.put( sqmJoin.getNavigablePath(), sqmJoin );
} }
public boolean isResolved(SqmFrom fromElement) { public boolean isResolved(SqmFrom fromElement) {

View File

@ -31,6 +31,7 @@ import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.sqm.internal.DomainParameterXref; import org.hibernate.query.sqm.internal.DomainParameterXref;
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter; import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
import org.hibernate.query.sqm.sql.SqlAstCreationState; import org.hibernate.query.sqm.sql.SqlAstCreationState;
import org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType; import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation; import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
@ -67,7 +68,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class StandardSqmSelectToSqlAstConverter public class StandardSqmSelectToSqlAstConverter
extends BaseSqmToSqlAstConverter extends BaseSqmToSqlAstConverter
implements DomainResultCreationState, org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter { implements DomainResultCreationState, SqmSelectToSqlAstConverter {
private final LoadQueryInfluencers fetchInfluencers; private final LoadQueryInfluencers fetchInfluencers;
private final CircularFetchDetector circularFetchDetector = new CircularFetchDetector(); private final CircularFetchDetector circularFetchDetector = new CircularFetchDetector();
@ -155,7 +156,7 @@ public class StandardSqmSelectToSqlAstConverter
@Override @Override
public List<Fetch> visitFetches(FetchParent fetchParent) { public List<Fetch> visitFetches(FetchParent fetchParent) {
final List<Fetch> fetches = CollectionHelper.arrayList( fetchParent.getReferencedMappingType().getNumberOfAttributeMappings() ); final List<Fetch> fetches = CollectionHelper.arrayList( fetchParent.getReferencedMappingType().getNumberOfFetchables() );
//noinspection Convert2Lambda //noinspection Convert2Lambda
final Consumer<Fetchable> fetchableConsumer = new Consumer<Fetchable>() { final Consumer<Fetchable> fetchableConsumer = new Consumer<Fetchable>() {
@ -214,7 +215,7 @@ public class StandardSqmSelectToSqlAstConverter
if ( fetchedJoin != null ) { if ( fetchedJoin != null ) {
// there was an explicit fetch in the SQM // there was an explicit fetch in the SQM
// there should be a TableGroupJoin registered n SqmJoin registered for this `fetchablePath` already // there should be a TableGroupJoin registered for this `fetchablePath` already
// because it // because it
assert getFromClauseIndex().getTableGroup( fetchablePath ) != null; assert getFromClauseIndex().getTableGroup( fetchablePath ) != null;

View File

@ -6,13 +6,18 @@
*/ */
package org.hibernate.sql.ast.tree.from; package org.hibernate.sql.ast.tree.from;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase; import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.tree.predicate.Predicate;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -23,7 +28,7 @@ public class StandardTableGroup extends AbstractTableGroup {
public StandardTableGroup( public StandardTableGroup(
NavigablePath navigablePath, NavigablePath navigablePath,
RootTableGroupProducer tableGroupProducer, TableGroupProducer tableGroupProducer,
LockMode lockMode, LockMode lockMode,
TableReference primaryTableReference, TableReference primaryTableReference,
List<TableReferenceJoin> tableJoins, List<TableReferenceJoin> tableJoins,
@ -34,11 +39,6 @@ public class StandardTableGroup extends AbstractTableGroup {
this.tableJoins = tableJoins; this.tableJoins = tableJoins;
} }
@Override
public RootTableGroupProducer getModelPart() {
return (RootTableGroupProducer) super.getModelPart();
}
@Override @Override
public void applyAffectedTableNames(Consumer<String> nameCollector) { public void applyAffectedTableNames(Consumer<String> nameCollector) {
// todo (6.0) : if we implement dynamic TableReference creation, this still needs to return the expressions for all mapped tables not just the ones with a TableReference at this time // todo (6.0) : if we implement dynamic TableReference creation, this still needs to return the expressions for all mapped tables not just the ones with a TableReference at this time

View File

@ -0,0 +1,131 @@
/*
* 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.sql.ast.tree.from;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
/**
* @author Steve Ebersole
*/
public class TableGroupBuilder implements TableReferenceCollector {
public static TableGroupBuilder builder(
NavigablePath path,
TableGroupProducer producer,
LockMode lockMode,
SqlAliasBase sqlAliasBase,
SessionFactoryImplementor sessionFactory) {
return new TableGroupBuilder( path, producer, lockMode, sqlAliasBase, sessionFactory );
}
private final NavigablePath path;
private final TableGroupProducer producer;
private final SessionFactoryImplementor sessionFactory;
private final SqlAliasBase sqlAliasBase;
private final LockMode lockMode;
private final Function<TableReference,TableReferenceJoin> primaryJoinProducer;
private TableReference primaryTableReference;
private TableReference secondaryTableLhs;
private java.util.List<TableReferenceJoin> tableJoins;
private TableGroupBuilder(
NavigablePath path,
TableGroupProducer producer,
LockMode lockMode,
SqlAliasBase sqlAliasBase,
SessionFactoryImplementor sessionFactory) {
this( path, producer, lockMode, sqlAliasBase, null, sessionFactory );
}
private TableGroupBuilder(
NavigablePath path,
TableGroupProducer producer,
LockMode lockMode,
SqlAliasBase sqlAliasBase,
Function<TableReference,TableReferenceJoin> primaryJoinProducer,
SessionFactoryImplementor sessionFactory) {
this.path = path;
this.producer = producer;
this.lockMode = lockMode;
this.sqlAliasBase = sqlAliasBase;
this.primaryJoinProducer = primaryJoinProducer;
this.sessionFactory = sessionFactory;
}
public TableGroup build() {
if ( primaryTableReference == null ) {
throw new IllegalStateException( "Primary TableReference was not specified : " + path );
}
return new StandardTableGroup(
path,
producer,
lockMode,
primaryTableReference,
tableJoins == null ? Collections.emptyList() : tableJoins,
sqlAliasBase,
sessionFactory
);
}
@Override
public void applyPrimaryReference(TableReference tableReference) {
if ( primaryTableReference != null ) {
assert primaryJoinProducer != null;
addTableReferenceJoin( primaryJoinProducer.apply( tableReference ) );
}
else {
primaryTableReference = tableReference;
}
secondaryTableLhs = tableReference;
}
@Override
public void applySecondaryTableReferences(
TableReference tableReference,
JoinType tableReferenceJoinType,
TableReferenceJoinPredicateProducer predicateProducer) {
if ( primaryTableReference == null ) {
primaryTableReference = tableReference;
secondaryTableLhs = primaryTableReference;
}
else {
addTableReferenceJoin(
new TableReferenceJoin(
tableReferenceJoinType,
tableReference,
predicateProducer.producePredicate(
secondaryTableLhs,
tableReference,
tableReferenceJoinType
)
)
);
}
}
public void addTableReferenceJoin(TableReferenceJoin join) {
if ( tableJoins == null ) {
tableJoins = new ArrayList<>();
}
tableJoins.add( join );
}
}

View File

@ -15,7 +15,7 @@ import org.hibernate.query.sqm.sql.SqlAliasBaseManager;
* @author Steve Ebersole * @author Steve Ebersole
* @author Andrea Boriero * @author Andrea Boriero
*/ */
public interface TableGroupProducer extends ModelPartContainer { public interface TableGroupProducer extends ModelPartContainer, TableReferenceContributor {
/** /**
* Get the "stem" used as the base for generating SQL table aliases for table * Get the "stem" used as the base for generating SQL table aliases for table
* references that are part of the TableGroup being generated * references that are part of the TableGroup being generated

View File

@ -0,0 +1,38 @@
/*
* 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.sql.ast.tree.from;
import org.hibernate.sql.ast.JoinType;
/**
* Used in constructing {@link TableGroup} references to collect the individual table
* references
*
* @author Steve Ebersole
*/
public interface TableReferenceCollector {
void applyPrimaryReference(TableReference tableReference);
/**
* Collect a table reference as part of the TableGroup.
*
* @param tableReference The TableReference.
* @param joinType The type of join indicated by the mapping of the table, if it is to be joined
* @param predicateProducer Function for creating the join predicate, if it is to be joined. The first
* argument passed to the function is the LHS reference. The second is the same as `tableReference`.
* The result is a SQL AST Predicate to use as the join-predicate
*/
void applySecondaryTableReferences(
TableReference tableReference,
JoinType joinType,
TableReferenceJoinPredicateProducer predicateProducer);
/**
* Directly add a TableReferenceJoin
*/
void addTableReferenceJoin(TableReferenceJoin join);
}

View File

@ -6,19 +6,22 @@
*/ */
package org.hibernate.sql.ast.tree.from; package org.hibernate.sql.ast.tree.from;
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.sql.ast.JoinType; import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase; import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface TableReferenceContributor { public interface TableReferenceContributor {
// /** /**
// * Apply the Tables mapped by this producer to the collector as TableReferences * Apply the Tables mapped by this producer to the collector as TableReferences
// */ */
// void applyTableReferenceJoins( void applyTableReferences(
// ColumnReferenceQualifier lhs, SqlAliasBase sqlAliasBase,
// JoinType joinType, JoinType baseJoinType,
// SqlAliasBase sqlAliasBase, TableReferenceCollector collector,
// TableReferenceJoinCollector joinCollector); SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext);
} }

View File

@ -0,0 +1,24 @@
/*
* 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.sql.ast.tree.from;
import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.tree.predicate.Predicate;
/**
* Functional contract for producing the join-predicate related to a {@link TableReferenceJoin}.
*
* @see TableReferenceJoin#getJoinPredicate
* @see TableReferenceCollector#applySecondaryTableReferences
*
* @author Steve Ebersole
*/
@FunctionalInterface
public
interface TableReferenceJoinPredicateProducer {
Predicate producePredicate(TableReference lhs, TableReference rhs, JoinType joinType);
}

View File

@ -0,0 +1,97 @@
/*
* 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.sql.results.internal;
import java.io.Serializable;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.results.spi.CollectionInitializer;
import org.hibernate.sql.results.spi.LoadingCollectionEntry;
/**
* Represents a collection currently being loaded.
*
* @author Steve Ebersole
*/
public class LoadingCollectionEntryImpl implements LoadingCollectionEntry {
private final CollectionPersister collectionDescriptor;
private final CollectionInitializer initializer;
private final Object key;
private final PersistentCollection collectionInstance;
public LoadingCollectionEntryImpl(
CollectionPersister collectionDescriptor,
CollectionInitializer initializer,
Object key,
PersistentCollection collectionInstance) {
this.collectionDescriptor = collectionDescriptor;
this.initializer = initializer;
this.key = key;
this.collectionInstance = collectionInstance;
collectionInstance.beforeInitialize( getCollectionDescriptor(), -1 );
collectionInstance.beginRead();
}
@Override public CollectionPersister getCollectionDescriptor() {
return collectionDescriptor;
}
/**
* Access to the initializer that is responsible for initializing this collection
*/
@Override public CollectionInitializer getInitializer() {
return initializer;
}
@Override public Serializable getKey() {
// todo (6.0) : change from Serializable to Object
return (Serializable) key;
}
@Override public PersistentCollection getCollectionInstance() {
return collectionInstance;
}
@Override
public String toString() {
return getClass().getSimpleName() + "(" + getCollectionDescriptor().getNavigableRole().getFullPath() + "#" + getKey() + ")";
}
@Override public void finishLoading(ExecutionContext executionContext) {
collectionInstance.endRead();
final SharedSessionContractImplementor session = executionContext.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext();
final CollectionPersister collectionDescriptor = getCollectionDescriptor();
CollectionEntry collectionEntry = persistenceContext.getCollectionEntry( collectionInstance );
if ( collectionEntry == null ) {
collectionEntry = persistenceContext.addInitializedCollection(
collectionDescriptor,
getCollectionInstance(),
getKey()
);
}
else {
collectionEntry.postInitialize( collectionInstance );
}
if ( collectionDescriptor.getCollectionType().hasHolder() ) {
persistenceContext.addCollectionHolder( collectionInstance );
}
// todo (6.0) : there is other logic still needing to be implemented here. caching, etc
// see org.hibernate.engine.loading.internal.CollectionLoadContext#endLoadingCollection in 5.x
}
}

View File

@ -11,7 +11,9 @@ import java.util.List;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.named.RowReaderMemento; import org.hibernate.query.named.RowReaderMemento;
import org.hibernate.sql.exec.spi.Callback; import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.results.spi.CollectionInitializer;
import org.hibernate.sql.results.spi.DomainResultAssembler; import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.EntityInitializer;
import org.hibernate.sql.results.spi.Initializer; import org.hibernate.sql.results.spi.Initializer;
import org.hibernate.sql.results.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.spi.JdbcValuesSourceProcessingState; import org.hibernate.sql.results.spi.JdbcValuesSourceProcessingState;
@ -125,7 +127,17 @@ public class StandardRowReader<T> implements RowReader<T> {
// old // old
for ( int i = 0; i < initializers.size(); i++ ) { for ( int i = 0; i < initializers.size(); i++ ) {
initializers.get( i ).resolveKey( rowProcessingState ); final Initializer initializer = initializers.get( i );
if ( ! ( initializer instanceof CollectionInitializer ) ) {
initializer.resolveKey( rowProcessingState );
}
}
for ( int i = 0; i < initializers.size(); i++ ) {
final Initializer initializer = initializers.get( i );
if ( initializer instanceof CollectionInitializer ) {
initializer.resolveKey( rowProcessingState );
}
} }
for ( int i = 0; i < initializers.size(); i++ ) { for ( int i = 0; i < initializers.size(); i++ ) {

View File

@ -0,0 +1,56 @@
/*
* 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.sql.results.internal.domain.collection;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.spi.Fetch;
import org.hibernate.sql.results.spi.FetchParent;
/**
* @author Steve Ebersole
*/
public abstract class CollectionFetch implements Fetch {
private final NavigablePath fetchedPath;
private final PluralAttributeMapping fetchedAttribute;
private final boolean nullable;
private final FetchParent fetchParent;
public CollectionFetch(
NavigablePath fetchedPath,
PluralAttributeMapping fetchedAttribute,
boolean nullable,
FetchParent fetchParent) {
this.fetchedPath = fetchedPath;
this.fetchedAttribute = fetchedAttribute;
this.fetchParent = fetchParent;
this.nullable = nullable;
}
@Override
public FetchParent getFetchParent() {
return fetchParent;
}
@Override
public PluralAttributeMapping getFetchedMapping() {
return fetchedAttribute;
}
@Override
public NavigablePath getNavigablePath() {
return fetchedPath;
}
@Override
public boolean isNullable() {
return nullable;
}
}

View File

@ -0,0 +1,155 @@
/*
* 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.sql.results.internal.domain.collection;
import java.io.Serializable;
import java.util.function.Consumer;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.spi.AssemblerCreationState;
import org.hibernate.sql.results.spi.CollectionInitializer;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.FetchParentAccess;
import org.hibernate.sql.results.spi.Initializer;
import org.hibernate.sql.results.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.spi.LoadingCollectionEntry;
import org.hibernate.sql.results.spi.RowProcessingState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Steve Ebersole
*/
public class DelayedCollectionAssembler implements DomainResultAssembler {
private final PluralAttributeMapping fetchedMapping;
private final FetchParentAccess parentAccess;
private final CollectionInitializer initializer;
public DelayedCollectionAssembler(
NavigablePath fetchPath,
PluralAttributeMapping fetchedMapping,
FetchParentAccess parentAccess,
Consumer<Initializer> collector,
AssemblerCreationState creationState) {
this.fetchedMapping = fetchedMapping;
this.parentAccess = parentAccess;
this.initializer = new InitializerImpl( fetchPath, fetchedMapping, parentAccess, creationState );
collector.accept( initializer );
}
@Override
public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
return initializer.getCollectionInstance();
}
@Override
public JavaTypeDescriptor getAssembledJavaTypeDescriptor() {
return fetchedMapping.getJavaTypeDescriptor();
}
private static class InitializerImpl implements CollectionInitializer {
private final NavigablePath fetchedPath;
private final PluralAttributeMapping fetchedMapping;
private final FetchParentAccess parentAccess;
private CollectionKey collectionKey;
private PersistentCollection instance;
public InitializerImpl(
NavigablePath fetchedPath,
PluralAttributeMapping fetchedMapping,
FetchParentAccess parentAccess,
AssemblerCreationState creationState) {
this.fetchedPath = fetchedPath;
this.fetchedMapping = fetchedMapping;
this.parentAccess = parentAccess;
}
@Override
public NavigablePath getNavigablePath() {
return fetchedPath;
}
@Override
public void resolveKey(RowProcessingState rowProcessingState) {
if ( collectionKey != null ) {
// already resolved
return;
}
collectionKey = new CollectionKey(
fetchedMapping.getCollectionDescriptor(),
parentAccess.getParentKey()
);
}
@Override
public void resolveInstance(RowProcessingState rowProcessingState) {
final SharedSessionContractImplementor session = rowProcessingState.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext();
final LoadingCollectionEntry loadingEntry = persistenceContext.getLoadContexts().findLoadingCollectionEntry( collectionKey );
final PersistentCollection registeredInstance = persistenceContext.getCollection( collectionKey );
if ( loadingEntry != null ) {
instance = loadingEntry.getCollectionInstance();
return;
}
if ( registeredInstance != null ) {
this.instance = registeredInstance;
return;
}
this.instance = makePersistentCollection( fetchedMapping, collectionKey, rowProcessingState );
persistenceContext.addUninitializedCollection(
getInitializingCollectionDescriptor(),
instance,
(Serializable) collectionKey.getKey()
);
}
private static PersistentCollection makePersistentCollection(
PluralAttributeMapping fetchedMapping,
CollectionKey collectionKey,
RowProcessingState rowProcessingState) {
final CollectionPersister collectionDescriptor = fetchedMapping.getCollectionDescriptor();
final CollectionSemantics collectionSemantics = collectionDescriptor.getCollectionSemantics();
return collectionSemantics.instantiateWrapper(
collectionKey.getKey(),
collectionDescriptor,
rowProcessingState.getSession()
);
}
@Override
public void initializeInstance(RowProcessingState rowProcessingState) {
}
@Override
public void finishUpRow(RowProcessingState rowProcessingState) {
collectionKey = null;
instance = null;
}
@Override
public CollectionPersister getInitializingCollectionDescriptor() {
return fetchedMapping.getCollectionDescriptor();
}
@Override
public PersistentCollection getCollectionInstance() {
return instance;
}
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.sql.results.internal.domain.collection;
import java.util.function.Consumer;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.spi.AssemblerCreationState;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.FetchParent;
import org.hibernate.sql.results.spi.FetchParentAccess;
import org.hibernate.sql.results.spi.Initializer;
/**
* @author Steve Ebersole
*/
public class DelayedCollectionFetch extends CollectionFetch {
public DelayedCollectionFetch(
NavigablePath fetchedPath,
PluralAttributeMapping fetchedAttribute,
boolean nullable,
FetchParent fetchParent) {
super( fetchedPath, fetchedAttribute, nullable, fetchParent );
}
@Override
public DomainResultAssembler createAssembler(
FetchParentAccess parentAccess,
Consumer<Initializer> collector,
AssemblerCreationState creationState) {
return new DelayedCollectionAssembler(
getNavigablePath(),
getFetchedMapping(),
parentAccess,
collector,
creationState
);
}
}

View File

@ -0,0 +1,258 @@
/*
* 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.sql.results.internal.domain.collection;
import java.util.function.Consumer;
import org.hibernate.collection.spi.CollectionSemantics;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.internal.LoadingCollectionEntryImpl;
import org.hibernate.sql.results.spi.AssemblerCreationState;
import org.hibernate.sql.results.spi.CollectionInitializer;
import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.Fetch;
import org.hibernate.sql.results.spi.FetchParentAccess;
import org.hibernate.sql.results.spi.Initializer;
import org.hibernate.sql.results.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.spi.LoadContexts;
import org.hibernate.sql.results.spi.LoadingCollectionEntry;
import org.hibernate.sql.results.spi.RowProcessingState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Steve Ebersole
*/
public class EagerCollectionAssembler implements DomainResultAssembler {
private final PluralAttributeMapping fetchedMapping;
private final FetchParentAccess parentAccess;
private final CollectionInitializer initializer;
public EagerCollectionAssembler(
NavigablePath fetchPath,
PluralAttributeMapping fetchedMapping,
DomainResult fkResult,
Fetch elementFetch,
Fetch indexFetch,
DomainResult identifierResult,
FetchParentAccess parentAccess,
Consumer<Initializer> collector,
AssemblerCreationState creationState) {
this.fetchedMapping = fetchedMapping;
this.parentAccess = parentAccess;
this.initializer = new InitializerImpl(
fetchPath,
fetchedMapping,
parentAccess,
fkResult,
elementFetch,
indexFetch,
identifierResult,
collector,
creationState
);
collector.accept( initializer );
}
@Override
public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) {
return initializer.getCollectionInstance();
}
@Override
public JavaTypeDescriptor getAssembledJavaTypeDescriptor() {
return fetchedMapping.getJavaTypeDescriptor();
}
private static class InitializerImpl implements CollectionInitializer {
private final NavigablePath fetchedPath;
private final PluralAttributeMapping fetchedMapping;
private final FetchParentAccess parentAccess;
private final DomainResultAssembler fkAssembler;
private final DomainResultAssembler elementAssembler;
private final DomainResultAssembler indexAssembler;
private final DomainResultAssembler identifierAssembler;
private CollectionKey collectionKey;
private boolean managing;
private Object fkValue;
// todo (6.0) : consider using the initializer itself as the holder of the various "temp" collections
// used while reading a collection. that would mean collection-type specific initializers (List, versus Set)
private PersistentCollection instance;
public InitializerImpl(
NavigablePath fetchedPath,
PluralAttributeMapping fetchedMapping,
FetchParentAccess parentAccess,
DomainResult fkResult,
Fetch elementFetch,
Fetch indexFetch,
DomainResult identifierResult,
Consumer<Initializer> collector,
AssemblerCreationState creationState) {
this.fetchedPath = fetchedPath;
this.fetchedMapping = fetchedMapping;
this.parentAccess = parentAccess;
this.fkAssembler = fkResult.createResultAssembler( collector, creationState );
// questionable what should be the parent access here
this.elementAssembler = elementFetch.createAssembler( parentAccess, collector, creationState );
this.indexAssembler = indexFetch == null
? null
: indexFetch.createAssembler( parentAccess, collector, creationState );
this.identifierAssembler = identifierResult == null
? null
: identifierResult.createResultAssembler( collector, creationState );
}
@Override
public CollectionPersister getInitializingCollectionDescriptor() {
return fetchedMapping.getCollectionDescriptor();
}
@Override
public PersistentCollection getCollectionInstance() {
return instance;
}
@Override
public NavigablePath getNavigablePath() {
return fetchedPath;
}
@Override
public void finishUpRow(RowProcessingState rowProcessingState) {
collectionKey = null;
managing = false;
instance = null;
}
@Override
public void resolveKey(RowProcessingState rowProcessingState) {
if ( collectionKey != null ) {
// already resolved
return;
}
collectionKey = new CollectionKey(
fetchedMapping.getCollectionDescriptor(),
parentAccess.getParentKey()
);
final Object fkValue = fkAssembler.assemble( rowProcessingState );
if ( fkValue == null ) {
// this row has no collection element
return;
}
}
@Override
public void resolveInstance(RowProcessingState rowProcessingState) {
if ( instance != null ) {
// already resolved
return;
}
final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext();
// see if the collection is already being initialized
final LoadContexts loadContexts = persistenceContext.getLoadContexts();
final LoadingCollectionEntry existingEntry = loadContexts.findLoadingCollectionEntry( collectionKey );
if ( existingEntry != null ) {
this.instance = existingEntry.getCollectionInstance();
if ( existingEntry.getInitializer() == this ) {
this.managing = true;
}
return;
}
// see if it has been already registered with the Session
final PersistentCollection registeredInstance = persistenceContext.getCollection( collectionKey );
if ( registeredInstance != null ) {
this.instance = registeredInstance;
// it was already registered, so use that wrapper.
if ( ! registeredInstance.wasInitialized() ) {
// if the existing wrapper is not initialized, we will take responsibility for initializing it
managing = true;
rowProcessingState.getJdbcValuesSourceProcessingState().registerLoadingCollection(
collectionKey,
new LoadingCollectionEntryImpl(
getInitializingCollectionDescriptor(),
this,
collectionKey,
registeredInstance
)
);
return;
}
}
this.instance = makePersistentCollection( fetchedMapping, collectionKey, rowProcessingState );
this.managing = true;
rowProcessingState.getJdbcValuesSourceProcessingState().registerLoadingCollection(
collectionKey,
new LoadingCollectionEntryImpl(
fetchedMapping.getCollectionDescriptor(),
this,
collectionKey.getKey(),
instance
)
);
}
private static PersistentCollection makePersistentCollection(
PluralAttributeMapping fetchedMapping,
CollectionKey collectionKey,
RowProcessingState rowProcessingState) {
final CollectionPersister collectionDescriptor = fetchedMapping.getCollectionDescriptor();
final CollectionSemantics collectionSemantics = collectionDescriptor.getCollectionSemantics();
return collectionSemantics.instantiateWrapper(
collectionKey.getKey(),
collectionDescriptor,
rowProcessingState.getSession()
);
}
@Override
public void initializeInstance(RowProcessingState rowProcessingState) {
if ( ! managing ) {
return;
}
final Object fkValue = fkAssembler.assemble( rowProcessingState );
if ( fkValue == null ) {
// this row contains no collection element
return;
}
getCollectionInstance().readFrom(
rowProcessingState,
elementAssembler,
indexAssembler,
identifierAssembler,
parentAccess.getFetchParentInstance()
);
}
}
}

View File

@ -0,0 +1,125 @@
/*
* 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.sql.results.internal.domain.collection;
import java.util.List;
import java.util.function.Consumer;
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.spi.AssemblerCreationState;
import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.sql.results.spi.DomainResultCreationState;
import org.hibernate.sql.results.spi.Fetch;
import org.hibernate.sql.results.spi.FetchParent;
import org.hibernate.sql.results.spi.FetchParentAccess;
import org.hibernate.sql.results.spi.FetchableContainer;
import org.hibernate.sql.results.spi.Initializer;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Steve Ebersole
*/
public class EagerCollectionFetch extends CollectionFetch implements FetchParent {
private final DomainResult fkResult;
private final Fetch elementFetch;
private final Fetch indexFetch;
private final DomainResult identifierResult;
private final List<Fetch> fetches;
public EagerCollectionFetch(
NavigablePath fetchedPath,
PluralAttributeMapping fetchedAttribute,
DomainResult fkResult,
boolean nullable,
FetchParent fetchParent,
DomainResultCreationState creationState) {
super( fetchedPath, fetchedAttribute, nullable, fetchParent );
this.fkResult = fkResult;
final CollectionIdentifierDescriptor identifierDescriptor = fetchedAttribute.getIdentifierDescriptor();
if ( identifierDescriptor == null ) {
this.identifierResult = null;
}
else {
final TableGroup collectionTableGroup = creationState.getSqlAstCreationState().getFromClauseAccess().getTableGroup( fetchedPath );
this.identifierResult = identifierDescriptor.createDomainResult( fetchedPath, collectionTableGroup, creationState );
}
fetches = creationState.visitFetches( this );
if ( fetchedAttribute.getIndexDescriptor() != null ) {
assert fetches.size() == 2;
indexFetch = fetches.get( 0 );
elementFetch = fetches.get( 1 );
}
else {
assert fetches.size() == 1;
indexFetch = null;
elementFetch = fetches.get( 0 );
}
}
@Override
public DomainResultAssembler createAssembler(
FetchParentAccess parentAccess,
Consumer<Initializer> collector,
AssemblerCreationState creationState) {
return new EagerCollectionAssembler(
getNavigablePath(),
getFetchedMapping(),
fkResult,
elementFetch,
indexFetch,
identifierResult,
parentAccess,
collector,
creationState
);
}
@Override
public FetchableContainer getReferencedMappingContainer() {
return getFetchedMapping();
}
@Override
public PluralAttributeMapping getReferencedMappingType() {
return getFetchedMapping();
}
@Override
public List<Fetch> getFetches() {
return fetches;
}
@Override
public Fetch findFetch(String fetchableName) {
if ( CollectionPart.Nature.ELEMENT.getName().equals( fetchableName ) ) {
return elementFetch;
}
else if ( CollectionPart.Nature.INDEX.getName().equals( fetchableName ) ) {
return indexFetch;
}
else {
throw new IllegalArgumentException(
"Unknown fetchable [" + getFetchedMapping().getCollectionDescriptor().getRole() +
" -> " + fetchableName + "]"
);
}
}
@Override
public JavaTypeDescriptor getResultJavaTypeDescriptor() {
return getFetchedMapping().getJavaTypeDescriptor();
}
}

View File

@ -10,7 +10,7 @@ import java.util.function.Consumer;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.results.internal.domain.AbstractFetchParent; import org.hibernate.sql.results.internal.domain.AbstractFetchParent;
import org.hibernate.sql.results.spi.AssemblerCreationState; import org.hibernate.sql.results.spi.AssemblerCreationState;
@ -29,17 +29,20 @@ import org.hibernate.sql.results.spi.Initializer;
public class CompositeFetch extends AbstractFetchParent implements CompositeResultMappingNode, Fetch { public class CompositeFetch extends AbstractFetchParent implements CompositeResultMappingNode, Fetch {
private final FetchParent fetchParent; private final FetchParent fetchParent;
private final FetchTiming fetchTiming; private final FetchTiming fetchTiming;
private final boolean nullable;
public CompositeFetch( public CompositeFetch(
NavigablePath navigablePath, NavigablePath navigablePath,
EmbeddedAttributeMapping embeddedAttribute, EmbeddableValuedModelPart embeddedPartDescriptor,
FetchParent fetchParent, FetchParent fetchParent,
FetchTiming fetchTiming, FetchTiming fetchTiming,
boolean nullable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
super( embeddedAttribute, navigablePath ); super( embeddedPartDescriptor, navigablePath );
this.fetchParent = fetchParent; this.fetchParent = fetchParent;
this.fetchTiming = fetchTiming; this.fetchTiming = fetchTiming;
this.nullable = nullable;
creationState.getSqlAstCreationState().getFromClauseAccess().registerTableGroup( creationState.getSqlAstCreationState().getFromClauseAccess().registerTableGroup(
getNavigablePath(), getNavigablePath(),
@ -49,38 +52,34 @@ public class CompositeFetch extends AbstractFetchParent implements CompositeResu
afterInitialize( creationState ); afterInitialize( creationState );
} }
public EmbeddedAttributeMapping getEmbeddedAttributeMapping() {
return (EmbeddedAttributeMapping) super.getFetchContainer();
}
@Override @Override
public FetchParent getFetchParent() { public FetchParent getFetchParent() {
return fetchParent; return fetchParent;
} }
@Override @Override
public EmbeddedAttributeMapping getFetchContainer() { public EmbeddableValuedModelPart getFetchContainer() {
return getEmbeddedAttributeMapping(); return (EmbeddableValuedModelPart) super.getFetchContainer();
} }
@Override @Override
public EmbeddedAttributeMapping getReferencedMappingContainer() { public EmbeddableValuedModelPart getReferencedMappingContainer() {
return getEmbeddedAttributeMapping(); return getFetchContainer();
} }
@Override @Override
public Fetchable getFetchedMapping() { public Fetchable getFetchedMapping() {
return getEmbeddedAttributeMapping(); return getFetchContainer();
} }
@Override @Override
public EmbeddableMappingType getReferencedMappingType() { public EmbeddableMappingType getReferencedMappingType() {
return getEmbeddedAttributeMapping().getEmbeddableTypeDescriptor(); return getFetchContainer().getEmbeddableTypeDescriptor();
} }
@Override @Override
public boolean isNullable() { public boolean isNullable() {
return getEmbeddedAttributeMapping().getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(); return nullable;
} }
@Override @Override

View File

@ -27,4 +27,9 @@ public class CompositeFetchInitializer
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
super( resultDescriptor, fetchParentAccess, initializerConsumer, creationState ); super( resultDescriptor, fetchParentAccess, initializerConsumer, creationState );
} }
@Override
public Object getParentKey() {
return getFetchParentAccess().getParentKey();
}
} }

View File

@ -22,4 +22,9 @@ public class CompositeRootInitializer extends AbstractCompositeInitializer {
AssemblerCreationState creationState) { AssemblerCreationState creationState) {
super( resultDescriptor, null, initializerConsumer, creationState ); super( resultDescriptor, null, initializerConsumer, creationState );
} }
@Override
public Object getParentKey() {
return null;
}
} }

View File

@ -34,7 +34,6 @@ import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener; import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable; import org.hibernate.persister.entity.Loadable;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
@ -197,6 +196,11 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
return entityKey.getIdentifier(); return entityKey.getIdentifier();
} }
@Override
public Object getParentKey() {
return getKeyValue();
}
@Override @Override
public Object getFetchParentInstance() { public Object getFetchParentInstance() {
if ( entityInstance == null ) { if ( entityInstance == null ) {

View File

@ -25,8 +25,6 @@ import org.hibernate.sql.results.spi.EntityResult;
public class EntityResultImpl extends AbstractEntityResultNode implements EntityResult { public class EntityResultImpl extends AbstractEntityResultNode implements EntityResult {
private final String resultVariable; private final String resultVariable;
public EntityResultImpl( public EntityResultImpl(
NavigablePath navigablePath, NavigablePath navigablePath,
EntityValuedModelPart entityValuedModelPart, EntityValuedModelPart entityValuedModelPart,

View File

@ -8,7 +8,7 @@ package org.hibernate.sql.results.spi;
import java.util.List; import java.util.List;
import org.hibernate.metamodel.mapping.ManagedMappingType; import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
/** /**
@ -22,7 +22,7 @@ public interface FetchParent extends ResultSetMappingNode {
/** /**
* This parent's type * This parent's type
*/ */
ManagedMappingType getReferencedMappingType(); FetchableContainer getReferencedMappingType();
/** /**
* Get the property path to this parent * Get the property path to this parent

View File

@ -19,6 +19,8 @@ import org.hibernate.query.NavigablePath;
public interface FetchParentAccess { public interface FetchParentAccess {
FetchParentAccess findFirstEntityDescriptorAccess(); FetchParentAccess findFirstEntityDescriptorAccess();
Object getParentKey();
/** /**
* Access to the fetch's parent instance. * Access to the fetch's parent instance.
*/ */

View File

@ -15,6 +15,8 @@ import org.hibernate.metamodel.mapping.ModelPartContainer;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface FetchableContainer extends ModelPartContainer { public interface FetchableContainer extends ModelPartContainer {
int getNumberOfFetchables();
default void visitKeyFetchables( default void visitKeyFetchables(
Consumer<Fetchable> fetchableConsumer, Consumer<Fetchable> fetchableConsumer,
EntityMappingType treatTargetType) { EntityMappingType treatTargetType) {

View File

@ -6,8 +6,6 @@
*/ */
package org.hibernate.sql.results.spi; package org.hibernate.sql.results.spi;
import java.sql.ResultSet;
import org.hibernate.engine.spi.CollectionKey; import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
@ -18,7 +16,7 @@ import org.hibernate.internal.util.collections.StandardStack;
/** /**
* Maintains a Stack of processing state related to performing load operations. * Maintains a Stack of processing state related to performing load operations.
* The sCollectionLoadContexttate is defined by {@link JdbcValuesSourceProcessingState} which * The state is defined by {@link JdbcValuesSourceProcessingState} which
* encapsulates the data to be processed by the load whether the data comes from * encapsulates the data to be processed by the load whether the data comes from
* a ResultSet or second-level cache hit. * a ResultSet or second-level cache hit.
* *

View File

@ -9,9 +9,6 @@ package org.hibernate.sql.results.spi;
import java.io.Serializable; import java.io.Serializable;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
@ -20,76 +17,14 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class LoadingCollectionEntry { public interface LoadingCollectionEntry {
private final CollectionPersister collectionDescriptor; CollectionPersister getCollectionDescriptor();
private final CollectionInitializer initializer;
// todo (6.0) : change from Serializable to Object
private final Serializable key;
private final PersistentCollection collectionInstance;
public LoadingCollectionEntry( CollectionInitializer getInitializer();
CollectionPersister collectionDescriptor,
CollectionInitializer initializer,
Serializable key,
PersistentCollection collectionInstance) {
this.collectionDescriptor = collectionDescriptor;
this.initializer = initializer;
this.key = key;
this.collectionInstance = collectionInstance;
collectionInstance.beforeInitialize( getCollectionDescriptor(), -1 ); Serializable getKey();
collectionInstance.beginRead();
}
public CollectionPersister getCollectionDescriptor() { PersistentCollection getCollectionInstance();
return collectionDescriptor;
}
/** void finishLoading(ExecutionContext executionContext);
* Access to the initializer that is responsible for initializing this collection
*/
public CollectionInitializer getInitializer() {
return initializer;
}
public Serializable getKey() {
return key;
}
public PersistentCollection getCollectionInstance() {
return collectionInstance;
}
@Override
public String toString() {
return getClass().getSimpleName() + "(" + getCollectionDescriptor().getNavigableRole().getFullPath() + "#" + getKey() + ")";
}
public void finishLoading(ExecutionContext executionContext) {
collectionInstance.endRead();
final SharedSessionContractImplementor session = executionContext.getSession();
final PersistenceContext persistenceContext = session.getPersistenceContext();
final CollectionPersister collectionDescriptor = getCollectionDescriptor();
CollectionEntry collectionEntry = persistenceContext.getCollectionEntry( collectionInstance );
if ( collectionEntry == null ) {
collectionEntry = persistenceContext.addInitializedCollection(
collectionDescriptor,
getCollectionInstance(),
getKey()
);
}
else {
collectionEntry.postInitialize( collectionInstance );
}
if ( collectionDescriptor.getCollectionType().hasHolder() ) {
persistenceContext.addCollectionHolder( collectionInstance );
}
// todo (6.0) : there is other logic still needing to be implemented here. caching, etc
// see org.hibernate.engine.loading.internal.CollectionLoadContext#endLoadingCollection in 5.x
}
} }

View File

@ -7,6 +7,7 @@
package org.hibernate.type.descriptor.java; package org.hibernate.type.descriptor.java;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.spi.Primitive;
import static java.lang.Boolean.FALSE; import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE; import static java.lang.Boolean.TRUE;
@ -16,7 +17,7 @@ import static java.lang.Boolean.TRUE;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class BooleanTypeDescriptor extends AbstractTypeDescriptor<Boolean> { public class BooleanTypeDescriptor extends AbstractTypeDescriptor<Boolean> implements Primitive<Boolean> {
public static final BooleanTypeDescriptor INSTANCE = new BooleanTypeDescriptor(); public static final BooleanTypeDescriptor INSTANCE = new BooleanTypeDescriptor();
private final char characterValueTrue; private final char characterValueTrue;
@ -130,4 +131,14 @@ public class BooleanTypeDescriptor extends AbstractTypeDescriptor<Boolean> {
public Long toLong(Boolean value) { public Long toLong(Boolean value) {
return (long) toInt( value ); return (long) toInt( value );
} }
@Override
public Class getPrimitiveClass() {
return boolean.class;
}
@Override
public Boolean getDefaultValue() {
return FALSE;
}
} }

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.type.descriptor.java; package org.hibernate.type.descriptor.java;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.spi.Primitive;
/** /**
* Descriptor for {@link Byte} handling. * Descriptor for {@link Byte} handling.
@ -13,7 +14,7 @@ import org.hibernate.type.descriptor.WrapperOptions;
* @author Steve Ebersole * @author Steve Ebersole
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/ */
public class ByteTypeDescriptor extends AbstractTypeDescriptor<Byte> { public class ByteTypeDescriptor extends AbstractTypeDescriptor<Byte> implements Primitive<Byte> {
public static final ByteTypeDescriptor INSTANCE = new ByteTypeDescriptor(); public static final ByteTypeDescriptor INSTANCE = new ByteTypeDescriptor();
public ByteTypeDescriptor() { public ByteTypeDescriptor() {
@ -58,6 +59,7 @@ public class ByteTypeDescriptor extends AbstractTypeDescriptor<Byte> {
} }
throw unknownUnwrap( type ); throw unknownUnwrap( type );
} }
@Override @Override
public <X> Byte wrap(X value, WrapperOptions options) { public <X> Byte wrap(X value, WrapperOptions options) {
if ( value == null ) { if ( value == null ) {
@ -74,4 +76,14 @@ public class ByteTypeDescriptor extends AbstractTypeDescriptor<Byte> {
} }
throw unknownWrap( value.getClass() ); throw unknownWrap( value.getClass() );
} }
@Override
public Class getPrimitiveClass() {
return byte.class;
}
@Override
public Byte getDefaultValue() {
return 0;
}
} }

View File

@ -7,13 +7,14 @@
package org.hibernate.type.descriptor.java; package org.hibernate.type.descriptor.java;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.spi.Primitive;
/** /**
* Descriptor for {@link Character} handling. * Descriptor for {@link Character} handling.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CharacterTypeDescriptor extends AbstractTypeDescriptor<Character> { public class CharacterTypeDescriptor extends AbstractTypeDescriptor<Character> implements Primitive<Character> {
public static final CharacterTypeDescriptor INSTANCE = new CharacterTypeDescriptor(); public static final CharacterTypeDescriptor INSTANCE = new CharacterTypeDescriptor();
public CharacterTypeDescriptor() { public CharacterTypeDescriptor() {
@ -66,4 +67,14 @@ public class CharacterTypeDescriptor extends AbstractTypeDescriptor<Character> {
} }
throw unknownWrap( value.getClass() ); throw unknownWrap( value.getClass() );
} }
@Override
public Class getPrimitiveClass() {
return char.class;
}
@Override
public Character getDefaultValue() {
return 0;
}
} }

View File

@ -10,13 +10,14 @@ import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.spi.Primitive;
/** /**
* Descriptor for {@link Double} handling. * Descriptor for {@link Double} handling.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class DoubleTypeDescriptor extends AbstractTypeDescriptor<Double> { public class DoubleTypeDescriptor extends AbstractTypeDescriptor<Double> implements Primitive<Double> {
public static final DoubleTypeDescriptor INSTANCE = new DoubleTypeDescriptor(); public static final DoubleTypeDescriptor INSTANCE = new DoubleTypeDescriptor();
public DoubleTypeDescriptor() { public DoubleTypeDescriptor() {
@ -71,15 +72,25 @@ public class DoubleTypeDescriptor extends AbstractTypeDescriptor<Double> {
if ( value == null ) { if ( value == null ) {
return null; return null;
} }
if ( Double.class.isInstance( value ) ) { if ( value instanceof Double ) {
return (Double) value; return (Double) value;
} }
if ( Number.class.isInstance( value ) ) { if ( value instanceof Number ) {
return ( (Number) value ).doubleValue(); return ( (Number) value ).doubleValue();
} }
else if ( String.class.isInstance( value ) ) { else if ( value instanceof String ) {
return Double.valueOf( ( (String) value ) ); return Double.valueOf( ( (String) value ) );
} }
throw unknownWrap( value.getClass() ); throw unknownWrap( value.getClass() );
} }
@Override
public Class getPrimitiveClass() {
return double.class;
}
@Override
public Double getDefaultValue() {
return 0.0;
}
} }

View File

@ -10,13 +10,14 @@ import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.spi.Primitive;
/** /**
* Descriptor for {@link Float} handling. * Descriptor for {@link Float} handling.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class FloatTypeDescriptor extends AbstractTypeDescriptor<Float> { public class FloatTypeDescriptor extends AbstractTypeDescriptor<Float> implements Primitive<Float> {
public static final FloatTypeDescriptor INSTANCE = new FloatTypeDescriptor(); public static final FloatTypeDescriptor INSTANCE = new FloatTypeDescriptor();
public FloatTypeDescriptor() { public FloatTypeDescriptor() {
@ -82,4 +83,14 @@ public class FloatTypeDescriptor extends AbstractTypeDescriptor<Float> {
} }
throw unknownWrap( value.getClass() ); throw unknownWrap( value.getClass() );
} }
@Override
public Class getPrimitiveClass() {
return float.class;
}
@Override
public Float getDefaultValue() {
return 0F;
}
} }

View File

@ -10,13 +10,14 @@ import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.spi.Primitive;
/** /**
* Descriptor for {@link Integer} handling. * Descriptor for {@link Integer} handling.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class IntegerTypeDescriptor extends AbstractTypeDescriptor<Integer> { public class IntegerTypeDescriptor extends AbstractTypeDescriptor<Integer> implements Primitive<Integer> {
public static final IntegerTypeDescriptor INSTANCE = new IntegerTypeDescriptor(); public static final IntegerTypeDescriptor INSTANCE = new IntegerTypeDescriptor();
public IntegerTypeDescriptor() { public IntegerTypeDescriptor() {
@ -82,4 +83,14 @@ public class IntegerTypeDescriptor extends AbstractTypeDescriptor<Integer> {
} }
throw unknownWrap( value.getClass() ); throw unknownWrap( value.getClass() );
} }
@Override
public Class getPrimitiveClass() {
return int.class;
}
@Override
public Integer getDefaultValue() {
return 0;
}
} }

View File

@ -10,13 +10,14 @@ import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.spi.Primitive;
/** /**
* Descriptor for {@link Long} handling. * Descriptor for {@link Long} handling.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class LongTypeDescriptor extends AbstractTypeDescriptor<Long> { public class LongTypeDescriptor extends AbstractTypeDescriptor<Long>implements Primitive<Long> {
public static final LongTypeDescriptor INSTANCE = new LongTypeDescriptor(); public static final LongTypeDescriptor INSTANCE = new LongTypeDescriptor();
public LongTypeDescriptor() { public LongTypeDescriptor() {
@ -82,4 +83,14 @@ public class LongTypeDescriptor extends AbstractTypeDescriptor<Long> {
} }
throw unknownWrap( value.getClass() ); throw unknownWrap( value.getClass() );
} }
@Override
public Class getPrimitiveClass() {
return long.class;
}
@Override
public Long getDefaultValue() {
return 0L;
}
} }

View File

@ -6,13 +6,14 @@
*/ */
package org.hibernate.type.descriptor.java; package org.hibernate.type.descriptor.java;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.spi.Primitive;
/** /**
* Descriptor for {@link Short} handling. * Descriptor for {@link Short} handling.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ShortTypeDescriptor extends AbstractTypeDescriptor<Short> { public class ShortTypeDescriptor extends AbstractTypeDescriptor<Short> implements Primitive<Short> {
public static final ShortTypeDescriptor INSTANCE = new ShortTypeDescriptor(); public static final ShortTypeDescriptor INSTANCE = new ShortTypeDescriptor();
public ShortTypeDescriptor() { public ShortTypeDescriptor() {
@ -72,4 +73,14 @@ public class ShortTypeDescriptor extends AbstractTypeDescriptor<Short> {
} }
throw unknownWrap( value.getClass() ); throw unknownWrap( value.getClass() );
} }
@Override
public Class getPrimitiveClass() {
return short.class;
}
@Override
public Short getDefaultValue() {
return 0;
}
} }

View File

@ -39,6 +39,7 @@ public class JavaTypeDescriptorRegistry implements JavaTypeDescriptorBaseline.Ba
@SuppressWarnings("unused") @SuppressWarnings("unused")
public JavaTypeDescriptorRegistry(TypeConfiguration typeConfiguration) { public JavaTypeDescriptorRegistry(TypeConfiguration typeConfiguration) {
this.typeConfiguration = typeConfiguration; this.typeConfiguration = typeConfiguration;
JavaTypeDescriptorBaseline.prime( this );
} }

View File

@ -21,6 +21,7 @@ import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata; import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cache.spi.access.EntityDataAccess; import org.hibernate.cache.spi.access.EntityDataAccess;
import org.hibernate.cache.spi.access.NaturalIdDataAccess; import org.hibernate.cache.spi.access.NaturalIdDataAccess;
@ -58,6 +59,11 @@ import org.hibernate.persister.spi.PersisterClassResolver;
import org.hibernate.persister.spi.PersisterCreationContext; import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl; import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.entity.EntityTuplizer;
@ -717,6 +723,16 @@ public class PersisterClassProviderTest {
public JavaTypeDescriptor getMappedJavaTypeDescriptor() { public JavaTypeDescriptor getMappedJavaTypeDescriptor() {
return null; return null;
} }
@Override
public void applyTableReferences(
SqlAliasBase sqlAliasBase,
JoinType baseJoinType,
TableReferenceCollector collector,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
throw new NotYetImplementedFor6Exception( getClass() );
}
} }
public static class GoofyException extends RuntimeException { public static class GoofyException extends RuntimeException {

View File

@ -6,13 +6,16 @@
*/ */
package org.hibernate.orm.test.metamodel.mapping; package org.hibernate.orm.test.metamodel.mapping;
import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import javax.persistence.AttributeConverter; import javax.persistence.AttributeConverter;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Convert;
import javax.persistence.ElementCollection; import javax.persistence.ElementCollection;
import javax.persistence.Embeddable; import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EnumType; import javax.persistence.EnumType;
import javax.persistence.Enumerated; import javax.persistence.Enumerated;
@ -21,14 +24,20 @@ import javax.persistence.OneToMany;
import javax.persistence.OrderColumn; import javax.persistence.OrderColumn;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.DomainMetamodel;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry; import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory; 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.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -36,6 +45,7 @@ import org.junit.jupiter.api.Test;
annotatedClasses = { annotatedClasses = {
PluralAttributeTests.SimpleEntity.class, PluralAttributeTests.SimpleEntity.class,
PluralAttributeTests.EntityContainingLists.class, PluralAttributeTests.EntityContainingLists.class,
PluralAttributeTests.EntityContainingSets.class,
PluralAttributeTests.Component.class PluralAttributeTests.Component.class
} }
) )
@ -46,51 +56,50 @@ public class PluralAttributeTests {
@Test @Test
public void testLists(SessionFactoryScope scope) { public void testLists(SessionFactoryScope scope) {
System.out.println( "test" ); final DomainMetamodel domainModel = scope.getSessionFactory().getDomainModel();
final EntityMappingType containerEntityDescriptor = domainModel.getEntityDescriptor( EntityContainingLists.class );
assertThat( containerEntityDescriptor.getNumberOfAttributeMappings(), is( 6 ) );
final AttributeMapping listOfBasics = containerEntityDescriptor.findAttributeMapping( "listOfBasics" );
assertThat( listOfBasics, notNullValue() );
final AttributeMapping listOfConvertedBasics = containerEntityDescriptor.findAttributeMapping( "listOfConvertedBasics" );
assertThat( listOfConvertedBasics, notNullValue() );
final AttributeMapping listOfEnums = containerEntityDescriptor.findAttributeMapping( "listOfEnums" );
assertThat( listOfEnums, notNullValue() );
final AttributeMapping listOfComponents = containerEntityDescriptor.findAttributeMapping( "listOfComponents" );
assertThat( listOfComponents, notNullValue() );
final AttributeMapping listOfEntities = containerEntityDescriptor.findAttributeMapping( "listOfEntities" );
assertThat( listOfEntities, notNullValue() );
} }
@BeforeAll @Test
public void createTestData(SessionFactoryScope scope) { public void testSets(SessionFactoryScope scope) {
scope.inTransaction( final DomainMetamodel domainModel = scope.getSessionFactory().getDomainModel();
session -> { final EntityMappingType containerEntityDescriptor = domainModel.getEntityDescriptor( EntityContainingSets.class );
final EntityContainingLists entityContainingLists = new EntityContainingLists( 1, "first" );
entityContainingLists.addBasic( "abc" ); assertThat( containerEntityDescriptor.getNumberOfAttributeMappings(), is( 6 ) );
entityContainingLists.addBasic( "def" );
entityContainingLists.addBasic( "ghi" );
entityContainingLists.addConvertedBasic( EnumValue.TWO ); final AttributeMapping setOfBasics = containerEntityDescriptor.findAttributeMapping( "setOfBasics" );
assertThat( setOfBasics, notNullValue() );
entityContainingLists.addEnum( EnumValue.ONE ); final AttributeMapping setOfConvertedBasics = containerEntityDescriptor.findAttributeMapping( "setOfConvertedBasics" );
entityContainingLists.addEnum( EnumValue.THREE ); assertThat( setOfConvertedBasics, notNullValue() );
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" ) ); final AttributeMapping setOfEnums = containerEntityDescriptor.findAttributeMapping( "setOfEnums" );
entityContainingLists.addSimpleEntity( new SimpleEntity( 2, "simple-2" ) ); assertThat( setOfEnums, notNullValue() );
session.save( entityContainingLists ); final AttributeMapping setOfComponents = containerEntityDescriptor.findAttributeMapping( "setOfComponents" );
} assertThat( setOfComponents, notNullValue() );
);
}
@AfterAll final AttributeMapping setOfEntities = containerEntityDescriptor.findAttributeMapping( "setOfEntities" );
public void deleteTestData(SessionFactoryScope scope) { assertThat( setOfEntities, notNullValue() );
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 { public enum EnumValue {
@ -198,6 +207,7 @@ public class PluralAttributeTests {
@ElementCollection @ElementCollection
@OrderColumn @OrderColumn
@Convert( converter = Converter.class )
public List<EnumValue> getListOfConvertedBasics() { public List<EnumValue> getListOfConvertedBasics() {
return listOfConvertedBasics; return listOfConvertedBasics;
} }
@ -266,6 +276,127 @@ public class PluralAttributeTests {
} }
} }
@Entity( name = "EntityContainingSets" )
@Table( name = "entity_containing_sets" )
public static class EntityContainingSets {
private Integer id;
private String name;
private Set<String> setOfBasics;
private Set<EnumValue> setOfConvertedBasics;
private Set<EnumValue> setOfEnums;
private Set<Component> setOfComponents;
private Set<SimpleEntity> setOfEntities;
public EntityContainingSets() {
}
public EntityContainingSets(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
public Set<String> getSetOfBasics() {
return setOfBasics;
}
public void setSetOfBasics(Set<String> setOfBasics) {
this.setOfBasics = setOfBasics;
}
public void addBasic(String value) {
if ( setOfBasics == null ) {
setOfBasics = new HashSet<>();
}
setOfBasics.add( value );
}
@ElementCollection
@Convert( converter = Converter.class )
public Set<EnumValue> getSetOfConvertedBasics() {
return setOfConvertedBasics;
}
public void setSetOfConvertedBasics(Set<EnumValue> setOfConvertedBasics) {
this.setOfConvertedBasics = setOfConvertedBasics;
}
public void addConvertedBasic(EnumValue value) {
if ( setOfConvertedBasics == null ) {
setOfConvertedBasics = new HashSet<>();
}
setOfConvertedBasics.add( value );
}
@ElementCollection
@Enumerated( EnumType.STRING )
public Set<EnumValue> getSetOfEnums() {
return setOfEnums;
}
public void setSetOfEnums(Set<EnumValue> setOfEnums) {
this.setOfEnums = setOfEnums;
}
public void addEnum(EnumValue value) {
if ( setOfEnums == null ) {
setOfEnums = new HashSet<>();
}
setOfEnums.add( value );
}
@ElementCollection
@Embedded
public Set<Component> getSetOfComponents() {
return setOfComponents;
}
public void setSetOfComponents(Set<Component> setOfComponents) {
this.setOfComponents = setOfComponents;
}
public void addComponent(Component value) {
if ( setOfComponents == null ) {
setOfComponents = new HashSet<>();
}
setOfComponents.add( value );
}
@OneToMany( cascade = CascadeType.ALL )
public Set<SimpleEntity> getSetOfEntities() {
return setOfEntities;
}
public void setSetOfEntities(Set<SimpleEntity> setOfEntities) {
this.setOfEntities = setOfEntities;
}
public void addSimpleEntity(SimpleEntity value) {
if ( setOfEntities == null ) {
setOfEntities = new HashSet<>();
}
setOfEntities.add( value );
}
}
@Entity( name = "SimpleEntity" ) @Entity( name = "SimpleEntity" )
@Table( name = "simple_entity" ) @Table( name = "simple_entity" )
public static class SimpleEntity { public static class SimpleEntity {

View File

@ -24,7 +24,10 @@ import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping; import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
import org.hibernate.metamodel.model.convert.internal.NamedEnumValueConverter; import org.hibernate.metamodel.model.convert.internal.NamedEnumValueConverter;
import org.hibernate.metamodel.model.convert.internal.OrdinalEnumValueConverter; import org.hibernate.metamodel.model.convert.internal.OrdinalEnumValueConverter;
import org.hibernate.metamodel.model.convert.spi.EnumValueConverter;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.CustomType;
import org.hibernate.usertype.UserType;
import org.hibernate.testing.hamcrest.CollectionMatchers; import org.hibernate.testing.hamcrest.CollectionMatchers;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
@ -72,8 +75,12 @@ public class SmokeTests {
final BasicValuedSingularAttributeMapping genderAttrMapping = (BasicValuedSingularAttributeMapping) genderPart; final BasicValuedSingularAttributeMapping genderAttrMapping = (BasicValuedSingularAttributeMapping) genderPart;
assert "mapping_simple_entity".equals( genderAttrMapping.getContainingTableExpression() ); assert "mapping_simple_entity".equals( genderAttrMapping.getContainingTableExpression() );
assert "gender".equals( genderAttrMapping.getMappedColumnExpression() ); assert "gender".equals( genderAttrMapping.getMappedColumnExpression() );
assert genderAttrMapping.getConverter() != null; assert genderAttrMapping.getMappedTypeDescriptor() instanceof CustomType;
assert genderAttrMapping.getConverter() instanceof OrdinalEnumValueConverter; final UserType userType = ( (CustomType) genderAttrMapping.getMappedTypeDescriptor() ).getUserType();
assert userType instanceof org.hibernate.type.EnumType;
final EnumValueConverter converter = ( (org.hibernate.type.EnumType) userType ).getEnumValueConverter();
assert converter != null;
assert converter instanceof OrdinalEnumValueConverter;
} }
{ {
@ -82,8 +89,13 @@ public class SmokeTests {
final BasicValuedSingularAttributeMapping attrMapping = (BasicValuedSingularAttributeMapping) part; final BasicValuedSingularAttributeMapping attrMapping = (BasicValuedSingularAttributeMapping) part;
assert "mapping_simple_entity".equals( attrMapping.getContainingTableExpression() ); assert "mapping_simple_entity".equals( attrMapping.getContainingTableExpression() );
assert "gender2".equals( attrMapping.getMappedColumnExpression() ); assert "gender2".equals( attrMapping.getMappedColumnExpression() );
assert attrMapping.getConverter() != null;
assert attrMapping.getConverter() instanceof NamedEnumValueConverter; assert attrMapping.getMappedTypeDescriptor() instanceof CustomType;
final UserType userType = ( (CustomType) attrMapping.getMappedTypeDescriptor() ).getUserType();
assert userType instanceof org.hibernate.type.EnumType;
final EnumValueConverter converter = ( (org.hibernate.type.EnumType) userType ).getEnumValueConverter();
assert converter != null;
assert converter instanceof NamedEnumValueConverter;
} }
{ {

View File

@ -35,7 +35,10 @@ import org.hibernate.sql.results.internal.domain.basic.BasicResult;
import org.hibernate.sql.results.internal.SqlSelectionImpl; import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.spi.DomainResult; import org.hibernate.sql.results.spi.DomainResult;
import org.hibernate.sql.results.spi.DomainResultAssembler; import org.hibernate.sql.results.spi.DomainResultAssembler;
import org.hibernate.type.CustomType;
import org.hibernate.type.EnumType;
import org.hibernate.type.internal.StandardBasicTypeImpl; import org.hibernate.type.internal.StandardBasicTypeImpl;
import org.hibernate.usertype.UserType;
import org.hibernate.testing.hamcrest.AssignableMatcher; import org.hibernate.testing.hamcrest.AssignableMatcher;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
@ -49,6 +52,7 @@ import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
/** /**
@ -174,10 +178,15 @@ public class SmokeTests {
assertThat( columnReference.renderSqlFragment( scope.getSessionFactory() ), is( "s1_0.gender" ) ); assertThat( columnReference.renderSqlFragment( scope.getSessionFactory() ), is( "s1_0.gender" ) );
final MappingModelExpressable selectedExpressable = selectedExpression.getExpressionType(); final MappingModelExpressable selectedExpressable = selectedExpression.getExpressionType();
assertThat( selectedExpressable, instanceOf( StandardBasicTypeImpl.class ) ); //assertThat( selectedExpressable, instanceOf( StandardBasicTypeImpl.class ) );
final StandardBasicTypeImpl basicType = (StandardBasicTypeImpl) selectedExpressable; // assertThat( basicType.getJavaTypeDescriptor().getJavaType(), AssignableMatcher.assignableTo( Integer.class ) );
assertThat( basicType.getJavaTypeDescriptor().getJavaType(), AssignableMatcher.assignableTo( Integer.class ) ); // assertThat( basicType.getSqlTypeDescriptor().getSqlType(), is( Types.INTEGER ) );
assertThat( basicType.getSqlTypeDescriptor().getSqlType(), is( Types.INTEGER ) ); assertThat( selectedExpressable, instanceOf( CustomType.class ) );
final CustomType basicType = (CustomType) selectedExpressable;
final EnumType enumType = (EnumType) basicType.getUserType();
assertThat( enumType.getEnumValueConverter().getRelationalJavaDescriptor().getJavaType(), AssignableMatcher.assignableTo( Integer.class ) );
assertThat( enumType.sqlTypes()[0], is( Types.INTEGER ) );
assertThat( sqlAst.getDomainResultDescriptors().size(), is( 1 ) ); assertThat( sqlAst.getDomainResultDescriptors().size(), is( 1 ) );
final DomainResult domainResult = sqlAst.getDomainResultDescriptors().get( 0 ); final DomainResult domainResult = sqlAst.getDomainResultDescriptors().get( 0 );
@ -185,8 +194,10 @@ public class SmokeTests {
final BasicResult scalarDomainResult = (BasicResult) domainResult; final BasicResult scalarDomainResult = (BasicResult) domainResult;
assertThat( scalarDomainResult.getAssembler(), instanceOf( BasicResultAssembler.class ) ); assertThat( scalarDomainResult.getAssembler(), instanceOf( BasicResultAssembler.class ) );
final BasicResultAssembler<?> assembler = (BasicResultAssembler) scalarDomainResult.getAssembler(); final BasicResultAssembler<?> assembler = (BasicResultAssembler) scalarDomainResult.getAssembler();
assertThat( assembler.getValueConverter(), notNullValue() ); // assertThat( assembler.getValueConverter(), notNullValue() );
assertThat( assembler.getValueConverter(), instanceOf( OrdinalEnumValueConverter.class ) ); // assertThat( assembler.getValueConverter(), instanceOf( OrdinalEnumValueConverter.class ) );
assertThat( assembler.getValueConverter(), nullValue() );
final NavigablePath expectedSelectedPath = new NavigablePath( final NavigablePath expectedSelectedPath = new NavigablePath(
org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity.class.getName(), org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity.class.getName(),
"e" "e"
@ -202,9 +213,10 @@ public class SmokeTests {
); );
assertThat( resultAssembler, instanceOf( BasicResultAssembler.class ) ); assertThat( resultAssembler, instanceOf( BasicResultAssembler.class ) );
final BasicValueConverter valueConverter = ( (BasicResultAssembler) resultAssembler ).getValueConverter(); // final BasicValueConverter valueConverter = ( (BasicResultAssembler) resultAssembler ).getValueConverter();
assertThat( valueConverter, notNullValue() ); // assertThat( valueConverter, notNullValue() );
assertThat( valueConverter, instanceOf( OrdinalEnumValueConverter.class ) ); // assertThat( valueConverter, instanceOf( OrdinalEnumValueConverter.class ) );
assertThat( ( (BasicResultAssembler) resultAssembler ).getValueConverter(), nullValue() );
final JdbcSelect jdbcSelectOperation = new StandardSqlAstSelectTranslator( session.getSessionFactory() ) final JdbcSelect jdbcSelectOperation = new StandardSqlAstSelectTranslator( session.getSessionFactory() )
.interpret( sqlAst ); .interpret( sqlAst );

View File

@ -0,0 +1,196 @@
/*
* 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.sql.exec;
import java.sql.Statement;
import org.hibernate.Hibernate;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.orm.test.metamodel.mapping.PluralAttributeTests.Component;
import org.hibernate.orm.test.metamodel.mapping.PluralAttributeTests.EntityContainingLists;
import org.hibernate.orm.test.metamodel.mapping.PluralAttributeTests.EntityContainingSets;
import org.hibernate.orm.test.metamodel.mapping.PluralAttributeTests.EnumValue;
import org.hibernate.orm.test.metamodel.mapping.PluralAttributeTests.SimpleEntity;
import org.hibernate.query.spi.QueryImplementor;
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;
import org.hamcrest.CoreMatchers;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Steve Ebersole
*/
@DomainModel(
annotatedClasses = {
SimpleEntity.class,
EntityContainingLists.class,
EntityContainingSets.class,
Component.class
}
)
@ServiceRegistry
@SessionFactory
@SuppressWarnings("WeakerAccess")
public class PluralAttributeSmokeTests {
@Test
public void listBaselineTest(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final QueryImplementor<EntityContainingLists> query = session.createQuery(
"select e from EntityContainingLists e",
EntityContainingLists.class
);
final EntityContainingLists result = query.uniqueResult();
assertThat( result, notNullValue() );
assertThat( result.getListOfBasics(), notNullValue() );
assertThat( Hibernate.isInitialized( result.getListOfBasics() ), is( false ) );
}
);
}
@Test
public void listEagerBasicTest(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final QueryImplementor<EntityContainingLists> query = session.createQuery(
"select e from EntityContainingLists e join fetch e.listOfBasics",
EntityContainingLists.class
);
final EntityContainingLists result = query.uniqueResult();
assertThat( result, notNullValue() );
assertThat( result.getListOfBasics(), notNullValue() );
assertThat( Hibernate.isInitialized( result.getListOfBasics() ), is( true ) );
assertTrue( session.getPersistenceContext().containsCollection( (PersistentCollection) result.getListOfBasics() ) );
assertThat( result.getListOfBasics().size(), is( 3 ) );
assertThat( result.getListOfConvertedBasics(), notNullValue() );
assertThat( Hibernate.isInitialized( result.getListOfConvertedBasics() ), is( false ) );
assertTrue( session.getPersistenceContext().containsCollection( (PersistentCollection) result.getListOfConvertedBasics() ) );
assertThat( result.getListOfEnums(), notNullValue() );
assertThat( Hibernate.isInitialized( result.getListOfEnums() ), is( false ) );
assertTrue( session.getPersistenceContext().containsCollection( (PersistentCollection) result.getListOfEnums() ) );
assertThat( result.getListOfComponents(), notNullValue() );
assertThat( Hibernate.isInitialized( result.getListOfComponents() ), is( false ) );
assertTrue( session.getPersistenceContext().containsCollection( (PersistentCollection) result.getListOfComponents() ) );
assertThat( result.getListOfEntities(), notNullValue() );
assertThat( Hibernate.isInitialized( result.getListOfEntities() ), is( false ) );
assertTrue( session.getPersistenceContext().containsCollection( (PersistentCollection) result.getListOfEntities() ) );
}
);
}
@Test
public void setBaselineTest(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final QueryImplementor<EntityContainingSets> query = session.createQuery(
"select e from EntityContainingSets e",
EntityContainingSets.class
);
final EntityContainingSets result = query.uniqueResult();
assertThat( result, notNullValue() );
assertThat( result.getSetOfBasics(), notNullValue() );
assertThat( Hibernate.isInitialized( result.getSetOfBasics() ), is( false ) );
}
);
}
@BeforeAll
public void createTestData(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final SimpleEntity simpleEntity1 = new SimpleEntity( 1, "simple-1" );
final SimpleEntity simpleEntity2 = new SimpleEntity( 2, "simple-2" );
session.save( simpleEntity1 );
session.save( simpleEntity2 );
{
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( simpleEntity1 );
entityContainingLists.addSimpleEntity( simpleEntity2 );
session.save( entityContainingLists );
}
{
final EntityContainingSets entity = new EntityContainingSets( 1, "first" );
entity.addBasic( "abc" );
entity.addBasic( "def" );
entity.addBasic( "ghi" );
entity.addConvertedBasic( EnumValue.TWO );
entity.addEnum( EnumValue.ONE );
entity.addEnum( EnumValue.THREE );
entity.addComponent( new Component( "first-a1", "first-another-a1" ) );
entity.addComponent( new Component( "first-a2", "first-another-a2" ) );
entity.addSimpleEntity( simpleEntity1 );
entity.addSimpleEntity( simpleEntity2 );
session.save( entity );
}
}
);
}
@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" );
}
}
)
);
}
}

View File

@ -12,7 +12,6 @@ import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;

View File

@ -20,6 +20,7 @@ import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata; import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cache.spi.access.CollectionDataAccess; import org.hibernate.cache.spi.access.CollectionDataAccess;
import org.hibernate.cache.spi.access.EntityDataAccess; import org.hibernate.cache.spi.access.EntityDataAccess;
@ -58,6 +59,11 @@ import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CollectionElementDefinition; import org.hibernate.persister.walking.spi.CollectionElementDefinition;
import org.hibernate.persister.walking.spi.CollectionIndexDefinition; import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl; import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.entity.EntityTuplizer;
@ -703,6 +709,16 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
public JavaTypeDescriptor getMappedJavaTypeDescriptor() { public JavaTypeDescriptor getMappedJavaTypeDescriptor() {
return null; return null;
} }
@Override
public void applyTableReferences(
SqlAliasBase sqlAliasBase,
JoinType baseJoinType,
TableReferenceCollector collector,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
throw new NotYetImplementedFor6Exception( getClass() );
}
} }
public static class NoopCollectionPersister implements CollectionPersister { public static class NoopCollectionPersister implements CollectionPersister {

View File

@ -21,6 +21,7 @@ import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata; import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cache.spi.access.EntityDataAccess; import org.hibernate.cache.spi.access.EntityDataAccess;
import org.hibernate.cache.spi.access.NaturalIdDataAccess; import org.hibernate.cache.spi.access.NaturalIdDataAccess;
@ -59,6 +60,11 @@ import org.hibernate.persister.entity.MultiLoadOptions;
import org.hibernate.persister.spi.PersisterCreationContext; import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.persister.walking.spi.AttributeDefinition; import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition; import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
import org.hibernate.sql.ast.JoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.tree.from.TableReferenceCollector;
import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl; import org.hibernate.tuple.entity.BytecodeEnhancementMetadataNonPojoImpl;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer; import org.hibernate.tuple.entity.EntityTuplizer;
@ -815,4 +821,14 @@ public class CustomPersister implements EntityPersister {
public JavaTypeDescriptor getMappedJavaTypeDescriptor() { public JavaTypeDescriptor getMappedJavaTypeDescriptor() {
return null; return null;
} }
@Override
public void applyTableReferences(
SqlAliasBase sqlAliasBase,
JoinType baseJoinType,
TableReferenceCollector collector,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
throw new NotYetImplementedFor6Exception( getClass() );
}
} }