preliminary support for collections - lists and sets tested (excluding entity-valued elements and map-key)
This commit is contained in:
parent
093f410953
commit
c89ee3761a
|
@ -36,7 +36,8 @@ public class EnumeratedValueResolution<E extends Enum<E>> implements BasicValue.
|
|||
this.domainJtd = domainJtd;
|
||||
this.jdbcJtd = jdbcJtd;
|
||||
this.std = std;
|
||||
this.valueConverter = valueConverter;
|
||||
// this.valueConverter = valueConverter;
|
||||
this.valueConverter = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
|||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cfg.MetadataSourceType;
|
||||
import org.hibernate.collection.internal.StandardCollectionSemanticsResolver;
|
||||
import org.hibernate.collection.spi.CollectionSemanticsResolver;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.metamodel.internal.StandardManagedTypeRepresentationResolver;
|
||||
|
@ -61,7 +62,8 @@ public interface MetadataBuildingOptions {
|
|||
}
|
||||
|
||||
default CollectionSemanticsResolver getPersistentCollectionRepresentationResolver() {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
// for now always return the standard one
|
||||
return StandardCollectionSemanticsResolver.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,8 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.loader.CollectionAliases;
|
||||
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.jboss.logging.Logger;
|
||||
|
@ -190,6 +192,31 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
|
|||
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
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator entries(CollectionPersister persister) {
|
||||
|
|
|
@ -22,6 +22,8 @@ import org.hibernate.engine.spi.SessionImplementor;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.loader.CollectionAliases;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -133,6 +135,24 @@ public class PersistentBag extends AbstractPersistentCollection implements List
|
|||
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
|
||||
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
|
||||
this.bag = (List) persister.getCollectionType().instantiate( anticipatedSize );
|
||||
|
|
|
@ -22,6 +22,8 @@ import org.hibernate.engine.spi.SessionImplementor;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.loader.CollectionAliases;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -372,6 +374,30 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
|
|||
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
|
||||
@SuppressWarnings("unchecked")
|
||||
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
|
|
|
@ -20,6 +20,8 @@ import org.hibernate.engine.spi.SessionImplementor;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.loader.CollectionAliases;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -206,9 +208,9 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean containsAll(Collection coll) {
|
||||
read();
|
||||
//noinspection unchecked
|
||||
return list.containsAll( coll );
|
||||
}
|
||||
|
||||
|
@ -262,9 +264,9 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean retainAll(Collection coll) {
|
||||
initialize( true );
|
||||
//noinspection unchecked
|
||||
if ( list.retainAll( coll ) ) {
|
||||
dirty();
|
||||
return true;
|
||||
|
@ -275,7 +277,6 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void clear() {
|
||||
if ( isClearQueueEnabled() ) {
|
||||
queueOperation( new Clear() );
|
||||
|
@ -290,7 +291,6 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object get(int index) {
|
||||
if ( index < 0 ) {
|
||||
throw new ArrayIndexOutOfBoundsException( "negative index" );
|
||||
|
@ -300,7 +300,6 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object set(int index, Object value) {
|
||||
if (index<0) {
|
||||
throw new ArrayIndexOutOfBoundsException("negative index");
|
||||
|
@ -310,6 +309,7 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
|
||||
if ( old==UNKNOWN ) {
|
||||
write();
|
||||
//noinspection unchecked
|
||||
return list.set( index, value );
|
||||
}
|
||||
else {
|
||||
|
@ -319,7 +319,6 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object remove(int index) {
|
||||
if ( index < 0 ) {
|
||||
throw new ArrayIndexOutOfBoundsException( "negative index" );
|
||||
|
@ -338,45 +337,40 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void add(int index, Object value) {
|
||||
if ( index < 0 ) {
|
||||
throw new ArrayIndexOutOfBoundsException( "negative index" );
|
||||
}
|
||||
write();
|
||||
//noinspection unchecked
|
||||
list.add( index, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int indexOf(Object value) {
|
||||
read();
|
||||
return list.indexOf( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int lastIndexOf(Object value) {
|
||||
read();
|
||||
return list.lastIndexOf( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ListIterator listIterator() {
|
||||
read();
|
||||
return new ListIteratorProxy( list.listIterator() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ListIterator listIterator(int index) {
|
||||
read();
|
||||
return new ListIteratorProxy( list.listIterator( index ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public java.util.List subList(int from, int to) {
|
||||
read();
|
||||
return new ListProxy( list.subList( from, to ) );
|
||||
|
@ -409,6 +403,32 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
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
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator entries(CollectionPersister persister) {
|
||||
|
|
|
@ -22,6 +22,8 @@ import org.hibernate.engine.spi.SessionImplementor;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.loader.CollectionAliases;
|
||||
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;
|
||||
|
||||
|
||||
|
@ -176,7 +178,6 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object put(Object key, Object value) {
|
||||
if ( isPutQueueEnabled() ) {
|
||||
final Object old = readElementByIndex( key );
|
||||
|
@ -186,6 +187,7 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
}
|
||||
}
|
||||
initialize( true );
|
||||
//noinspection unchecked
|
||||
final Object old = map.put( key, value );
|
||||
// would be better to use the element-type to determine
|
||||
// whether the old and the new are equal here; the problem being
|
||||
|
@ -198,7 +200,6 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object remove(Object key) {
|
||||
if ( isPutQueueEnabled() ) {
|
||||
final Object old = readElementByIndex( key );
|
||||
|
@ -218,7 +219,6 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void putAll(Map puts) {
|
||||
if ( puts.size() > 0 ) {
|
||||
initialize( true );
|
||||
|
@ -230,7 +230,6 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void clear() {
|
||||
if ( isClearQueueEnabled() ) {
|
||||
queueOperation( new Clear() );
|
||||
|
@ -245,34 +244,29 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set keySet() {
|
||||
read();
|
||||
return new SetProxy( map.keySet() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection values() {
|
||||
read();
|
||||
return new SetProxy( map.values() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set entrySet() {
|
||||
read();
|
||||
return new EntrySetProxy( map.entrySet() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean empty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public String toString() {
|
||||
read();
|
||||
return map.toString();
|
||||
|
@ -281,7 +275,6 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
private transient List<Object[]> loadingEntries;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object readFrom(
|
||||
ResultSet rs,
|
||||
CollectionPersister persister,
|
||||
|
@ -298,6 +291,30 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
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
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean endRead() {
|
||||
|
|
|
@ -21,6 +21,8 @@ import org.hibernate.engine.spi.SessionImplementor;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.loader.CollectionAliases;
|
||||
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;
|
||||
|
||||
|
||||
|
@ -342,6 +344,27 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
|
|||
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
|
||||
@SuppressWarnings("unchecked")
|
||||
public void beginRead() {
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ package org.hibernate.collection.spi;
|
|||
import java.util.Iterator;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.metamodel.CollectionClassification;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
|
@ -22,6 +23,7 @@ import org.hibernate.persister.collection.CollectionPersister;
|
|||
* @author Steve Ebersole
|
||||
* @author Gavin King
|
||||
*/
|
||||
@Incubating
|
||||
public interface CollectionSemantics<C> {
|
||||
/**
|
||||
* Get the classification of collections described by this semantic
|
||||
|
|
|
@ -6,9 +6,12 @@
|
|||
*/
|
||||
package org.hibernate.collection.spi;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.mapping.Collection;
|
||||
|
||||
/**
|
||||
* Resolve the collection semantics for the given mapped collection
|
||||
*
|
||||
* todo (6.0) ...
|
||||
*
|
||||
* Ideally would act as the contract that allows pluggable resolution of
|
||||
|
@ -17,6 +20,7 @@ import org.hibernate.mapping.Collection;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Incubating
|
||||
public interface CollectionSemanticsResolver {
|
||||
// really need some form of access to the attribute site
|
||||
CollectionSemantics resolveRepresentation(Collection bootDescriptor);
|
||||
|
|
|
@ -16,6 +16,8 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.loader.CollectionAliases;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -173,6 +175,13 @@ public interface PersistentCollection {
|
|||
Object readFrom(ResultSet rs, CollectionPersister role, CollectionAliases descriptor, Object owner)
|
||||
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
|
||||
* identifier of the (possibly) entity elements. This is only valid for invocation on the
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -15,5 +15,5 @@ import org.hibernate.collection.spi.CollectionSemantics;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface CollectionMappingType<C> extends MappingType {
|
||||
CollectionSemantics<C> getCCollectionSemantics();
|
||||
CollectionSemantics<C> getCollectionSemantics();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -102,6 +102,7 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
CompositeType compositeType,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
final String containingTableExpression = valueMapping.getContainingTableExpression();
|
||||
|
||||
final List<String> mappedColumnExpressions = valueMapping.getMappedColumnExpressions();
|
||||
|
||||
final Type[] subtypes = compositeType.getSubtypes();
|
||||
|
@ -196,6 +197,11 @@ public class EmbeddableMappingType implements ManagedMappingType {
|
|||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfFetchables() {
|
||||
return attributeMappings.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFetchables(
|
||||
Consumer<Fetchable> fetchableConsumer,
|
||||
|
|
|
@ -14,12 +14,13 @@ import org.hibernate.sql.ast.Clause;
|
|||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
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
|
||||
*/
|
||||
public interface EmbeddableValuedModelPart extends ModelPart, FetchableContainer, TableGroupJoinProducer {
|
||||
public interface EmbeddableValuedModelPart extends ModelPart, Fetchable, FetchableContainer, TableGroupJoinProducer {
|
||||
EmbeddableMappingType getEmbeddableTypeDescriptor();
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -6,15 +6,39 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.mapping;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
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
|
||||
*/
|
||||
public interface PluralAttributeMapping extends AttributeMapping, StateArrayContributorMapping {
|
||||
public interface PluralAttributeMapping
|
||||
extends AttributeMapping, StateArrayContributorMapping, TableGroupJoinProducer, FetchableContainer {
|
||||
|
||||
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() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,14 +13,17 @@ import org.hibernate.LockMode;
|
|||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.results.SqlResultsLogger;
|
||||
import org.hibernate.sql.results.internal.domain.basic.BasicFetch;
|
||||
import org.hibernate.sql.results.internal.domain.basic.BasicResult;
|
||||
import org.hibernate.sql.results.spi.DomainResult;
|
||||
|
@ -36,13 +39,24 @@ import org.hibernate.type.spi.TypeConfiguration;
|
|||
*
|
||||
* @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(
|
||||
CollectionPersister collectionDescriptor,
|
||||
Nature nature,
|
||||
BasicType mapper,
|
||||
BasicValueConverter valueConverter,
|
||||
String tableExpression,
|
||||
String columnExpression) {
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
this.nature = nature;
|
||||
this.mapper = mapper;
|
||||
this.valueConverter = valueConverter;
|
||||
|
@ -50,14 +64,15 @@ public class BasicValuedCollectionPart implements BasicValuedModelPart {
|
|||
this.columnExpression = columnExpression;
|
||||
}
|
||||
|
||||
enum Nature { ELEMENT, INDEX }
|
||||
@Override
|
||||
public Nature getNature() {
|
||||
return nature;
|
||||
}
|
||||
|
||||
private final Nature nature;
|
||||
private final BasicType mapper;
|
||||
private final BasicValueConverter valueConverter;
|
||||
|
||||
private final String tableExpression;
|
||||
private final String columnExpression;
|
||||
@Override
|
||||
public BasicType getPartTypeDescriptor() {
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContainingTableExpression() {
|
||||
|
@ -91,7 +106,9 @@ public class BasicValuedCollectionPart implements BasicValuedModelPart {
|
|||
return new BasicResult(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
resultVariable,
|
||||
getJavaTypeDescriptor()
|
||||
getJavaTypeDescriptor(),
|
||||
valueConverter,
|
||||
navigablePath
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -100,9 +117,9 @@ public class BasicValuedCollectionPart implements BasicValuedModelPart {
|
|||
|
||||
return exprResolver.resolveSqlSelection(
|
||||
exprResolver.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey( tableExpression, columnExpression ),
|
||||
SqlExpressionResolver.createColumnReferenceKey( tableGroup.getPrimaryTableReference(), columnExpression ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
tableGroup.resolveTableReference( tableExpression ).getIdentificationVariable(),
|
||||
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
|
||||
columnExpression,
|
||||
mapper,
|
||||
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
|
||||
|
@ -148,6 +165,12 @@ public class BasicValuedCollectionPart implements BasicValuedModelPart {
|
|||
LockMode lockMode,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
SqlResultsLogger.INSTANCE.debugf(
|
||||
"Generating Fetch for collection-part : `%s` -> `%s`",
|
||||
collectionDescriptor.getRole(),
|
||||
nature.getName()
|
||||
);
|
||||
|
||||
final SqlSelection sqlSelection = resolveSqlSelection(
|
||||
creationState.getSqlAstCreationState().getFromClauseAccess().findTableGroup( fetchablePath.getParent() ),
|
||||
creationState
|
||||
|
|
|
@ -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() + ")";
|
||||
}
|
||||
}
|
|
@ -31,6 +31,7 @@ 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.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.TableGroup;
|
||||
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.TableReferenceCollector;
|
||||
import org.hibernate.sql.results.internal.domain.composite.CompositeFetch;
|
||||
import org.hibernate.sql.results.internal.domain.composite.CompositeResult;
|
||||
import org.hibernate.sql.results.spi.DomainResult;
|
||||
|
@ -162,6 +165,7 @@ public class EmbeddedAttributeMapping
|
|||
this,
|
||||
fetchParent,
|
||||
fetchTiming,
|
||||
getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
|
||||
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
|
||||
public String getSqlAliasStem() {
|
||||
return getAttributeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfFetchables() {
|
||||
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -7,6 +7,10 @@
|
|||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
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 org.hibernate.LockMode;
|
||||
|
@ -16,36 +20,35 @@ import org.hibernate.collection.internal.StandardArraySemantics;
|
|||
import org.hibernate.collection.internal.StandardBagSemantics;
|
||||
import org.hibernate.collection.internal.StandardIdentifierBagSemantics;
|
||||
import org.hibernate.collection.internal.StandardListSemantics;
|
||||
import org.hibernate.collection.internal.StandardMapSemantics;
|
||||
import org.hibernate.collection.internal.StandardOrderedMapSemantics;
|
||||
import org.hibernate.collection.internal.StandardOrderedSetSemantics;
|
||||
import org.hibernate.collection.internal.StandardSetSemantics;
|
||||
import org.hibernate.collection.internal.StandardSortedMapSemantics;
|
||||
import org.hibernate.collection.internal.StandardSortedSetSemantics;
|
||||
import org.hibernate.collection.spi.CollectionSemantics;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.mapping.Array;
|
||||
import org.hibernate.mapping.Bag;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.IdentifierBag;
|
||||
import org.hibernate.mapping.List;
|
||||
import org.hibernate.mapping.Map;
|
||||
import org.hibernate.mapping.IndexedCollection;
|
||||
import org.hibernate.mapping.OneToMany;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.PrimitiveArray;
|
||||
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.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
|
||||
import org.hibernate.metamodel.mapping.CollectionMappingType;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
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.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.spi.DomainMetamodel;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.collection.SQLLoadableCollection;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.persister.walking.internal.FetchStrategyHelper;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
||||
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.tree.expression.ColumnReference;
|
||||
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.type.BasicType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.MutabilityPlan;
|
||||
|
@ -622,75 +630,152 @@ public class MappingModelCreationHelper {
|
|||
final Collection bootValueMapping = (Collection) bootProperty.getValue();
|
||||
|
||||
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;
|
||||
|
||||
tableExpression = ( (Joinable) collectionDescriptor ).getTableName();
|
||||
|
||||
final String sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( bootProperty.getName() );
|
||||
|
||||
final CollectionMappingType<?> collectionMappingType;
|
||||
final JavaTypeDescriptorRegistry jtdRegistry = creationContext.getJavaTypeDescriptorRegistry();
|
||||
|
||||
if ( bootValueMapping instanceof Array ) {
|
||||
if ( bootValueMapping instanceof PrimitiveArray ) {
|
||||
throw new NotYetImplementedFor6Exception();
|
||||
}
|
||||
else {
|
||||
final ForeignKeyDescriptor keyDescriptor = interpretKeyDescriptor(
|
||||
bootProperty,
|
||||
bootValueMapping,
|
||||
dialect,
|
||||
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(
|
||||
jtdRegistry.getDescriptor( Object[].class ),
|
||||
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;
|
||||
}
|
||||
}
|
||||
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() ) {
|
||||
case BAG: {
|
||||
collectionMappingType = new CollectionMappingTypeImpl(
|
||||
jtdRegistry.getDescriptor( java.util.SortedMap.class ),
|
||||
StandardSortedMapSemantics.INSTANCE
|
||||
jtdRegistry.getDescriptor( java.util.Collection.class ),
|
||||
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() {
|
||||
|
@ -733,7 +818,7 @@ public class MappingModelCreationHelper {
|
|||
final FetchStyle style = FetchStrategyHelper.determineFetchStyleByMetadata(
|
||||
( (OuterJoinLoadable) declaringType ).getFetchMode( stateArrayPosition ),
|
||||
collectionDescriptor.getCollectionType(),
|
||||
creationContext.getSessionFactory()
|
||||
sessionFactory
|
||||
);
|
||||
|
||||
return new PluralAttributeMappingImpl(
|
||||
|
@ -742,15 +827,15 @@ public class MappingModelCreationHelper {
|
|||
entityMappingType -> contributorMetadata,
|
||||
collectionMappingType,
|
||||
stateArrayPosition,
|
||||
tableExpression,
|
||||
attrColumnExpressions,
|
||||
null,
|
||||
null,
|
||||
keyDescriptor,
|
||||
elementDescriptor,
|
||||
indexDescriptor,
|
||||
identifierDescriptor,
|
||||
new FetchStrategy(
|
||||
FetchStrategyHelper.determineFetchTiming(
|
||||
style,
|
||||
collectionDescriptor.getCollectionType(),
|
||||
creationContext.getSessionFactory()
|
||||
sessionFactory
|
||||
),
|
||||
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 final JavaTypeDescriptor collectionJtd;
|
||||
private final CollectionSemantics semantics;
|
||||
|
@ -773,7 +1008,7 @@ public class MappingModelCreationHelper {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CollectionSemantics getCCollectionSemantics() {
|
||||
public CollectionSemantics getCollectionSemantics() {
|
||||
return semantics;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,17 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
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.engine.spi.CascadeStyle;
|
||||
import org.hibernate.metamodel.mapping.CollectionIdentifierDescriptor;
|
||||
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.ModelPart;
|
||||
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.query.NavigablePath;
|
||||
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.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.Fetch;
|
||||
import org.hibernate.sql.results.spi.FetchParent;
|
||||
|
@ -33,17 +49,18 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
|||
private final PropertyAccess propertyAccess;
|
||||
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 String tableExpression;
|
||||
private final String[] attrColumnExpressions;
|
||||
|
||||
private final ModelPart elementDescriptor;
|
||||
private final ModelPart indexDescriptor;
|
||||
|
||||
private final CascadeStyle cascadeStyle;
|
||||
|
||||
private final CollectionPersister collectionDescriptor;
|
||||
|
||||
private final String sqlAliasStem;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public PluralAttributeMappingImpl(
|
||||
String attributeName,
|
||||
|
@ -51,10 +68,10 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
|||
StateArrayContributorMetadataAccess stateArrayContributorMetadataAccess,
|
||||
CollectionMappingType collectionMappingType,
|
||||
int stateArrayPosition,
|
||||
String tableExpression,
|
||||
String[] attrColumnExpressions,
|
||||
ModelPart elementDescriptor,
|
||||
ModelPart indexDescriptor,
|
||||
ForeignKeyDescriptor fkDescriptor,
|
||||
CollectionPart elementDescriptor,
|
||||
CollectionPart indexDescriptor,
|
||||
CollectionIdentifierDescriptor identifierDescriptor,
|
||||
FetchStrategy fetchStrategy,
|
||||
CascadeStyle cascadeStyle,
|
||||
ManagedMappingType declaringType,
|
||||
|
@ -63,36 +80,47 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
|||
this.propertyAccess = propertyAccess;
|
||||
this.stateArrayContributorMetadataAccess = stateArrayContributorMetadataAccess;
|
||||
this.stateArrayPosition = stateArrayPosition;
|
||||
this.tableExpression = tableExpression;
|
||||
this.attrColumnExpressions = attrColumnExpressions;
|
||||
this.fkDescriptor = fkDescriptor;
|
||||
this.elementDescriptor = elementDescriptor;
|
||||
this.indexDescriptor = indexDescriptor;
|
||||
this.identifierDescriptor = identifierDescriptor;
|
||||
this.fetchStrategy = fetchStrategy;
|
||||
this.cascadeStyle = cascadeStyle;
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
}
|
||||
|
||||
this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( attributeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionMappingType getMappedTypeDescriptor() {
|
||||
return (CollectionMappingType) super.getMappedTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKeyDescriptor getKeyDescriptor() {
|
||||
return fkDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionPersister getCollectionDescriptor() {
|
||||
return collectionDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPart getValueDescriptor() {
|
||||
public CollectionPart getElementDescriptor() {
|
||||
return elementDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPart getIndexDescriptor() {
|
||||
public CollectionPart getIndexDescriptor() {
|
||||
return indexDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionIdentifierDescriptor getIdentifierDescriptor() {
|
||||
return identifierDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStateArrayPosition() {
|
||||
return stateArrayPosition;
|
||||
|
@ -128,8 +156,119 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
|||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
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() + ")";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -7,12 +7,12 @@
|
|||
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.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess;
|
||||
import org.hibernate.property.access.spi.PropertyAccess;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
|
@ -29,7 +29,7 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
|||
int stateArrayPosition,
|
||||
StateArrayContributorMetadataAccess attributeMetadataAccess,
|
||||
FetchStrategy mappedFetchStrategy,
|
||||
MappingType type,
|
||||
EntityMappingType type,
|
||||
ManagedMappingType declaringType,
|
||||
PropertyAccess propertyAccess) {
|
||||
super(
|
||||
|
@ -43,9 +43,14 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType getMappedTypeDescriptor() {
|
||||
return (EntityMappingType) super.getMappedTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType getEntityMappingType() {
|
||||
return null;
|
||||
return getMappedTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,6 +62,11 @@ public class SingularAssociationAttributeMapping extends AbstractSingularAttribu
|
|||
LockMode lockMode,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
return null;
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfFetchables() {
|
||||
return getEntityMappingType().getNumberOfFetchables();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import java.util.HashMap;
|
|||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
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.StructuredMapCacheEntry;
|
||||
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
|
||||
import org.hibernate.collection.spi.CollectionSemantics;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
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.Expectations;
|
||||
import org.hibernate.loader.collection.CollectionInitializer;
|
||||
import org.hibernate.mapping.BasicValue;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Formula;
|
||||
|
@ -64,9 +65,9 @@ import org.hibernate.mapping.IndexedCollection;
|
|||
import org.hibernate.mapping.List;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.metadata.CollectionMetadata;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
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.EntityDefinition;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.query.sqm.sql.SqlExpressionResolver;
|
||||
import org.hibernate.sql.Alias;
|
||||
import org.hibernate.sql.SelectFragment;
|
||||
import org.hibernate.sql.SimpleSelect;
|
||||
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.AssociationType;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.EntityType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
|
@ -234,10 +240,26 @@ public abstract class AbstractCollectionPersister
|
|||
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(
|
||||
Collection collectionBinding,
|
||||
Collection collectionBootDescriptor,
|
||||
CollectionDataAccess cacheAccessStrategy,
|
||||
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 JdbcEnvironment jdbcEnvironment = database.getJdbcEnvironment();
|
||||
|
@ -245,7 +267,7 @@ public abstract class AbstractCollectionPersister
|
|||
this.factory = creationContext.getSessionFactory();
|
||||
this.cacheAccessStrategy = cacheAccessStrategy;
|
||||
if ( factory.getSessionFactoryOptions().isStructuredCacheEntriesEnabled() ) {
|
||||
cacheEntryStructure = collectionBinding.isMap()
|
||||
cacheEntryStructure = collectionBootDescriptor.isMap()
|
||||
? StructuredMapCacheEntry.INSTANCE
|
||||
: StructuredCollectionCacheEntry.INSTANCE;
|
||||
}
|
||||
|
@ -255,54 +277,54 @@ public abstract class AbstractCollectionPersister
|
|||
|
||||
dialect = factory.getDialect();
|
||||
sqlExceptionHelper = factory.getSQLExceptionHelper();
|
||||
collectionType = collectionBinding.getCollectionType();
|
||||
navigableRole = new NavigableRole( collectionBinding.getRole() );
|
||||
entityName = collectionBinding.getOwnerEntityName();
|
||||
collectionType = collectionBootDescriptor.getCollectionType();
|
||||
navigableRole = new NavigableRole( collectionBootDescriptor.getRole() );
|
||||
entityName = collectionBootDescriptor.getOwnerEntityName();
|
||||
ownerPersister = factory.getEntityPersister( entityName );
|
||||
queryLoaderName = collectionBinding.getLoaderName();
|
||||
isMutable = collectionBinding.isMutable();
|
||||
mappedByProperty = collectionBinding.getMappedByProperty();
|
||||
queryLoaderName = collectionBootDescriptor.getLoaderName();
|
||||
isMutable = collectionBootDescriptor.isMutable();
|
||||
mappedByProperty = collectionBootDescriptor.getMappedByProperty();
|
||||
|
||||
Table table = collectionBinding.getCollectionTable();
|
||||
fetchMode = collectionBinding.getElement().getFetchMode();
|
||||
elementType = collectionBinding.getElement().getType();
|
||||
Table table = collectionBootDescriptor.getCollectionTable();
|
||||
fetchMode = elementBootDescriptor.getFetchMode();
|
||||
elementType = elementBootDescriptor.getType();
|
||||
// isSet = collectionBinding.isSet();
|
||||
// isSorted = collectionBinding.isSorted();
|
||||
isPrimitiveArray = collectionBinding.isPrimitiveArray();
|
||||
isArray = collectionBinding.isArray();
|
||||
subselectLoadable = collectionBinding.isSubselectLoadable();
|
||||
isPrimitiveArray = collectionBootDescriptor.isPrimitiveArray();
|
||||
isArray = collectionBootDescriptor.isArray();
|
||||
subselectLoadable = collectionBootDescriptor.isSubselectLoadable();
|
||||
|
||||
qualifiedTableName = determineTableName( table, jdbcEnvironment );
|
||||
|
||||
int spacesSize = 1 + collectionBinding.getSynchronizedTables().size();
|
||||
int spacesSize = 1 + collectionBootDescriptor.getSynchronizedTables().size();
|
||||
spaces = new String[spacesSize];
|
||||
spaces[0] = qualifiedTableName;
|
||||
Iterator iter = collectionBinding.getSynchronizedTables().iterator();
|
||||
Iterator iter = collectionBootDescriptor.getSynchronizedTables().iterator();
|
||||
for ( int i = 1; i < spacesSize; i++ ) {
|
||||
spaces[i] = (String) iter.next();
|
||||
}
|
||||
|
||||
sqlWhereString = StringHelper.isNotEmpty( collectionBinding.getWhere() ) ? "( " + collectionBinding.getWhere() + ") " : null;
|
||||
sqlWhereString = StringHelper.isNotEmpty( collectionBootDescriptor.getWhere() ) ? "( " + collectionBootDescriptor.getWhere() + ") " : null;
|
||||
hasWhere = sqlWhereString != null;
|
||||
sqlWhereStringTemplate = hasWhere ?
|
||||
Template.renderWhereStringTemplate( sqlWhereString, dialect, factory.getSqlFunctionRegistry() ) :
|
||||
null;
|
||||
|
||||
hasOrphanDelete = collectionBinding.hasOrphanDelete();
|
||||
hasOrphanDelete = collectionBootDescriptor.hasOrphanDelete();
|
||||
|
||||
int batch = collectionBinding.getBatchSize();
|
||||
int batch = collectionBootDescriptor.getBatchSize();
|
||||
if ( batch == -1 ) {
|
||||
batch = factory.getSessionFactoryOptions().getDefaultBatchFetchSize();
|
||||
}
|
||||
batchSize = batch;
|
||||
|
||||
isVersioned = collectionBinding.isOptimisticLocked();
|
||||
isVersioned = collectionBootDescriptor.isOptimisticLocked();
|
||||
|
||||
// KEY
|
||||
|
||||
keyType = collectionBinding.getKey().getType();
|
||||
iter = collectionBinding.getKey().getColumnIterator();
|
||||
int keySpan = collectionBinding.getKey().getColumnSpan();
|
||||
keyType = collectionBootDescriptor.getKey().getType();
|
||||
iter = collectionBootDescriptor.getKey().getColumnIterator();
|
||||
int keySpan = collectionBootDescriptor.getKey().getColumnSpan();
|
||||
keyColumnNames = new String[keySpan];
|
||||
keyColumnAliases = new String[keySpan];
|
||||
int k = 0;
|
||||
|
@ -328,7 +350,7 @@ public abstract class AbstractCollectionPersister
|
|||
elementPersister = null;
|
||||
}
|
||||
|
||||
int elementSpan = collectionBinding.getElement().getColumnSpan();
|
||||
int elementSpan = elementBootDescriptor.getColumnSpan();
|
||||
elementColumnAliases = new String[elementSpan];
|
||||
elementColumnNames = new String[elementSpan];
|
||||
elementColumnWriters = new String[elementSpan];
|
||||
|
@ -341,13 +363,13 @@ public abstract class AbstractCollectionPersister
|
|||
elementColumnIsInPrimaryKey = new boolean[elementSpan];
|
||||
boolean isPureFormula = true;
|
||||
boolean hasNotNullableColumns = false;
|
||||
boolean oneToMany = collectionBinding.isOneToMany();
|
||||
boolean oneToMany = collectionBootDescriptor.isOneToMany();
|
||||
boolean[] columnInsertability = null;
|
||||
if ( !oneToMany ) {
|
||||
columnInsertability = collectionBinding.getElement().getColumnInsertability();
|
||||
columnInsertability = elementBootDescriptor.getColumnInsertability();
|
||||
}
|
||||
int j = 0;
|
||||
iter = collectionBinding.getElement().getColumnIterator();
|
||||
iter = elementBootDescriptor.getColumnIterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Selectable selectable = (Selectable) iter.next();
|
||||
elementColumnAliases[j] = selectable.getAlias( dialect, table );
|
||||
|
@ -390,10 +412,10 @@ public abstract class AbstractCollectionPersister
|
|||
|
||||
// INDEX AND ROW SELECT
|
||||
|
||||
hasIndex = collectionBinding.isIndexed();
|
||||
hasIndex = collectionBootDescriptor.isIndexed();
|
||||
if ( hasIndex ) {
|
||||
// NativeSQL: collect index column and auto-aliases
|
||||
IndexedCollection indexedCollection = (IndexedCollection) collectionBinding;
|
||||
IndexedCollection indexedCollection = (IndexedCollection) collectionBootDescriptor;
|
||||
indexType = indexedCollection.getIndex().getType();
|
||||
int indexSpan = indexedCollection.getIndex().getColumnSpan();
|
||||
boolean[] indexColumnInsertability = indexedCollection.getIndex().getColumnInsertability();
|
||||
|
@ -440,12 +462,12 @@ public abstract class AbstractCollectionPersister
|
|||
baseIndex = 0;
|
||||
}
|
||||
|
||||
hasIdentifier = collectionBinding.isIdentified();
|
||||
hasIdentifier = collectionBootDescriptor.isIdentified();
|
||||
if ( hasIdentifier ) {
|
||||
if ( collectionBinding.isOneToMany() ) {
|
||||
if ( collectionBootDescriptor.isOneToMany() ) {
|
||||
throw new MappingException( "one-to-many collections with identifiers are not supported" );
|
||||
}
|
||||
IdentifierCollection idColl = (IdentifierCollection) collectionBinding;
|
||||
IdentifierCollection idColl = (IdentifierCollection) collectionBootDescriptor;
|
||||
identifierType = idColl.getIdentifier().getType();
|
||||
iter = idColl.getIdentifier().getColumnIterator();
|
||||
Column col = (Column) iter.next();
|
||||
|
@ -473,68 +495,68 @@ public abstract class AbstractCollectionPersister
|
|||
// sqlSelectString = sqlSelectString();
|
||||
// sqlSelectRowString = sqlSelectRowString();
|
||||
|
||||
if ( collectionBinding.getCustomSQLInsert() == null ) {
|
||||
if ( collectionBootDescriptor.getCustomSQLInsert() == null ) {
|
||||
sqlInsertRowString = generateInsertRowString();
|
||||
insertCallable = false;
|
||||
insertCheckStyle = ExecuteUpdateResultCheckStyle.COUNT;
|
||||
}
|
||||
else {
|
||||
sqlInsertRowString = collectionBinding.getCustomSQLInsert();
|
||||
insertCallable = collectionBinding.isCustomInsertCallable();
|
||||
insertCheckStyle = collectionBinding.getCustomSQLInsertCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( collectionBinding.getCustomSQLInsert(), insertCallable )
|
||||
: collectionBinding.getCustomSQLInsertCheckStyle();
|
||||
sqlInsertRowString = collectionBootDescriptor.getCustomSQLInsert();
|
||||
insertCallable = collectionBootDescriptor.isCustomInsertCallable();
|
||||
insertCheckStyle = collectionBootDescriptor.getCustomSQLInsertCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( collectionBootDescriptor.getCustomSQLInsert(), insertCallable )
|
||||
: collectionBootDescriptor.getCustomSQLInsertCheckStyle();
|
||||
}
|
||||
|
||||
if ( collectionBinding.getCustomSQLUpdate() == null ) {
|
||||
if ( collectionBootDescriptor.getCustomSQLUpdate() == null ) {
|
||||
sqlUpdateRowString = generateUpdateRowString();
|
||||
updateCallable = false;
|
||||
updateCheckStyle = ExecuteUpdateResultCheckStyle.COUNT;
|
||||
}
|
||||
else {
|
||||
sqlUpdateRowString = collectionBinding.getCustomSQLUpdate();
|
||||
updateCallable = collectionBinding.isCustomUpdateCallable();
|
||||
updateCheckStyle = collectionBinding.getCustomSQLUpdateCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( collectionBinding.getCustomSQLUpdate(), insertCallable )
|
||||
: collectionBinding.getCustomSQLUpdateCheckStyle();
|
||||
sqlUpdateRowString = collectionBootDescriptor.getCustomSQLUpdate();
|
||||
updateCallable = collectionBootDescriptor.isCustomUpdateCallable();
|
||||
updateCheckStyle = collectionBootDescriptor.getCustomSQLUpdateCheckStyle() == null
|
||||
? ExecuteUpdateResultCheckStyle.determineDefault( collectionBootDescriptor.getCustomSQLUpdate(), insertCallable )
|
||||
: collectionBootDescriptor.getCustomSQLUpdateCheckStyle();
|
||||
}
|
||||
|
||||
if ( collectionBinding.getCustomSQLDelete() == null ) {
|
||||
if ( collectionBootDescriptor.getCustomSQLDelete() == null ) {
|
||||
sqlDeleteRowString = generateDeleteRowString();
|
||||
deleteCallable = false;
|
||||
deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
|
||||
}
|
||||
else {
|
||||
sqlDeleteRowString = collectionBinding.getCustomSQLDelete();
|
||||
deleteCallable = collectionBinding.isCustomDeleteCallable();
|
||||
sqlDeleteRowString = collectionBootDescriptor.getCustomSQLDelete();
|
||||
deleteCallable = collectionBootDescriptor.isCustomDeleteCallable();
|
||||
deleteCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
|
||||
}
|
||||
|
||||
if ( collectionBinding.getCustomSQLDeleteAll() == null ) {
|
||||
if ( collectionBootDescriptor.getCustomSQLDeleteAll() == null ) {
|
||||
sqlDeleteString = generateDeleteString();
|
||||
deleteAllCallable = false;
|
||||
deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
|
||||
}
|
||||
else {
|
||||
sqlDeleteString = collectionBinding.getCustomSQLDeleteAll();
|
||||
deleteAllCallable = collectionBinding.isCustomDeleteAllCallable();
|
||||
sqlDeleteString = collectionBootDescriptor.getCustomSQLDeleteAll();
|
||||
deleteAllCallable = collectionBootDescriptor.isCustomDeleteAllCallable();
|
||||
deleteAllCheckStyle = ExecuteUpdateResultCheckStyle.NONE;
|
||||
}
|
||||
|
||||
sqlSelectSizeString = generateSelectSizeString( collectionBinding.isIndexed() && !collectionBinding.isMap() );
|
||||
sqlSelectSizeString = generateSelectSizeString( collectionBootDescriptor.isIndexed() && !collectionBootDescriptor.isMap() );
|
||||
sqlDetectRowByIndexString = generateDetectRowByIndexString();
|
||||
sqlDetectRowByElementString = generateDetectRowByElementString();
|
||||
sqlSelectRowByIndexString = generateSelectRowByIndexString();
|
||||
|
||||
logStaticSQL();
|
||||
|
||||
isLazy = collectionBinding.isLazy();
|
||||
isExtraLazy = collectionBinding.isExtraLazy();
|
||||
isLazy = collectionBootDescriptor.isLazy();
|
||||
isExtraLazy = collectionBootDescriptor.isExtraLazy();
|
||||
|
||||
isInverse = collectionBinding.isInverse();
|
||||
isInverse = collectionBootDescriptor.isInverse();
|
||||
|
||||
if ( collectionBinding.isArray() ) {
|
||||
elementClass = ( (org.hibernate.mapping.Array) collectionBinding ).getElementClass();
|
||||
if ( collectionBootDescriptor.isArray() ) {
|
||||
elementClass = ( (org.hibernate.mapping.Array) collectionBootDescriptor ).getElementClass();
|
||||
}
|
||||
else {
|
||||
// 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 ) {
|
||||
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(
|
||||
// collectionBinding.getOrderBy(),
|
||||
// new ColumnMapperImpl(),
|
||||
|
@ -587,20 +609,20 @@ public abstract class AbstractCollectionPersister
|
|||
}
|
||||
|
||||
// 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
|
||||
manyToManyFilterHelper = new FilterHelper( collectionBinding.getManyToManyFilters(), factory);
|
||||
manyToManyWhereString = StringHelper.isNotEmpty( collectionBinding.getManyToManyWhere() ) ?
|
||||
"( " + collectionBinding.getManyToManyWhere() + ")" :
|
||||
manyToManyFilterHelper = new FilterHelper( collectionBootDescriptor.getManyToManyFilters(), factory);
|
||||
manyToManyWhereString = StringHelper.isNotEmpty( collectionBootDescriptor.getManyToManyWhere() ) ?
|
||||
"( " + collectionBootDescriptor.getManyToManyWhere() + ")" :
|
||||
null;
|
||||
manyToManyWhereTemplate = manyToManyWhereString == null ?
|
||||
null :
|
||||
Template.renderWhereStringTemplate( manyToManyWhereString, factory.getDialect(), factory.getSqlFunctionRegistry() );
|
||||
|
||||
hasManyToManyOrder = collectionBinding.getManyToManyOrdering() != null;
|
||||
hasManyToManyOrder = collectionBootDescriptor.getManyToManyOrdering() != null;
|
||||
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(
|
||||
// collectionBinding.getManyToManyOrdering(),
|
||||
// new ColumnMapperImpl(),
|
||||
|
@ -614,9 +636,37 @@ public abstract class AbstractCollectionPersister
|
|||
// manyToManyOrderByTranslation = null;
|
||||
}
|
||||
|
||||
comparator = collectionBinding.getComparator();
|
||||
comparator = collectionBootDescriptor.getComparator();
|
||||
|
||||
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
|
||||
|
@ -872,6 +922,16 @@ public abstract class AbstractCollectionPersister
|
|||
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
|
||||
*/
|
||||
|
@ -947,7 +1007,14 @@ public abstract class AbstractCollectionPersister
|
|||
*/
|
||||
protected int writeElement(PreparedStatement st, Object elt, int i, SharedSessionContractImplementor session)
|
||||
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 );
|
||||
|
||||
}
|
||||
|
@ -957,7 +1024,16 @@ public abstract class AbstractCollectionPersister
|
|||
*/
|
||||
protected int writeIndex(PreparedStatement st, Object index, int i, SharedSessionContractImplementor session)
|
||||
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 );
|
||||
}
|
||||
|
||||
|
@ -976,7 +1052,13 @@ public abstract class AbstractCollectionPersister
|
|||
if ( elementIsPureFormula ) {
|
||||
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;
|
||||
|
||||
}
|
||||
|
@ -989,7 +1071,13 @@ public abstract class AbstractCollectionPersister
|
|||
if ( indexContainsFormula ) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.hibernate.loader.collection.BatchingCollectionInitializerBuilder;
|
|||
import org.hibernate.loader.collection.CollectionInitializer;
|
||||
import org.hibernate.loader.collection.SubselectCollectionLoader;
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.persister.spi.PersisterCreationContext;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
|
|
|
@ -14,17 +14,26 @@ import java.util.Map;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
import org.hibernate.cache.spi.entry.CacheEntryStructure;
|
||||
import org.hibernate.collection.spi.CollectionSemantics;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
import org.hibernate.metadata.CollectionMetadata;
|
||||
import org.hibernate.metamodel.CollectionClassification;
|
||||
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
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.Type;
|
||||
|
||||
|
@ -62,7 +71,7 @@ import org.hibernate.type.Type;
|
|||
* @see org.hibernate.collection.spi.PersistentCollection
|
||||
* @author Gavin King
|
||||
*/
|
||||
public interface CollectionPersister extends CollectionDefinition {
|
||||
public interface CollectionPersister extends CollectionDefinition, TableReferenceContributor {
|
||||
/**
|
||||
* Initialize the given collection with the given key
|
||||
* TODO: add owner argument!!
|
||||
|
@ -103,6 +112,21 @@ public interface CollectionPersister extends CollectionDefinition {
|
|||
* Return the element class of an array, or null otherwise
|
||||
*/
|
||||
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>
|
||||
*/
|
||||
|
@ -332,4 +356,30 @@ public interface CollectionPersister extends CollectionDefinition {
|
|||
* @see CollectionClassification#SORTED_SET
|
||||
*/
|
||||
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() + "`"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.from.StandardTableGroup;
|
||||
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.TableReferenceCollector;
|
||||
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
||||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.Junction;
|
||||
|
@ -1187,20 +1189,23 @@ public abstract class AbstractEntityPersister
|
|||
SqlAstCreationContext creationContext) {
|
||||
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
|
||||
|
||||
final TableReference primaryTableReference = resolvePrimaryTableReference( sqlAliasBase, sqlExpressionResolver );
|
||||
|
||||
final List<TableReferenceJoin> joins = new ArrayList<>( );
|
||||
resolveTableReferenceJoins( primaryTableReference, sqlAliasBase, tableReferenceJoinType, joins::add, sqlExpressionResolver );
|
||||
|
||||
return new StandardTableGroup(
|
||||
final TableGroupBuilder builder = TableGroupBuilder.builder(
|
||||
navigablePath,
|
||||
this,
|
||||
lockMode,
|
||||
primaryTableReference,
|
||||
joins,
|
||||
sqlAliasBase,
|
||||
getFactory()
|
||||
creationContext.getSessionFactory()
|
||||
);
|
||||
|
||||
applyTableReferences(
|
||||
sqlAliasBase,
|
||||
tableReferenceJoinType,
|
||||
builder,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
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(
|
||||
int subClassTablePosition,
|
||||
TableReference rootTableReference,
|
||||
|
@ -6483,6 +6515,11 @@ public abstract class AbstractEntityPersister
|
|||
// otherwise, nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfFetchables() {
|
||||
return attributeMappings.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFetchables(
|
||||
Consumer<Fetchable> fetchableConsumer,
|
||||
|
|
|
@ -38,8 +38,13 @@ import org.hibernate.metamodel.model.domain.NavigableRole;
|
|||
import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
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.SqlAstCreationContext;
|
||||
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.EntityTuplizer;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -93,6 +98,11 @@ public interface EntityPersister extends EntityDefinition, EntityValuedModelPart
|
|||
@Deprecated
|
||||
void generateEntityDefinition();
|
||||
|
||||
@Override
|
||||
default int getNumberOfFetchables() {
|
||||
return getNumberOfAttributeMappings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the initialization of this object. {@link #prepareMappingModel}
|
||||
* must be called for all entity persisters before calling this method.
|
||||
|
@ -906,6 +916,4 @@ public interface EntityPersister extends EntityDefinition, EntityValuedModelPart
|
|||
default boolean canIdentityInsertBeDelayed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -499,6 +499,7 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
creationContext
|
||||
);
|
||||
|
||||
lhsTableGroup.addTableGroupJoin( tableGroupJoin );
|
||||
fromClauseIndex.register( sqmJoin, tableGroupJoin.getJoinedGroup() );
|
||||
|
||||
// add any additional join restrictions
|
||||
|
|
|
@ -37,7 +37,6 @@ public class FromClauseIndex extends SimpleFromClauseAccessImpl {
|
|||
* Holds *explicitly* fetched joins
|
||||
*/
|
||||
private Map<NavigablePath, SqmAttributeJoin> fetchesByPath;
|
||||
private Map<NavigablePath, Map<NavigablePath, SqmAttributeJoin>> fetchesByParentPath;
|
||||
|
||||
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) {
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.query.spi.QueryParameterBindings;
|
|||
import org.hibernate.query.sqm.internal.DomainParameterXref;
|
||||
import org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter;
|
||||
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.from.SqmAttributeJoin;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
|
@ -67,7 +68,7 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
|||
@SuppressWarnings("unchecked")
|
||||
public class StandardSqmSelectToSqlAstConverter
|
||||
extends BaseSqmToSqlAstConverter
|
||||
implements DomainResultCreationState, org.hibernate.query.sqm.sql.SqmSelectToSqlAstConverter {
|
||||
implements DomainResultCreationState, SqmSelectToSqlAstConverter {
|
||||
private final LoadQueryInfluencers fetchInfluencers;
|
||||
private final CircularFetchDetector circularFetchDetector = new CircularFetchDetector();
|
||||
|
||||
|
@ -155,7 +156,7 @@ public class StandardSqmSelectToSqlAstConverter
|
|||
|
||||
@Override
|
||||
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
|
||||
final Consumer<Fetchable> fetchableConsumer = new Consumer<Fetchable>() {
|
||||
|
@ -214,7 +215,7 @@ public class StandardSqmSelectToSqlAstConverter
|
|||
|
||||
if ( fetchedJoin != null ) {
|
||||
// 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
|
||||
assert getFromClauseIndex().getTableGroup( fetchablePath ) != null;
|
||||
|
||||
|
|
|
@ -6,13 +6,18 @@
|
|||
*/
|
||||
package org.hibernate.sql.ast.tree.from;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
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;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -23,7 +28,7 @@ public class StandardTableGroup extends AbstractTableGroup {
|
|||
|
||||
public StandardTableGroup(
|
||||
NavigablePath navigablePath,
|
||||
RootTableGroupProducer tableGroupProducer,
|
||||
TableGroupProducer tableGroupProducer,
|
||||
LockMode lockMode,
|
||||
TableReference primaryTableReference,
|
||||
List<TableReferenceJoin> tableJoins,
|
||||
|
@ -34,11 +39,6 @@ public class StandardTableGroup extends AbstractTableGroup {
|
|||
this.tableJoins = tableJoins;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RootTableGroupProducer getModelPart() {
|
||||
return (RootTableGroupProducer) super.getModelPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ import org.hibernate.query.sqm.sql.SqlAliasBaseManager;
|
|||
* @author Steve Ebersole
|
||||
* @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
|
||||
* references that are part of the TableGroup being generated
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -6,19 +6,22 @@
|
|||
*/
|
||||
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.spi.SqlAliasBase;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface TableReferenceContributor {
|
||||
// /**
|
||||
// * Apply the Tables mapped by this producer to the collector as TableReferences
|
||||
// */
|
||||
// void applyTableReferenceJoins(
|
||||
// ColumnReferenceQualifier lhs,
|
||||
// JoinType joinType,
|
||||
// SqlAliasBase sqlAliasBase,
|
||||
// TableReferenceJoinCollector joinCollector);
|
||||
/**
|
||||
* Apply the Tables mapped by this producer to the collector as TableReferences
|
||||
*/
|
||||
void applyTableReferences(
|
||||
SqlAliasBase sqlAliasBase,
|
||||
JoinType baseJoinType,
|
||||
TableReferenceCollector collector,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -11,7 +11,9 @@ import java.util.List;
|
|||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.named.RowReaderMemento;
|
||||
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.EntityInitializer;
|
||||
import org.hibernate.sql.results.spi.Initializer;
|
||||
import org.hibernate.sql.results.spi.JdbcValuesSourceProcessingOptions;
|
||||
import org.hibernate.sql.results.spi.JdbcValuesSourceProcessingState;
|
||||
|
@ -125,7 +127,17 @@ public class StandardRowReader<T> implements RowReader<T> {
|
|||
// old
|
||||
|
||||
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++ ) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ import java.util.function.Consumer;
|
|||
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
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.sql.results.internal.domain.AbstractFetchParent;
|
||||
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 {
|
||||
private final FetchParent fetchParent;
|
||||
private final FetchTiming fetchTiming;
|
||||
private final boolean nullable;
|
||||
|
||||
public CompositeFetch(
|
||||
NavigablePath navigablePath,
|
||||
EmbeddedAttributeMapping embeddedAttribute,
|
||||
EmbeddableValuedModelPart embeddedPartDescriptor,
|
||||
FetchParent fetchParent,
|
||||
FetchTiming fetchTiming,
|
||||
boolean nullable,
|
||||
DomainResultCreationState creationState) {
|
||||
super( embeddedAttribute, navigablePath );
|
||||
super( embeddedPartDescriptor, navigablePath );
|
||||
|
||||
this.fetchParent = fetchParent;
|
||||
this.fetchTiming = fetchTiming;
|
||||
this.nullable = nullable;
|
||||
|
||||
creationState.getSqlAstCreationState().getFromClauseAccess().registerTableGroup(
|
||||
getNavigablePath(),
|
||||
|
@ -49,38 +52,34 @@ public class CompositeFetch extends AbstractFetchParent implements CompositeResu
|
|||
afterInitialize( creationState );
|
||||
}
|
||||
|
||||
public EmbeddedAttributeMapping getEmbeddedAttributeMapping() {
|
||||
return (EmbeddedAttributeMapping) super.getFetchContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchParent getFetchParent() {
|
||||
return fetchParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbeddedAttributeMapping getFetchContainer() {
|
||||
return getEmbeddedAttributeMapping();
|
||||
public EmbeddableValuedModelPart getFetchContainer() {
|
||||
return (EmbeddableValuedModelPart) super.getFetchContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbeddedAttributeMapping getReferencedMappingContainer() {
|
||||
return getEmbeddedAttributeMapping();
|
||||
public EmbeddableValuedModelPart getReferencedMappingContainer() {
|
||||
return getFetchContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetchable getFetchedMapping() {
|
||||
return getEmbeddedAttributeMapping();
|
||||
return getFetchContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmbeddableMappingType getReferencedMappingType() {
|
||||
return getEmbeddedAttributeMapping().getEmbeddableTypeDescriptor();
|
||||
return getFetchContainer().getEmbeddableTypeDescriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return getEmbeddedAttributeMapping().getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable();
|
||||
return nullable;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -27,4 +27,9 @@ public class CompositeFetchInitializer
|
|||
AssemblerCreationState creationState) {
|
||||
super( resultDescriptor, fetchParentAccess, initializerConsumer, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getParentKey() {
|
||||
return getFetchParentAccess().getParentKey();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,4 +22,9 @@ public class CompositeRootInitializer extends AbstractCompositeInitializer {
|
|||
AssemblerCreationState creationState) {
|
||||
super( resultDescriptor, null, initializerConsumer, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getParentKey() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.hibernate.event.spi.PreLoadEvent;
|
|||
import org.hibernate.event.spi.PreLoadEventListener;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.StateArrayContributorMapping;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Loadable;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
|
@ -197,6 +196,11 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
|||
return entityKey.getIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getParentKey() {
|
||||
return getKeyValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getFetchParentInstance() {
|
||||
if ( entityInstance == null ) {
|
||||
|
|
|
@ -25,8 +25,6 @@ import org.hibernate.sql.results.spi.EntityResult;
|
|||
public class EntityResultImpl extends AbstractEntityResultNode implements EntityResult {
|
||||
private final String resultVariable;
|
||||
|
||||
|
||||
|
||||
public EntityResultImpl(
|
||||
NavigablePath navigablePath,
|
||||
EntityValuedModelPart entityValuedModelPart,
|
||||
|
|
|
@ -8,7 +8,7 @@ package org.hibernate.sql.results.spi;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
|
||||
/**
|
||||
|
@ -22,7 +22,7 @@ public interface FetchParent extends ResultSetMappingNode {
|
|||
/**
|
||||
* This parent's type
|
||||
*/
|
||||
ManagedMappingType getReferencedMappingType();
|
||||
FetchableContainer getReferencedMappingType();
|
||||
|
||||
/**
|
||||
* Get the property path to this parent
|
||||
|
|
|
@ -19,6 +19,8 @@ import org.hibernate.query.NavigablePath;
|
|||
public interface FetchParentAccess {
|
||||
FetchParentAccess findFirstEntityDescriptorAccess();
|
||||
|
||||
Object getParentKey();
|
||||
|
||||
/**
|
||||
* Access to the fetch's parent instance.
|
||||
*/
|
||||
|
|
|
@ -15,6 +15,8 @@ import org.hibernate.metamodel.mapping.ModelPartContainer;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface FetchableContainer extends ModelPartContainer {
|
||||
int getNumberOfFetchables();
|
||||
|
||||
default void visitKeyFetchables(
|
||||
Consumer<Fetchable> fetchableConsumer,
|
||||
EntityMappingType treatTargetType) {
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.sql.results.spi;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
|
||||
import org.hibernate.engine.spi.CollectionKey;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
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.
|
||||
* 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
|
||||
* a ResultSet or second-level cache hit.
|
||||
*
|
||||
|
|
|
@ -9,9 +9,6 @@ package org.hibernate.sql.results.spi;
|
|||
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;
|
||||
|
||||
|
@ -20,76 +17,14 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class LoadingCollectionEntry {
|
||||
private final CollectionPersister collectionDescriptor;
|
||||
private final CollectionInitializer initializer;
|
||||
// todo (6.0) : change from Serializable to Object
|
||||
private final Serializable key;
|
||||
private final PersistentCollection collectionInstance;
|
||||
public interface LoadingCollectionEntry {
|
||||
CollectionPersister getCollectionDescriptor();
|
||||
|
||||
public LoadingCollectionEntry(
|
||||
CollectionPersister collectionDescriptor,
|
||||
CollectionInitializer initializer,
|
||||
Serializable key,
|
||||
PersistentCollection collectionInstance) {
|
||||
this.collectionDescriptor = collectionDescriptor;
|
||||
this.initializer = initializer;
|
||||
this.key = key;
|
||||
this.collectionInstance = collectionInstance;
|
||||
CollectionInitializer getInitializer();
|
||||
|
||||
collectionInstance.beforeInitialize( getCollectionDescriptor(), -1 );
|
||||
collectionInstance.beginRead();
|
||||
}
|
||||
Serializable getKey();
|
||||
|
||||
public CollectionPersister getCollectionDescriptor() {
|
||||
return collectionDescriptor;
|
||||
}
|
||||
PersistentCollection getCollectionInstance();
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
void finishLoading(ExecutionContext executionContext);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.type.descriptor.java;
|
||||
|
||||
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.TRUE;
|
||||
|
@ -16,7 +17,7 @@ import static java.lang.Boolean.TRUE;
|
|||
*
|
||||
* @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();
|
||||
|
||||
private final char characterValueTrue;
|
||||
|
@ -130,4 +131,14 @@ public class BooleanTypeDescriptor extends AbstractTypeDescriptor<Boolean> {
|
|||
public Long toLong(Boolean value) {
|
||||
return (long) toInt( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getPrimitiveClass() {
|
||||
return boolean.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getDefaultValue() {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.type.descriptor.java;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.spi.Primitive;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Byte} handling.
|
||||
|
@ -13,7 +14,7 @@ import org.hibernate.type.descriptor.WrapperOptions;
|
|||
* @author Steve Ebersole
|
||||
* @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 ByteTypeDescriptor() {
|
||||
|
@ -58,6 +59,7 @@ public class ByteTypeDescriptor extends AbstractTypeDescriptor<Byte> {
|
|||
}
|
||||
throw unknownUnwrap( type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Byte wrap(X value, WrapperOptions options) {
|
||||
if ( value == null ) {
|
||||
|
@ -74,4 +76,14 @@ public class ByteTypeDescriptor extends AbstractTypeDescriptor<Byte> {
|
|||
}
|
||||
throw unknownWrap( value.getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getPrimitiveClass() {
|
||||
return byte.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte getDefaultValue() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
package org.hibernate.type.descriptor.java;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.spi.Primitive;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Character} handling.
|
||||
*
|
||||
* @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 CharacterTypeDescriptor() {
|
||||
|
@ -66,4 +67,14 @@ public class CharacterTypeDescriptor extends AbstractTypeDescriptor<Character> {
|
|||
}
|
||||
throw unknownWrap( value.getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getPrimitiveClass() {
|
||||
return char.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Character getDefaultValue() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,14 @@ import java.math.BigDecimal;
|
|||
import java.math.BigInteger;
|
||||
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.spi.Primitive;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Double} handling.
|
||||
*
|
||||
* @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 DoubleTypeDescriptor() {
|
||||
|
@ -71,15 +72,25 @@ public class DoubleTypeDescriptor extends AbstractTypeDescriptor<Double> {
|
|||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
if ( Double.class.isInstance( value ) ) {
|
||||
if ( value instanceof Double ) {
|
||||
return (Double) value;
|
||||
}
|
||||
if ( Number.class.isInstance( value ) ) {
|
||||
if ( value instanceof Number ) {
|
||||
return ( (Number) value ).doubleValue();
|
||||
}
|
||||
else if ( String.class.isInstance( value ) ) {
|
||||
else if ( value instanceof String ) {
|
||||
return Double.valueOf( ( (String) value ) );
|
||||
}
|
||||
throw unknownWrap( value.getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getPrimitiveClass() {
|
||||
return double.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getDefaultValue() {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,14 @@ import java.math.BigDecimal;
|
|||
import java.math.BigInteger;
|
||||
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.spi.Primitive;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Float} handling.
|
||||
*
|
||||
* @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 FloatTypeDescriptor() {
|
||||
|
@ -82,4 +83,14 @@ public class FloatTypeDescriptor extends AbstractTypeDescriptor<Float> {
|
|||
}
|
||||
throw unknownWrap( value.getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getPrimitiveClass() {
|
||||
return float.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float getDefaultValue() {
|
||||
return 0F;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,14 @@ import java.math.BigDecimal;
|
|||
import java.math.BigInteger;
|
||||
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.spi.Primitive;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Integer} handling.
|
||||
*
|
||||
* @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 IntegerTypeDescriptor() {
|
||||
|
@ -82,4 +83,14 @@ public class IntegerTypeDescriptor extends AbstractTypeDescriptor<Integer> {
|
|||
}
|
||||
throw unknownWrap( value.getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getPrimitiveClass() {
|
||||
return int.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getDefaultValue() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,14 @@ import java.math.BigDecimal;
|
|||
import java.math.BigInteger;
|
||||
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.spi.Primitive;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Long} handling.
|
||||
*
|
||||
* @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 LongTypeDescriptor() {
|
||||
|
@ -82,4 +83,14 @@ public class LongTypeDescriptor extends AbstractTypeDescriptor<Long> {
|
|||
}
|
||||
throw unknownWrap( value.getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getPrimitiveClass() {
|
||||
return long.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getDefaultValue() {
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
*/
|
||||
package org.hibernate.type.descriptor.java;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.spi.Primitive;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Short} handling.
|
||||
*
|
||||
* @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 ShortTypeDescriptor() {
|
||||
|
@ -72,4 +73,14 @@ public class ShortTypeDescriptor extends AbstractTypeDescriptor<Short> {
|
|||
}
|
||||
throw unknownWrap( value.getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getPrimitiveClass() {
|
||||
return short.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Short getDefaultValue() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ public class JavaTypeDescriptorRegistry implements JavaTypeDescriptorBaseline.Ba
|
|||
@SuppressWarnings("unused")
|
||||
public JavaTypeDescriptorRegistry(TypeConfiguration typeConfiguration) {
|
||||
this.typeConfiguration = typeConfiguration;
|
||||
JavaTypeDescriptorBaseline.prime( this );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
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.walking.spi.AttributeDefinition;
|
||||
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.EntityMetamodel;
|
||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||
|
@ -717,6 +723,16 @@ public class PersisterClassProviderTest {
|
|||
public JavaTypeDescriptor getMappedJavaTypeDescriptor() {
|
||||
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 {
|
||||
|
|
|
@ -6,13 +6,16 @@
|
|||
*/
|
||||
package org.hibernate.orm.test.metamodel.mapping;
|
||||
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
|
@ -21,14 +24,20 @@ import javax.persistence.OneToMany;
|
|||
import javax.persistence.OrderColumn;
|
||||
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.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 static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -36,6 +45,7 @@ import org.junit.jupiter.api.Test;
|
|||
annotatedClasses = {
|
||||
PluralAttributeTests.SimpleEntity.class,
|
||||
PluralAttributeTests.EntityContainingLists.class,
|
||||
PluralAttributeTests.EntityContainingSets.class,
|
||||
PluralAttributeTests.Component.class
|
||||
}
|
||||
)
|
||||
|
@ -46,51 +56,50 @@ public class PluralAttributeTests {
|
|||
|
||||
@Test
|
||||
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
|
||||
public void createTestData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final EntityContainingLists entityContainingLists = new EntityContainingLists( 1, "first" );
|
||||
@Test
|
||||
public void testSets(SessionFactoryScope scope) {
|
||||
final DomainMetamodel domainModel = scope.getSessionFactory().getDomainModel();
|
||||
final EntityMappingType containerEntityDescriptor = domainModel.getEntityDescriptor( EntityContainingSets.class );
|
||||
|
||||
entityContainingLists.addBasic( "abc" );
|
||||
entityContainingLists.addBasic( "def" );
|
||||
entityContainingLists.addBasic( "ghi" );
|
||||
assertThat( containerEntityDescriptor.getNumberOfAttributeMappings(), is( 6 ) );
|
||||
|
||||
entityContainingLists.addConvertedBasic( EnumValue.TWO );
|
||||
final AttributeMapping setOfBasics = containerEntityDescriptor.findAttributeMapping( "setOfBasics" );
|
||||
assertThat( setOfBasics, notNullValue() );
|
||||
|
||||
entityContainingLists.addEnum( EnumValue.ONE );
|
||||
entityContainingLists.addEnum( EnumValue.THREE );
|
||||
final AttributeMapping setOfConvertedBasics = containerEntityDescriptor.findAttributeMapping( "setOfConvertedBasics" );
|
||||
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" ) );
|
||||
entityContainingLists.addSimpleEntity( new SimpleEntity( 2, "simple-2" ) );
|
||||
final AttributeMapping setOfEnums = containerEntityDescriptor.findAttributeMapping( "setOfEnums" );
|
||||
assertThat( setOfEnums, notNullValue() );
|
||||
|
||||
session.save( entityContainingLists );
|
||||
}
|
||||
);
|
||||
}
|
||||
final AttributeMapping setOfComponents = containerEntityDescriptor.findAttributeMapping( "setOfComponents" );
|
||||
assertThat( setOfComponents, notNullValue() );
|
||||
|
||||
@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" );
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
final AttributeMapping setOfEntities = containerEntityDescriptor.findAttributeMapping( "setOfEntities" );
|
||||
assertThat( setOfEntities, notNullValue() );
|
||||
}
|
||||
|
||||
public enum EnumValue {
|
||||
|
@ -198,6 +207,7 @@ public class PluralAttributeTests {
|
|||
|
||||
@ElementCollection
|
||||
@OrderColumn
|
||||
@Convert( converter = Converter.class )
|
||||
public List<EnumValue> getListOfConvertedBasics() {
|
||||
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" )
|
||||
@Table( name = "simple_entity" )
|
||||
public static class SimpleEntity {
|
||||
|
|
|
@ -24,7 +24,10 @@ import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
|||
import org.hibernate.metamodel.mapping.internal.SingularAssociationAttributeMapping;
|
||||
import org.hibernate.metamodel.model.convert.internal.NamedEnumValueConverter;
|
||||
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.type.CustomType;
|
||||
import org.hibernate.usertype.UserType;
|
||||
|
||||
import org.hibernate.testing.hamcrest.CollectionMatchers;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
|
@ -72,8 +75,12 @@ public class SmokeTests {
|
|||
final BasicValuedSingularAttributeMapping genderAttrMapping = (BasicValuedSingularAttributeMapping) genderPart;
|
||||
assert "mapping_simple_entity".equals( genderAttrMapping.getContainingTableExpression() );
|
||||
assert "gender".equals( genderAttrMapping.getMappedColumnExpression() );
|
||||
assert genderAttrMapping.getConverter() != null;
|
||||
assert genderAttrMapping.getConverter() instanceof OrdinalEnumValueConverter;
|
||||
assert genderAttrMapping.getMappedTypeDescriptor() instanceof CustomType;
|
||||
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;
|
||||
assert "mapping_simple_entity".equals( attrMapping.getContainingTableExpression() );
|
||||
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;
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -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.spi.DomainResult;
|
||||
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.usertype.UserType;
|
||||
|
||||
import org.hibernate.testing.hamcrest.AssignableMatcher;
|
||||
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.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
/**
|
||||
|
@ -174,10 +178,15 @@ public class SmokeTests {
|
|||
assertThat( columnReference.renderSqlFragment( scope.getSessionFactory() ), is( "s1_0.gender" ) );
|
||||
|
||||
final MappingModelExpressable selectedExpressable = selectedExpression.getExpressionType();
|
||||
assertThat( selectedExpressable, instanceOf( StandardBasicTypeImpl.class ) );
|
||||
final StandardBasicTypeImpl basicType = (StandardBasicTypeImpl) selectedExpressable;
|
||||
assertThat( basicType.getJavaTypeDescriptor().getJavaType(), AssignableMatcher.assignableTo( Integer.class ) );
|
||||
assertThat( basicType.getSqlTypeDescriptor().getSqlType(), is( Types.INTEGER ) );
|
||||
//assertThat( selectedExpressable, instanceOf( StandardBasicTypeImpl.class ) );
|
||||
// assertThat( basicType.getJavaTypeDescriptor().getJavaType(), AssignableMatcher.assignableTo( Integer.class ) );
|
||||
// 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 ) );
|
||||
final DomainResult domainResult = sqlAst.getDomainResultDescriptors().get( 0 );
|
||||
|
@ -185,8 +194,10 @@ public class SmokeTests {
|
|||
final BasicResult scalarDomainResult = (BasicResult) domainResult;
|
||||
assertThat( scalarDomainResult.getAssembler(), instanceOf( BasicResultAssembler.class ) );
|
||||
final BasicResultAssembler<?> assembler = (BasicResultAssembler) scalarDomainResult.getAssembler();
|
||||
assertThat( assembler.getValueConverter(), notNullValue() );
|
||||
assertThat( assembler.getValueConverter(), instanceOf( OrdinalEnumValueConverter.class ) );
|
||||
// assertThat( assembler.getValueConverter(), notNullValue() );
|
||||
// assertThat( assembler.getValueConverter(), instanceOf( OrdinalEnumValueConverter.class ) );
|
||||
assertThat( assembler.getValueConverter(), nullValue() );
|
||||
|
||||
final NavigablePath expectedSelectedPath = new NavigablePath(
|
||||
org.hibernate.orm.test.metamodel.mapping.SmokeTests.SimpleEntity.class.getName(),
|
||||
"e"
|
||||
|
@ -202,9 +213,10 @@ public class SmokeTests {
|
|||
);
|
||||
|
||||
assertThat( resultAssembler, instanceOf( BasicResultAssembler.class ) );
|
||||
final BasicValueConverter valueConverter = ( (BasicResultAssembler) resultAssembler ).getValueConverter();
|
||||
assertThat( valueConverter, notNullValue() );
|
||||
assertThat( valueConverter, instanceOf( OrdinalEnumValueConverter.class ) );
|
||||
// final BasicValueConverter valueConverter = ( (BasicResultAssembler) resultAssembler ).getValueConverter();
|
||||
// assertThat( valueConverter, notNullValue() );
|
||||
// assertThat( valueConverter, instanceOf( OrdinalEnumValueConverter.class ) );
|
||||
assertThat( ( (BasicResultAssembler) resultAssembler ).getValueConverter(), nullValue() );
|
||||
|
||||
final JdbcSelect jdbcSelectOperation = new StandardSqlAstSelectTranslator( session.getSessionFactory() )
|
||||
.interpret( sqlAst );
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -12,7 +12,6 @@ import java.util.List;
|
|||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
|
||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||
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.CollectionIndexDefinition;
|
||||
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.EntityMetamodel;
|
||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||
|
@ -703,6 +709,16 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
|
|||
public JavaTypeDescriptor getMappedJavaTypeDescriptor() {
|
||||
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 {
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
|
||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
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.walking.spi.AttributeDefinition;
|
||||
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.EntityMetamodel;
|
||||
import org.hibernate.tuple.entity.EntityTuplizer;
|
||||
|
@ -815,4 +821,14 @@ public class CustomPersister implements EntityPersister {
|
|||
public JavaTypeDescriptor getMappedJavaTypeDescriptor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTableReferences(
|
||||
SqlAliasBase sqlAliasBase,
|
||||
JoinType baseJoinType,
|
||||
TableReferenceCollector collector,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue