merge master
This commit is contained in:
commit
a3184e16cb
|
@ -483,3 +483,5 @@ subprojects { subProject ->
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task release(type: Task, dependsOn: 'release:release')
|
||||||
|
|
|
@ -26,7 +26,6 @@ package org.hibernate;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import org.hibernate.procedure.ProcedureCall;
|
import org.hibernate.procedure.ProcedureCall;
|
||||||
import org.hibernate.procedure.ProcedureCallMemento;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contract methods shared between {@link Session} and {@link StatelessSession}.
|
* Contract methods shared between {@link Session} and {@link StatelessSession}.
|
||||||
|
|
|
@ -61,14 +61,20 @@ public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFa
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
public RegionFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
|
public RegionFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
|
||||||
Properties p = new Properties();
|
final Properties p = new Properties();
|
||||||
if (configurationValues != null) {
|
if (configurationValues != null) {
|
||||||
p.putAll( configurationValues );
|
p.putAll( configurationValues );
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean useSecondLevelCache = ConfigurationHelper.getBoolean( AvailableSettings.USE_SECOND_LEVEL_CACHE,
|
final boolean useSecondLevelCache = ConfigurationHelper.getBoolean(
|
||||||
configurationValues, true );
|
AvailableSettings.USE_SECOND_LEVEL_CACHE,
|
||||||
boolean useQueryCache = ConfigurationHelper.getBoolean( AvailableSettings.USE_QUERY_CACHE, configurationValues );
|
configurationValues,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
final boolean useQueryCache = ConfigurationHelper.getBoolean(
|
||||||
|
AvailableSettings.USE_QUERY_CACHE,
|
||||||
|
configurationValues
|
||||||
|
);
|
||||||
|
|
||||||
RegionFactory regionFactory = NoCachingRegionFactory.INSTANCE;
|
RegionFactory regionFactory = NoCachingRegionFactory.INSTANCE;
|
||||||
|
|
||||||
|
@ -81,16 +87,6 @@ public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFa
|
||||||
try {
|
try {
|
||||||
regionFactory = registry.getService( StrategySelector.class )
|
regionFactory = registry.getService( StrategySelector.class )
|
||||||
.resolveStrategy( RegionFactory.class, setting );
|
.resolveStrategy( RegionFactory.class, setting );
|
||||||
// try {
|
|
||||||
// regionFactory = regionFactoryClass.getConstructor( Properties.class ).newInstance( p );
|
|
||||||
// }
|
|
||||||
// catch ( NoSuchMethodException e ) {
|
|
||||||
// // no constructor accepting Properties found, try no arg constructor
|
|
||||||
// LOG.debugf(
|
|
||||||
// "%s did not provide constructor accepting java.util.Properties; attempting no-arg constructor.",
|
|
||||||
// regionFactoryClass.getSimpleName() );
|
|
||||||
// regionFactory = regionFactoryClass.getConstructor().newInstance();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
catch ( Exception e ) {
|
catch ( Exception e ) {
|
||||||
throw new HibernateException( "could not instantiate RegionFactory [" + setting + "]", e );
|
throw new HibernateException( "could not instantiate RegionFactory [" + setting + "]", e );
|
||||||
|
|
|
@ -209,6 +209,9 @@ public final class AnnotationBinder {
|
||||||
|
|
||||||
public static void bindDefaults(Mappings mappings) {
|
public static void bindDefaults(Mappings mappings) {
|
||||||
Map defaults = mappings.getReflectionManager().getDefaults();
|
Map defaults = mappings.getReflectionManager().getDefaults();
|
||||||
|
|
||||||
|
// id generators ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
{
|
{
|
||||||
List<SequenceGenerator> anns = ( List<SequenceGenerator> ) defaults.get( SequenceGenerator.class );
|
List<SequenceGenerator> anns = ( List<SequenceGenerator> ) defaults.get( SequenceGenerator.class );
|
||||||
if ( anns != null ) {
|
if ( anns != null ) {
|
||||||
|
@ -231,6 +234,9 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// queries ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
{
|
{
|
||||||
List<NamedQuery> anns = ( List<NamedQuery> ) defaults.get( NamedQuery.class );
|
List<NamedQuery> anns = ( List<NamedQuery> ) defaults.get( NamedQuery.class );
|
||||||
if ( anns != null ) {
|
if ( anns != null ) {
|
||||||
|
@ -247,6 +253,9 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// result-set-mappings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
{
|
{
|
||||||
List<SqlResultSetMapping> anns = ( List<SqlResultSetMapping> ) defaults.get( SqlResultSetMapping.class );
|
List<SqlResultSetMapping> anns = ( List<SqlResultSetMapping> ) defaults.get( SqlResultSetMapping.class );
|
||||||
if ( anns != null ) {
|
if ( anns != null ) {
|
||||||
|
@ -256,6 +265,8 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stored procs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
{
|
{
|
||||||
final List<NamedStoredProcedureQuery> annotations =
|
final List<NamedStoredProcedureQuery> annotations =
|
||||||
(List<NamedStoredProcedureQuery>) defaults.get( NamedStoredProcedureQuery.class );
|
(List<NamedStoredProcedureQuery>) defaults.get( NamedStoredProcedureQuery.class );
|
||||||
|
@ -265,7 +276,6 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
final List<NamedStoredProcedureQueries> annotations =
|
final List<NamedStoredProcedureQueries> annotations =
|
||||||
(List<NamedStoredProcedureQueries>) defaults.get( NamedStoredProcedureQueries.class );
|
(List<NamedStoredProcedureQueries>) defaults.get( NamedStoredProcedureQueries.class );
|
||||||
|
|
|
@ -341,6 +341,7 @@ public class BinderHelper {
|
||||||
*/
|
*/
|
||||||
if ( value instanceof ToOne ) {
|
if ( value instanceof ToOne ) {
|
||||||
( (ToOne) value ).setReferencedPropertyName( syntheticPropertyName );
|
( (ToOne) value ).setReferencedPropertyName( syntheticPropertyName );
|
||||||
|
( (ToOne) value ).setReferenceToPrimaryKey( syntheticPropertyName == null );
|
||||||
mappings.addUniquePropertyReference( ownerEntity.getEntityName(), syntheticPropertyName );
|
mappings.addUniquePropertyReference( ownerEntity.getEntityName(), syntheticPropertyName );
|
||||||
}
|
}
|
||||||
else if ( value instanceof Collection ) {
|
else if ( value instanceof Collection ) {
|
||||||
|
|
|
@ -84,6 +84,8 @@ import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
|
||||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
|
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
|
||||||
|
import org.hibernate.cache.spi.GeneralDataRegion;
|
||||||
|
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||||
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
|
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
|
||||||
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
|
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
|
||||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||||
|
@ -217,6 +219,7 @@ public class Configuration implements Serializable {
|
||||||
protected Map<String, NamedSQLQueryDefinition> namedSqlQueries;
|
protected Map<String, NamedSQLQueryDefinition> namedSqlQueries;
|
||||||
protected Map<String, NamedProcedureCallDefinition> namedProcedureCallMap;
|
protected Map<String, NamedProcedureCallDefinition> namedProcedureCallMap;
|
||||||
protected Map<String, ResultSetMappingDefinition> sqlResultSetMappings;
|
protected Map<String, ResultSetMappingDefinition> sqlResultSetMappings;
|
||||||
|
protected Map<String, NamedEntityGraphDefinition> namedEntityGraphMap;
|
||||||
|
|
||||||
protected Map<String, TypeDef> typeDefs;
|
protected Map<String, TypeDef> typeDefs;
|
||||||
protected Map<String, FilterDefinition> filterDefinitions;
|
protected Map<String, FilterDefinition> filterDefinitions;
|
||||||
|
@ -299,6 +302,7 @@ public class Configuration implements Serializable {
|
||||||
namedQueries = new HashMap<String,NamedQueryDefinition>();
|
namedQueries = new HashMap<String,NamedQueryDefinition>();
|
||||||
namedSqlQueries = new HashMap<String,NamedSQLQueryDefinition>();
|
namedSqlQueries = new HashMap<String,NamedSQLQueryDefinition>();
|
||||||
sqlResultSetMappings = new HashMap<String, ResultSetMappingDefinition>();
|
sqlResultSetMappings = new HashMap<String, ResultSetMappingDefinition>();
|
||||||
|
namedEntityGraphMap = new HashMap<String, NamedEntityGraphDefinition>();
|
||||||
|
|
||||||
typeDefs = new HashMap<String,TypeDef>();
|
typeDefs = new HashMap<String,TypeDef>();
|
||||||
filterDefinitions = new HashMap<String, FilterDefinition>();
|
filterDefinitions = new HashMap<String, FilterDefinition>();
|
||||||
|
@ -2619,6 +2623,12 @@ public class Configuration implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public java.util.Collection<NamedEntityGraphDefinition> getNamedEntityGraphs() {
|
||||||
|
return namedEntityGraphMap == null
|
||||||
|
? Collections.<NamedEntityGraphDefinition>emptyList()
|
||||||
|
: namedEntityGraphMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Mappings impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// Mappings impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -2886,6 +2896,16 @@ public class Configuration implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addNamedEntityGraphDefintion(NamedEntityGraphDefinition definition)
|
||||||
|
throws DuplicateMappingException {
|
||||||
|
final String name = definition.getRegisteredName();
|
||||||
|
final NamedEntityGraphDefinition previous = namedEntityGraphMap.put( name, definition );
|
||||||
|
if ( previous != null ) {
|
||||||
|
throw new DuplicateMappingException( "NamedEntityGraph", name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void addDefaultSQLQuery(String name, NamedSQLQueryDefinition query) {
|
public void addDefaultSQLQuery(String name, NamedSQLQueryDefinition query) {
|
||||||
applySQLQuery( name, query );
|
applySQLQuery( name, query );
|
||||||
defaultNamedNativeQueryNames.add( name );
|
defaultNamedNativeQueryNames.add( name );
|
||||||
|
|
|
@ -1620,6 +1620,7 @@ public final class HbmBinder {
|
||||||
if ( ukName != null ) {
|
if ( ukName != null ) {
|
||||||
manyToOne.setReferencedPropertyName( ukName.getValue() );
|
manyToOne.setReferencedPropertyName( ukName.getValue() );
|
||||||
}
|
}
|
||||||
|
manyToOne.setReferenceToPrimaryKey( manyToOne.getReferencedPropertyName() == null );
|
||||||
|
|
||||||
manyToOne.setReferencedEntityName( getEntityName( node, mappings ) );
|
manyToOne.setReferencedEntityName( getEntityName( node, mappings ) );
|
||||||
|
|
||||||
|
@ -1702,6 +1703,7 @@ public final class HbmBinder {
|
||||||
|
|
||||||
Attribute ukName = node.attribute( "property-ref" );
|
Attribute ukName = node.attribute( "property-ref" );
|
||||||
if ( ukName != null ) oneToOne.setReferencedPropertyName( ukName.getValue() );
|
if ( ukName != null ) oneToOne.setReferencedPropertyName( ukName.getValue() );
|
||||||
|
oneToOne.setReferenceToPrimaryKey( oneToOne.getReferencedPropertyName() == null );
|
||||||
|
|
||||||
oneToOne.setPropertyName( node.attributeValue( "name" ) );
|
oneToOne.setPropertyName( node.attributeValue( "name" ) );
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.hibernate.MappingException;
|
||||||
import org.hibernate.annotations.AnyMetaDef;
|
import org.hibernate.annotations.AnyMetaDef;
|
||||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||||
import org.hibernate.annotations.common.reflection.XClass;
|
import org.hibernate.annotations.common.reflection.XClass;
|
||||||
|
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||||
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
|
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
|
||||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||||
import org.hibernate.engine.spi.FilterDefinition;
|
import org.hibernate.engine.spi.FilterDefinition;
|
||||||
|
@ -347,6 +348,15 @@ public interface Mappings {
|
||||||
*/
|
*/
|
||||||
public void addNamedProcedureCallDefinition(NamedProcedureCallDefinition definition) throws DuplicateMappingException;
|
public void addNamedProcedureCallDefinition(NamedProcedureCallDefinition definition) throws DuplicateMappingException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds metadata for a named entity graph to this repository
|
||||||
|
*
|
||||||
|
* @param namedEntityGraphDefinition The procedure call information
|
||||||
|
*
|
||||||
|
* @throws DuplicateMappingException If an entity graph already exists with that name.
|
||||||
|
*/
|
||||||
|
public void addNamedEntityGraphDefintion(NamedEntityGraphDefinition namedEntityGraphDefinition);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the metadata for a named SQL result set mapping.
|
* Get the metadata for a named SQL result set mapping.
|
||||||
*
|
*
|
||||||
|
|
|
@ -39,6 +39,7 @@ import org.hibernate.mapping.ManyToOne;
|
||||||
import org.hibernate.mapping.OneToOne;
|
import org.hibernate.mapping.OneToOne;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.mapping.Property;
|
||||||
|
import org.hibernate.mapping.Selectable;
|
||||||
import org.hibernate.mapping.SimpleValue;
|
import org.hibernate.mapping.SimpleValue;
|
||||||
import org.hibernate.type.ForeignKeyDirection;
|
import org.hibernate.type.ForeignKeyDirection;
|
||||||
|
|
||||||
|
@ -212,11 +213,9 @@ public class OneToOneSecondPass implements SecondPass {
|
||||||
propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
|
propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value.setReferencedPropertyName( mappedBy );
|
||||||
|
|
||||||
// HHH-6813
|
// HHH-6813
|
||||||
// If otherSide's id is derived, do not set EntityType#uniqueKeyPropertyName.
|
|
||||||
// EntityType#isReferenceToPrimaryKey() assumes that, if it's set,
|
|
||||||
// a PK is not referenced. Example:
|
|
||||||
//
|
|
||||||
// Foo: @Id long id, @OneToOne(mappedBy="foo") Bar bar
|
// Foo: @Id long id, @OneToOne(mappedBy="foo") Bar bar
|
||||||
// Bar: @Id @OneToOne Foo foo
|
// Bar: @Id @OneToOne Foo foo
|
||||||
boolean referencesDerivedId = false;
|
boolean referencesDerivedId = false;
|
||||||
|
@ -227,8 +226,14 @@ public class OneToOneSecondPass implements SecondPass {
|
||||||
catch ( MappingException e ) {
|
catch ( MappingException e ) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
String referencedPropertyName = referencesDerivedId ? null : mappedBy;
|
boolean referenceToPrimaryKey = referencesDerivedId || mappedBy == null;
|
||||||
value.setReferencedPropertyName( referencedPropertyName );
|
value.setReferenceToPrimaryKey( referenceToPrimaryKey );
|
||||||
|
|
||||||
|
// If the other side is a derived ID, prevent an infinite
|
||||||
|
// loop of attempts to resolve identifiers.
|
||||||
|
if ( referencesDerivedId ) {
|
||||||
|
( (ManyToOne) otherSideProperty.getValue() ).setReferenceToPrimaryKey( false );
|
||||||
|
}
|
||||||
|
|
||||||
String propertyRef = value.getReferencedPropertyName();
|
String propertyRef = value.getReferencedPropertyName();
|
||||||
if ( propertyRef != null ) {
|
if ( propertyRef != null ) {
|
||||||
|
|
|
@ -1511,6 +1511,7 @@ public abstract class CollectionBinder {
|
||||||
( (ManyToOne) value ).setReferencedPropertyName( referencedPropertyName );
|
( (ManyToOne) value ).setReferencedPropertyName( referencedPropertyName );
|
||||||
mappings.addUniquePropertyReference( referencedEntity.getEntityName(), referencedPropertyName );
|
mappings.addUniquePropertyReference( referencedEntity.getEntityName(), referencedPropertyName );
|
||||||
}
|
}
|
||||||
|
( (ManyToOne) value ).setReferenceToPrimaryKey( referencedPropertyName == null );
|
||||||
value.createForeignKey();
|
value.createForeignKey();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -31,6 +31,8 @@ import javax.persistence.Access;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.JoinTable;
|
import javax.persistence.JoinTable;
|
||||||
|
import javax.persistence.NamedEntityGraph;
|
||||||
|
import javax.persistence.NamedEntityGraphs;
|
||||||
import javax.persistence.PrimaryKeyJoinColumn;
|
import javax.persistence.PrimaryKeyJoinColumn;
|
||||||
import javax.persistence.SecondaryTable;
|
import javax.persistence.SecondaryTable;
|
||||||
import javax.persistence.SecondaryTables;
|
import javax.persistence.SecondaryTables;
|
||||||
|
@ -83,7 +85,6 @@ import org.hibernate.cfg.ObjectNameSource;
|
||||||
import org.hibernate.cfg.PropertyHolder;
|
import org.hibernate.cfg.PropertyHolder;
|
||||||
import org.hibernate.cfg.UniqueConstraintHolder;
|
import org.hibernate.cfg.UniqueConstraintHolder;
|
||||||
import org.hibernate.engine.OptimisticLockStyle;
|
import org.hibernate.engine.OptimisticLockStyle;
|
||||||
import org.hibernate.engine.internal.Versioning;
|
|
||||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||||
import org.hibernate.engine.spi.FilterDefinition;
|
import org.hibernate.engine.spi.FilterDefinition;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
@ -159,8 +160,27 @@ public class EntityBinder {
|
||||||
this.annotatedClass = annotatedClass;
|
this.annotatedClass = annotatedClass;
|
||||||
bindEjb3Annotation( ejb3Ann );
|
bindEjb3Annotation( ejb3Ann );
|
||||||
bindHibernateAnnotation();
|
bindHibernateAnnotation();
|
||||||
|
processNamedEntityGraphs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processNamedEntityGraphs() {
|
||||||
|
processNamedEntityGraph( annotatedClass.getAnnotation( NamedEntityGraph.class ) );
|
||||||
|
final NamedEntityGraphs graphs = annotatedClass.getAnnotation( NamedEntityGraphs.class );
|
||||||
|
if ( graphs != null ) {
|
||||||
|
for ( NamedEntityGraph graph : graphs.value() ) {
|
||||||
|
processNamedEntityGraph( graph );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processNamedEntityGraph(NamedEntityGraph annotation) {
|
||||||
|
if ( annotation == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mappings.addNamedEntityGraphDefintion( new NamedEntityGraphDefinition( annotation, name, persistentClass.getEntityName() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("SimplifiableConditionalExpression")
|
@SuppressWarnings("SimplifiableConditionalExpression")
|
||||||
private void bindHibernateAnnotation() {
|
private void bindHibernateAnnotation() {
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.cfg.annotations;
|
||||||
|
|
||||||
|
import javax.persistence.NamedEntityGraph;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models the definition of a {@link NamedEntityGraph} annotation
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class NamedEntityGraphDefinition {
|
||||||
|
private final NamedEntityGraph annotation;
|
||||||
|
private final String jpaEntityName;
|
||||||
|
private final String entityName;
|
||||||
|
|
||||||
|
public NamedEntityGraphDefinition(NamedEntityGraph annotation, String jpaEntityName, String entityName) {
|
||||||
|
this.annotation = annotation;
|
||||||
|
this.jpaEntityName = jpaEntityName;
|
||||||
|
this.entityName = entityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRegisteredName() {
|
||||||
|
return jpaEntityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJpaEntityName() {
|
||||||
|
return jpaEntityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEntityName() {
|
||||||
|
return entityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NamedEntityGraph getAnnotation() {
|
||||||
|
return annotation;
|
||||||
|
}
|
||||||
|
}
|
|
@ -299,6 +299,12 @@ public abstract class Dialect implements ConversionContext {
|
||||||
|
|
||||||
// database type mapping support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// database type mapping support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows the Dialect to contribute additional types
|
||||||
|
*
|
||||||
|
* @param typeContributions Callback to contribute the types
|
||||||
|
* @param serviceRegistry The service registry
|
||||||
|
*/
|
||||||
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||||
// by default, nothing to do
|
// by default, nothing to do
|
||||||
}
|
}
|
||||||
|
@ -1362,7 +1368,7 @@ public abstract class Dialect implements ConversionContext {
|
||||||
* @param lockOptions the lock options to apply
|
* @param lockOptions the lock options to apply
|
||||||
* @return The appropriate <tt>FOR UPDATE OF column_list</tt> clause string.
|
* @return The appropriate <tt>FOR UPDATE OF column_list</tt> clause string.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( {"unchecked"})
|
@SuppressWarnings({"unchecked", "UnusedParameters"})
|
||||||
public String getForUpdateString(String aliases, LockOptions lockOptions) {
|
public String getForUpdateString(String aliases, LockOptions lockOptions) {
|
||||||
LockMode lockMode = lockOptions.getLockMode();
|
LockMode lockMode = lockOptions.getLockMode();
|
||||||
final Iterator<Map.Entry<String, LockMode>> itr = lockOptions.getAliasLockIterator();
|
final Iterator<Map.Entry<String, LockMode>> itr = lockOptions.getAliasLockIterator();
|
||||||
|
@ -1612,6 +1618,7 @@ public abstract class Dialect implements ConversionContext {
|
||||||
*
|
*
|
||||||
* @throws SQLException Indicates problems registering the param.
|
* @throws SQLException Indicates problems registering the param.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("UnusedParameters")
|
||||||
public int registerResultSetOutParameter(CallableStatement statement, String name) throws SQLException {
|
public int registerResultSetOutParameter(CallableStatement statement, String name) throws SQLException {
|
||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
getClass().getName() +
|
getClass().getName() +
|
||||||
|
@ -1644,6 +1651,7 @@ public abstract class Dialect implements ConversionContext {
|
||||||
*
|
*
|
||||||
* @throws SQLException Indicates problems extracting the result set.
|
* @throws SQLException Indicates problems extracting the result set.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("UnusedParameters")
|
||||||
public ResultSet getResultSet(CallableStatement statement, int position) throws SQLException {
|
public ResultSet getResultSet(CallableStatement statement, int position) throws SQLException {
|
||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
getClass().getName() + " does not support resultsets via stored procedures"
|
getClass().getName() + " does not support resultsets via stored procedures"
|
||||||
|
@ -1661,6 +1669,7 @@ public abstract class Dialect implements ConversionContext {
|
||||||
*
|
*
|
||||||
* @throws SQLException Indicates problems extracting the result set.
|
* @throws SQLException Indicates problems extracting the result set.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("UnusedParameters")
|
||||||
public ResultSet getResultSet(CallableStatement statement, String name) throws SQLException {
|
public ResultSet getResultSet(CallableStatement statement, String name) throws SQLException {
|
||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
getClass().getName() + " does not support resultsets via stored procedures"
|
getClass().getName() + " does not support resultsets via stored procedures"
|
||||||
|
|
|
@ -40,7 +40,11 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public class DialectResolverInitiator implements StandardServiceInitiator<DialectResolver> {
|
public class DialectResolverInitiator implements StandardServiceInitiator<DialectResolver> {
|
||||||
|
/**
|
||||||
|
* Singleton access
|
||||||
|
*/
|
||||||
public static final DialectResolverInitiator INSTANCE = new DialectResolverInitiator();
|
public static final DialectResolverInitiator INSTANCE = new DialectResolverInitiator();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -45,9 +45,9 @@ import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport;
|
||||||
import org.hibernate.engine.jdbc.env.spi.SQLStateType;
|
import org.hibernate.engine.jdbc.env.spi.SQLStateType;
|
||||||
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
|
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
|
||||||
import org.hibernate.engine.jdbc.env.spi.StandardQualifiedObjectNameSupportImpl;
|
import org.hibernate.engine.jdbc.env.spi.StandardQualifiedObjectNameSupportImpl;
|
||||||
import org.hibernate.engine.jdbc.internal.TypeInfo;
|
|
||||||
import org.hibernate.engine.jdbc.internal.TypeInfoExtracter;
|
import org.hibernate.engine.jdbc.internal.TypeInfoExtracter;
|
||||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||||
|
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||||
import org.hibernate.exception.internal.SQLExceptionTypeDelegate;
|
import org.hibernate.exception.internal.SQLExceptionTypeDelegate;
|
||||||
import org.hibernate.exception.internal.SQLStateConversionDelegate;
|
import org.hibernate.exception.internal.SQLStateConversionDelegate;
|
||||||
import org.hibernate.exception.internal.StandardSQLExceptionConverter;
|
import org.hibernate.exception.internal.StandardSQLExceptionConverter;
|
||||||
|
|
|
@ -26,8 +26,8 @@ package org.hibernate.engine.jdbc.env.spi;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.jdbc.internal.TypeInfo;
|
|
||||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||||
|
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||||
import org.hibernate.service.Service;
|
import org.hibernate.service.Service;
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,6 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
||||||
@Override
|
@Override
|
||||||
public void configure(Map configValues) {
|
public void configure(Map configValues) {
|
||||||
this.jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
this.jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
||||||
|
|
||||||
this.connectionProvider = serviceRegistry.getService( ConnectionProvider.class );
|
this.connectionProvider = serviceRegistry.getService( ConnectionProvider.class );
|
||||||
final boolean showSQL = ConfigurationHelper.getBoolean( Environment.SHOW_SQL, configValues, false );
|
final boolean showSQL = ConfigurationHelper.getBoolean( Environment.SHOW_SQL, configValues, false );
|
||||||
final boolean formatSQL = ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, configValues, false );
|
final boolean formatSQL = ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, configValues, false );
|
||||||
|
|
|
@ -30,6 +30,9 @@ import java.util.LinkedHashSet;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||||
|
import org.hibernate.engine.jdbc.spi.TypeNullability;
|
||||||
|
import org.hibernate.engine.jdbc.spi.TypeSearchability;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@ package org.hibernate.engine.jdbc.spi;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A no-op adapter for ConnectionObserver.
|
||||||
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class ConnectionObserverAdapter implements ConnectionObserver {
|
public class ConnectionObserverAdapter implements ConnectionObserver {
|
||||||
|
|
|
@ -154,6 +154,7 @@ public interface JdbcCoordinator extends Serializable {
|
||||||
* @throws org.hibernate.TransactionException Indicates the time out period has already been exceeded.
|
* @throws org.hibernate.TransactionException Indicates the time out period has already been exceeded.
|
||||||
*/
|
*/
|
||||||
public int determineRemainingTransactionTimeOutPeriod();
|
public int determineRemainingTransactionTimeOutPeriod();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a JDBC statement.
|
* Register a JDBC statement.
|
||||||
*
|
*
|
||||||
|
@ -200,8 +201,14 @@ public interface JdbcCoordinator extends Serializable {
|
||||||
*/
|
*/
|
||||||
public void releaseResources();
|
public void releaseResources();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable connection releases
|
||||||
|
*/
|
||||||
public void enableReleases();
|
public void enableReleases();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable connection releases
|
||||||
|
*/
|
||||||
public void disableReleases();
|
public void disableReleases();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -211,5 +218,10 @@ public interface JdbcCoordinator extends Serializable {
|
||||||
*/
|
*/
|
||||||
public void registerLastQuery(Statement statement);
|
public void registerLastQuery(Statement statement);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can this coordinator be serialized?
|
||||||
|
*
|
||||||
|
* @return {@code true} indicates the coordinator can be serialized.
|
||||||
|
*/
|
||||||
public boolean isReadyForSerialization();
|
public boolean isReadyForSerialization();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.engine.jdbc.spi;
|
package org.hibernate.engine.jdbc.spi;
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
|
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||||
import org.hibernate.engine.jdbc.LobCreator;
|
import org.hibernate.engine.jdbc.LobCreator;
|
||||||
|
@ -90,7 +88,7 @@ public interface JdbcServices extends Service {
|
||||||
public LobCreator getLobCreator(LobCreationContext lobCreationContext);
|
public LobCreator getLobCreator(LobCreationContext lobCreationContext);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain service for wrapping a {@link ResultSet} in a "column name cache" wrapper.
|
* Obtain service for wrapping a {@link java.sql.ResultSet} in a "column name cache" wrapper.
|
||||||
* @return The ResultSet wrapper.
|
* @return The ResultSet wrapper.
|
||||||
*/
|
*/
|
||||||
public ResultSetWrapper getResultSetWrapper();
|
public ResultSetWrapper getResultSetWrapper();
|
||||||
|
|
|
@ -79,13 +79,34 @@ public interface LogicalConnectionImplementor extends LogicalConnection {
|
||||||
*/
|
*/
|
||||||
public void manualReconnect(Connection suppliedConnection);
|
public void manualReconnect(Connection suppliedConnection);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an aggressive release
|
||||||
|
*/
|
||||||
public void aggressiveRelease();
|
public void aggressiveRelease();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release any held connection.
|
||||||
|
*
|
||||||
|
* @throws JDBCException Indicates a problem releasing the connection
|
||||||
|
*/
|
||||||
public void releaseConnection() throws JDBCException;
|
public void releaseConnection() throws JDBCException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this logical connection in auto-commit mode?
|
||||||
|
*
|
||||||
|
* @return {@code true} if auto-commit
|
||||||
|
*/
|
||||||
public boolean isAutoCommit();
|
public boolean isAutoCommit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to notify all registered observers of a connection being prepared.
|
||||||
|
*/
|
||||||
public void notifyObserversStatementPrepared();
|
public void notifyObserversStatementPrepared();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this logical connection wrap a user/application supplied connection?
|
||||||
|
*
|
||||||
|
* @return {@code true} if the underlying connection was user supplied.
|
||||||
|
*/
|
||||||
public boolean isUserSuppliedConnection();
|
public boolean isUserSuppliedConnection();
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,74 +35,83 @@ import java.sql.Statement;
|
||||||
* TODO: This could eventually utilize the new Return interface. It would be
|
* TODO: This could eventually utilize the new Return interface. It would be
|
||||||
* great to have a common API shared.
|
* great to have a common API shared.
|
||||||
*
|
*
|
||||||
|
* Generally the methods here dealing with CallableStatement are extremely limited, relying on the legacy
|
||||||
|
*
|
||||||
|
*
|
||||||
* @author Brett Meyer
|
* @author Brett Meyer
|
||||||
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface ResultSetReturn {
|
public interface ResultSetReturn {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the ResultSet from the statement. If user passes {@link CallableStatement}
|
* Extract the ResultSet from the PreparedStatement.
|
||||||
* reference, method calls {@link #extract(CallableStatement)} internally.
|
* <p/>
|
||||||
|
* If user passes {@link CallableStatement} reference, this method calls {@link #extract(CallableStatement)}
|
||||||
|
* internally. Otherwise, generally speaking, {@link java.sql.PreparedStatement#executeQuery()} is called
|
||||||
*
|
*
|
||||||
* @param statement
|
* @param statement The PreparedStatement from which to extract the ResultSet
|
||||||
*
|
*
|
||||||
* @return the ResultSet
|
* @return The extracted ResultSet
|
||||||
*/
|
*/
|
||||||
public ResultSet extract(PreparedStatement statement);
|
public ResultSet extract(PreparedStatement statement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the ResultSet from the statement.
|
* Extract the ResultSet from the CallableStatement. Note that this is the limited legacy form which delegates to
|
||||||
|
* {@link org.hibernate.dialect.Dialect#getResultSet}. Better option is to integrate
|
||||||
|
* {@link org.hibernate.procedure.ProcedureCall}-like hooks
|
||||||
*
|
*
|
||||||
* @param statement
|
* @param callableStatement The CallableStatement from which to extract the ResultSet
|
||||||
*
|
*
|
||||||
* @return the ResultSet
|
* @return The extracted ResultSet
|
||||||
*/
|
*/
|
||||||
public ResultSet extract( CallableStatement statement );
|
public ResultSet extract(CallableStatement callableStatement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the ResultSet from the statement.
|
* Performs the given SQL statement, expecting a ResultSet in return
|
||||||
*
|
*
|
||||||
* @param statement
|
* @param statement The JDBC Statement object to use
|
||||||
* @param sql
|
* @param sql The SQL to execute
|
||||||
*
|
*
|
||||||
* @return the ResultSet
|
* @return The resulting ResultSet
|
||||||
*/
|
*/
|
||||||
public ResultSet extract(Statement statement, String sql);
|
public ResultSet extract(Statement statement, String sql);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the Statement query and, if results in a ResultSet, extract it.
|
* Execute the PreparedStatement return its first ResultSet, if any. If there is no ResultSet, returns {@code null}
|
||||||
*
|
*
|
||||||
* @param statement
|
* @param statement The PreparedStatement to execute
|
||||||
*
|
*
|
||||||
* @return the ResultSet
|
* @return The extracted ResultSet, or {@code null}
|
||||||
*/
|
*/
|
||||||
public ResultSet execute(PreparedStatement statement);
|
public ResultSet execute(PreparedStatement statement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the Statement query and, if results in a ResultSet, extract it.
|
* Performs the given SQL statement, returning its first ResultSet, if any. If there is no ResultSet,
|
||||||
|
* returns {@code null}
|
||||||
*
|
*
|
||||||
* @param statement
|
* @param statement The JDBC Statement object to use
|
||||||
* @param sql
|
* @param sql The SQL to execute
|
||||||
*
|
*
|
||||||
* @return the ResultSet
|
* @return The extracted ResultSet, or {@code null}
|
||||||
*/
|
*/
|
||||||
public ResultSet execute(Statement statement, String sql);
|
public ResultSet execute(Statement statement, String sql);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the Statement queryUpdate.
|
* Execute the PreparedStatement, returning its "affected row count".
|
||||||
*
|
*
|
||||||
* @param statement
|
* @param statement The PreparedStatement to execute
|
||||||
*
|
*
|
||||||
* @return int
|
* @return The {@link java.sql.PreparedStatement#executeUpdate()} result
|
||||||
*/
|
*/
|
||||||
public int executeUpdate(PreparedStatement statement);
|
public int executeUpdate(PreparedStatement statement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the Statement query and, if results in a ResultSet, extract it.
|
* Execute the given SQL statement returning its "affected row count".
|
||||||
*
|
*
|
||||||
* @param statement
|
* @param statement The JDBC Statement object to use
|
||||||
* @param sql
|
* @param sql The SQL to execute
|
||||||
*
|
*
|
||||||
* @return the ResultSet
|
* @return The {@link java.sql.PreparedStatement#executeUpdate(String)} result
|
||||||
*/
|
*/
|
||||||
public int executeUpdate(Statement statement, String sql);
|
public int executeUpdate(Statement statement, String sql);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,12 @@ public class SqlStatementLogger {
|
||||||
logStatement( statement, FormatStyle.BASIC.getFormatter() );
|
logStatement( statement, FormatStyle.BASIC.getFormatter() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a SQL statement string using the specified formatter
|
||||||
|
*
|
||||||
|
* @param statement The SQL statement.
|
||||||
|
* @param formatter The formatter to use.
|
||||||
|
*/
|
||||||
public void logStatement(String statement, Formatter formatter) {
|
public void logStatement(String statement, Formatter formatter) {
|
||||||
if ( format ) {
|
if ( format ) {
|
||||||
if ( logToStdout || LOG.isDebugEnabled() ) {
|
if ( logToStdout || LOG.isDebugEnabled() ) {
|
||||||
|
|
|
@ -38,8 +38,6 @@ public interface StatementPreparer {
|
||||||
/**
|
/**
|
||||||
* Create a statement.
|
* Create a statement.
|
||||||
*
|
*
|
||||||
* @param sql The SQL the statement to be created
|
|
||||||
*
|
|
||||||
* @return the statement
|
* @return the statement
|
||||||
*/
|
*/
|
||||||
public Statement createStatement();
|
public Statement createStatement();
|
||||||
|
@ -64,14 +62,15 @@ public interface StatementPreparer {
|
||||||
public PreparedStatement prepareStatement(String sql, boolean isCallable);
|
public PreparedStatement prepareStatement(String sql, boolean isCallable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a prepared statement to use for inserting using JDBC3
|
* Prepare an INSERT statement, specifying how auto-generated (by the database) keys should be handled. Really this
|
||||||
* {@link java.sql.PreparedStatement#getGeneratedKeys getGeneratedKeys} processing.
|
* is a boolean, but JDBC opted to define it instead using 2 int constants:<ul>
|
||||||
*
|
|
||||||
* @param sql - the SQL for the statement to be prepared
|
|
||||||
* @param autoGeneratedKeys - a flag indicating whether auto-generated keys should be returned; one of<ul>
|
|
||||||
* <li>{@link PreparedStatement#RETURN_GENERATED_KEYS}</li>
|
* <li>{@link PreparedStatement#RETURN_GENERATED_KEYS}</li>
|
||||||
* <li>{@link PreparedStatement#NO_GENERATED_KEYS}</li>
|
* <li>{@link PreparedStatement#NO_GENERATED_KEYS}</li>
|
||||||
* </li>
|
* </ul>
|
||||||
|
* Generated keys are accessed afterwards via {@link java.sql.PreparedStatement#getGeneratedKeys}
|
||||||
|
*
|
||||||
|
* @param sql The INSERT SQL
|
||||||
|
* @param autoGeneratedKeys The autoGeneratedKeys flag
|
||||||
*
|
*
|
||||||
* @return the prepared statement
|
* @return the prepared statement
|
||||||
*
|
*
|
||||||
|
@ -79,10 +78,9 @@ public interface StatementPreparer {
|
||||||
*/
|
*/
|
||||||
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys);
|
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a prepared statement to use for inserting using JDBC3
|
* Prepare an INSERT statement, specifying columns which are auto-generated values to be returned.
|
||||||
* {@link java.sql.PreparedStatement#getGeneratedKeys getGeneratedKeys} processing.
|
* Generated keys are accessed afterwards via {@link java.sql.PreparedStatement#getGeneratedKeys}
|
||||||
*
|
*
|
||||||
* @param sql - the SQL for the statement to be prepared
|
* @param sql - the SQL for the statement to be prepared
|
||||||
* @param columnNames The name of the columns to be returned in the generated keys result set.
|
* @param columnNames The name of the columns to be returned in the generated keys result set.
|
||||||
|
|
|
@ -21,15 +21,30 @@
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.engine.jdbc.internal;
|
package org.hibernate.engine.jdbc.spi;
|
||||||
|
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Models type info extracted from {@link java.sql.DatabaseMetaData#getTypeInfo()}
|
* Models type info extracted from {@link java.sql.DatabaseMetaData#getTypeInfo()}
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
public class TypeInfo {
|
public class TypeInfo {
|
||||||
|
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||||
|
CoreMessageLogger.class,
|
||||||
|
TypeInfo.class.getName()
|
||||||
|
);
|
||||||
|
|
||||||
private final String typeName;
|
private final String typeName;
|
||||||
private final int jdbcTypeCode;
|
private final int jdbcTypeCode;
|
||||||
private final String[] createParams;
|
private final String[] createParams;
|
||||||
|
@ -73,6 +88,64 @@ public class TypeInfo {
|
||||||
this.nullability = nullability;
|
this.nullability = nullability;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the type information from the JDBC driver's DatabaseMetaData
|
||||||
|
*
|
||||||
|
* @param metaData The JDBC metadata
|
||||||
|
*
|
||||||
|
* @return The extracted type info
|
||||||
|
*/
|
||||||
|
public static LinkedHashSet<TypeInfo> extractTypeInfo(DatabaseMetaData metaData) {
|
||||||
|
final LinkedHashSet<TypeInfo> typeInfoSet = new LinkedHashSet<TypeInfo>();
|
||||||
|
try {
|
||||||
|
final ResultSet resultSet = metaData.getTypeInfo();
|
||||||
|
try {
|
||||||
|
while ( resultSet.next() ) {
|
||||||
|
typeInfoSet.add(
|
||||||
|
new TypeInfo(
|
||||||
|
resultSet.getString( "TYPE_NAME" ),
|
||||||
|
resultSet.getInt( "DATA_TYPE" ),
|
||||||
|
interpretCreateParams( resultSet.getString( "CREATE_PARAMS" ) ),
|
||||||
|
resultSet.getBoolean( "UNSIGNED_ATTRIBUTE" ),
|
||||||
|
resultSet.getInt( "PRECISION" ),
|
||||||
|
resultSet.getShort( "MINIMUM_SCALE" ),
|
||||||
|
resultSet.getShort( "MAXIMUM_SCALE" ),
|
||||||
|
resultSet.getBoolean( "FIXED_PREC_SCALE" ),
|
||||||
|
resultSet.getString( "LITERAL_PREFIX" ),
|
||||||
|
resultSet.getString( "LITERAL_SUFFIX" ),
|
||||||
|
resultSet.getBoolean( "CASE_SENSITIVE" ),
|
||||||
|
TypeSearchability.interpret( resultSet.getShort( "SEARCHABLE" ) ),
|
||||||
|
TypeNullability.interpret( resultSet.getShort( "NULLABLE" ) )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( SQLException e ) {
|
||||||
|
LOG.unableToAccessTypeInfoResultSet( e.toString() );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
resultSet.close();
|
||||||
|
}
|
||||||
|
catch ( SQLException e ) {
|
||||||
|
LOG.unableToReleaseTypeInfoResultSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( SQLException e ) {
|
||||||
|
LOG.unableToRetrieveTypeInfoResultSet( e.toString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeInfoSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] interpretCreateParams(String value) {
|
||||||
|
if ( value == null || value.length() == 0 ) {
|
||||||
|
return ArrayHelper.EMPTY_STRING_ARRAY;
|
||||||
|
}
|
||||||
|
return value.split( "," );
|
||||||
|
}
|
||||||
|
|
||||||
public String getTypeName() {
|
public String getTypeName() {
|
||||||
return typeName;
|
return typeName;
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.engine.jdbc.internal;
|
package org.hibernate.engine.jdbc.spi;
|
||||||
|
|
||||||
import java.sql.DatabaseMetaData;
|
import java.sql.DatabaseMetaData;
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.engine.jdbc.internal;
|
package org.hibernate.engine.jdbc.spi;
|
||||||
|
|
||||||
import java.sql.DatabaseMetaData;
|
import java.sql.DatabaseMetaData;
|
||||||
|
|
|
@ -30,7 +30,13 @@ import org.hibernate.HibernateException;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class JndiException extends HibernateException {
|
public class JndiException extends HibernateException {
|
||||||
public JndiException(String string, Throwable root) {
|
/**
|
||||||
super( string, root );
|
* Constructs a JndiException
|
||||||
|
*
|
||||||
|
* @param message Message explaining the exception condition
|
||||||
|
* @param cause The underlying cause
|
||||||
|
*/
|
||||||
|
public JndiException(String message, Throwable cause) {
|
||||||
|
super( message, cause );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,13 @@ import org.hibernate.HibernateException;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class JndiNameException extends HibernateException {
|
public class JndiNameException extends HibernateException {
|
||||||
public JndiNameException(String string, Throwable root) {
|
/**
|
||||||
super( string, root );
|
* Constructs a JndiNameException
|
||||||
|
*
|
||||||
|
* @param message Message explaining the exception condition
|
||||||
|
* @param cause The underlying cause.
|
||||||
|
*/
|
||||||
|
public JndiNameException(String message, Throwable cause) {
|
||||||
|
super( message, cause );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ package org.hibernate.engine.jndi.internal;
|
||||||
|
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
import javax.naming.Context;
|
import javax.naming.Context;
|
||||||
import javax.naming.InitialContext;
|
import javax.naming.InitialContext;
|
||||||
import javax.naming.InvalidNameException;
|
import javax.naming.InvalidNameException;
|
||||||
|
@ -36,11 +38,11 @@ import javax.naming.event.NamespaceChangeListener;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.engine.jndi.JndiException;
|
import org.hibernate.engine.jndi.JndiException;
|
||||||
import org.hibernate.engine.jndi.JndiNameException;
|
import org.hibernate.engine.jndi.JndiNameException;
|
||||||
import org.hibernate.engine.jndi.spi.JndiService;
|
import org.hibernate.engine.jndi.spi.JndiService;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
import org.hibernate.internal.util.jndi.JndiHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard implementation of JNDI services.
|
* Standard implementation of JNDI services.
|
||||||
|
@ -48,19 +50,66 @@ import org.hibernate.internal.util.jndi.JndiHelper;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class JndiServiceImpl implements JndiService {
|
public class JndiServiceImpl implements JndiService {
|
||||||
|
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, JndiServiceImpl.class.getName());
|
CoreMessageLogger.class,
|
||||||
|
JndiServiceImpl.class.getName()
|
||||||
|
);
|
||||||
|
|
||||||
private final Hashtable initialContextSettings;
|
private final Hashtable initialContextSettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a JndiServiceImpl
|
||||||
|
*
|
||||||
|
* @param configurationValues Map of configuration settings, some of which apply to JNDI support.
|
||||||
|
*/
|
||||||
public JndiServiceImpl(Map configurationValues) {
|
public JndiServiceImpl(Map configurationValues) {
|
||||||
this.initialContextSettings = JndiHelper.extractJndiProperties( configurationValues );
|
this.initialContextSettings = extractJndiProperties( configurationValues );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a hodgepodge of properties, extract out the ones relevant for JNDI interaction.
|
||||||
|
*
|
||||||
|
* @param configurationValues The map of config values
|
||||||
|
*
|
||||||
|
* @return The extracted JNDI specific properties.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({ "unchecked" })
|
||||||
|
public static Properties extractJndiProperties(Map configurationValues) {
|
||||||
|
final Properties jndiProperties = new Properties();
|
||||||
|
|
||||||
|
for ( Map.Entry entry : (Set<Map.Entry>) configurationValues.entrySet() ) {
|
||||||
|
if ( !String.class.isInstance( entry.getKey() ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final String propertyName = (String) entry.getKey();
|
||||||
|
final Object propertyValue = entry.getValue();
|
||||||
|
if ( propertyName.startsWith( Environment.JNDI_PREFIX ) ) {
|
||||||
|
// write the IntialContextFactory class and provider url to the result only if they are
|
||||||
|
// non-null; this allows the environmental defaults (if any) to remain in effect
|
||||||
|
if ( Environment.JNDI_CLASS.equals( propertyName ) ) {
|
||||||
|
if ( propertyValue != null ) {
|
||||||
|
jndiProperties.put( Context.INITIAL_CONTEXT_FACTORY, propertyValue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( Environment.JNDI_URL.equals( propertyName ) ) {
|
||||||
|
if ( propertyValue != null ) {
|
||||||
|
jndiProperties.put( Context.PROVIDER_URL, propertyValue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final String passThruPropertyname = propertyName.substring( Environment.JNDI_PREFIX.length() + 1 );
|
||||||
|
jndiProperties.put( passThruPropertyname, propertyValue );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return jndiProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object locate(String jndiName) {
|
public Object locate(String jndiName) {
|
||||||
InitialContext initialContext = buildInitialContext();
|
final InitialContext initialContext = buildInitialContext();
|
||||||
Name name = parseName( jndiName, initialContext );
|
final Name name = parseName( jndiName, initialContext );
|
||||||
try {
|
try {
|
||||||
return initialContext.lookup( name );
|
return initialContext.lookup( name );
|
||||||
}
|
}
|
||||||
|
@ -104,8 +153,8 @@ public class JndiServiceImpl implements JndiService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bind(String jndiName, Object value) {
|
public void bind(String jndiName, Object value) {
|
||||||
InitialContext initialContext = buildInitialContext();
|
final InitialContext initialContext = buildInitialContext();
|
||||||
Name name = parseName( jndiName, initialContext );
|
final Name name = parseName( jndiName, initialContext );
|
||||||
try {
|
try {
|
||||||
bind( name, value, initialContext );
|
bind( name, value, initialContext );
|
||||||
}
|
}
|
||||||
|
@ -172,8 +221,8 @@ public class JndiServiceImpl implements JndiService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unbind(String jndiName) {
|
public void unbind(String jndiName) {
|
||||||
InitialContext initialContext = buildInitialContext();
|
final InitialContext initialContext = buildInitialContext();
|
||||||
Name name = parseName( jndiName, initialContext );
|
final Name name = parseName( jndiName, initialContext );
|
||||||
try {
|
try {
|
||||||
initialContext.unbind( name );
|
initialContext.unbind( name );
|
||||||
}
|
}
|
||||||
|
@ -187,8 +236,8 @@ public class JndiServiceImpl implements JndiService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addListener(String jndiName, NamespaceChangeListener listener) {
|
public void addListener(String jndiName, NamespaceChangeListener listener) {
|
||||||
InitialContext initialContext = buildInitialContext();
|
final InitialContext initialContext = buildInitialContext();
|
||||||
Name name = parseName( jndiName, initialContext );
|
final Name name = parseName( jndiName, initialContext );
|
||||||
try {
|
try {
|
||||||
( (EventContext) initialContext ).addNamingListener( name, EventContext.OBJECT_SCOPE, listener );
|
( (EventContext) initialContext ).addNamingListener( name, EventContext.OBJECT_SCOPE, listener );
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,9 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class JndiServiceInitiator implements StandardServiceInitiator<JndiService> {
|
public class JndiServiceInitiator implements StandardServiceInitiator<JndiService> {
|
||||||
|
/**
|
||||||
|
* Singleton access
|
||||||
|
*/
|
||||||
public static final JndiServiceInitiator INSTANCE = new JndiServiceInitiator();
|
public static final JndiServiceInitiator INSTANCE = new JndiServiceInitiator();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
/**
|
||||||
|
* Internal contracts defining the JNDI support within Hibernate
|
||||||
|
*/
|
||||||
|
package org.hibernate.engine.jndi.internal;
|
|
@ -0,0 +1,4 @@
|
||||||
|
/**
|
||||||
|
* Support for JNDI within Hibernate
|
||||||
|
*/
|
||||||
|
package org.hibernate.engine.jndi;
|
|
@ -0,0 +1,4 @@
|
||||||
|
/**
|
||||||
|
* The SPI contracts for Hibernate JNDI support
|
||||||
|
*/
|
||||||
|
package org.hibernate.engine.jndi.spi;
|
|
@ -27,6 +27,7 @@ import javax.transaction.SystemException;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.TransactionException;
|
import org.hibernate.TransactionException;
|
||||||
import org.hibernate.cfg.Settings;
|
import org.hibernate.cfg.Settings;
|
||||||
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
|
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
|
||||||
|
@ -56,9 +57,9 @@ public class SynchronizationCallbackCoordinatorImpl implements SynchronizationCa
|
||||||
private AfterCompletionAction afterCompletionAction;
|
private AfterCompletionAction afterCompletionAction;
|
||||||
private ExceptionMapper exceptionMapper;
|
private ExceptionMapper exceptionMapper;
|
||||||
|
|
||||||
private long registrationThreadId;
|
private volatile long registrationThreadId;
|
||||||
private final int NO_STATUS = -1;
|
private final int NO_STATUS = -1;
|
||||||
private int delayedCompletionHandlingStatus;
|
private volatile int delayedCompletionHandlingStatus;
|
||||||
|
|
||||||
public SynchronizationCallbackCoordinatorImpl(TransactionCoordinator transactionCoordinator) {
|
public SynchronizationCallbackCoordinatorImpl(TransactionCoordinator transactionCoordinator) {
|
||||||
this.transactionCoordinator = transactionCoordinator;
|
this.transactionCoordinator = transactionCoordinator;
|
||||||
|
@ -154,11 +155,12 @@ public class SynchronizationCallbackCoordinatorImpl implements SynchronizationCa
|
||||||
if ( delayedCompletionHandlingStatus != NO_STATUS ) {
|
if ( delayedCompletionHandlingStatus != NO_STATUS ) {
|
||||||
doAfterCompletion( delayedCompletionHandlingStatus );
|
doAfterCompletion( delayedCompletionHandlingStatus );
|
||||||
delayedCompletionHandlingStatus = NO_STATUS;
|
delayedCompletionHandlingStatus = NO_STATUS;
|
||||||
|
throw new HibernateException("Transaction was rolled back in a different thread!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doAfterCompletion(int status) {
|
private void doAfterCompletion(int status) {
|
||||||
LOG.tracev( "Transaction after completion callback [status={0}]", status );
|
LOG.tracev( "Transaction afterCompletion callback [status={0}]", status );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
afterCompletionAction.doAction( transactionCoordinator, status );
|
afterCompletionAction.doAction( transactionCoordinator, status );
|
||||||
|
|
|
@ -74,9 +74,11 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
|
||||||
source
|
source
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( foundInCache && traceEnabled ) {
|
if ( foundInCache ) {
|
||||||
|
if ( traceEnabled ) {
|
||||||
LOG.trace( "Collection initialized from cache" );
|
LOG.trace( "Collection initialized from cache" );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if ( traceEnabled ) {
|
if ( traceEnabled ) {
|
||||||
LOG.trace( "Collection not cached" );
|
LOG.trace( "Collection not cached" );
|
||||||
|
|
|
@ -94,6 +94,8 @@ public class JoinProcessor implements SqlTokenTypes {
|
||||||
return JoinType.INNER_JOIN;
|
return JoinType.INNER_JOIN;
|
||||||
case RIGHT_OUTER:
|
case RIGHT_OUTER:
|
||||||
return JoinType.RIGHT_OUTER_JOIN;
|
return JoinType.RIGHT_OUTER_JOIN;
|
||||||
|
case FULL:
|
||||||
|
return JoinType.FULL_JOIN;
|
||||||
default:
|
default:
|
||||||
throw new AssertionFailure( "undefined join type " + astJoinType );
|
throw new AssertionFailure( "undefined join type " + astJoinType );
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,17 +23,16 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.internal.util.jndi;
|
package org.hibernate.internal.util.jndi;
|
||||||
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
import javax.naming.Context;
|
import javax.naming.Context;
|
||||||
import javax.naming.InitialContext;
|
import javax.naming.InitialContext;
|
||||||
import javax.naming.Name;
|
import javax.naming.Name;
|
||||||
import javax.naming.NameNotFoundException;
|
import javax.naming.NameNotFoundException;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.engine.jndi.internal.JndiServiceImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for dealing with JNDI.
|
* Helper for dealing with JNDI.
|
||||||
|
@ -54,42 +53,12 @@ public final class JndiHelper {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
public static Properties extractJndiProperties(Map configurationValues) {
|
public static Properties extractJndiProperties(Map configurationValues) {
|
||||||
final Properties jndiProperties = new Properties();
|
return JndiServiceImpl.extractJndiProperties( configurationValues );
|
||||||
|
|
||||||
for ( Map.Entry entry : (Set<Map.Entry>) configurationValues.entrySet() ) {
|
|
||||||
if ( !String.class.isInstance( entry.getKey() ) ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final String propertyName = (String) entry.getKey();
|
|
||||||
final Object propertyValue = entry.getValue();
|
|
||||||
if ( propertyName.startsWith( Environment.JNDI_PREFIX ) ) {
|
|
||||||
// write the IntialContextFactory class and provider url to the result only if they are
|
|
||||||
// non-null; this allows the environmental defaults (if any) to remain in effect
|
|
||||||
if ( Environment.JNDI_CLASS.equals( propertyName ) ) {
|
|
||||||
if ( propertyValue != null ) {
|
|
||||||
jndiProperties.put( Context.INITIAL_CONTEXT_FACTORY, propertyValue );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( Environment.JNDI_URL.equals( propertyName ) ) {
|
|
||||||
if ( propertyValue != null ) {
|
|
||||||
jndiProperties.put( Context.PROVIDER_URL, propertyValue );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final String passThruPropertyname = propertyName.substring( Environment.JNDI_PREFIX.length() + 1 );
|
|
||||||
jndiProperties.put( passThruPropertyname, propertyValue );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return jndiProperties;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static InitialContext getInitialContext(Properties props) throws NamingException {
|
public static InitialContext getInitialContext(Properties props) throws NamingException {
|
||||||
Hashtable hash = extractJndiProperties(props);
|
final Hashtable hash = extractJndiProperties( props );
|
||||||
return hash.size()==0 ?
|
return hash.size() == 0 ? new InitialContext() : new InitialContext( hash );
|
||||||
new InitialContext() :
|
|
||||||
new InitialContext(hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,7 +77,7 @@ public final class JndiHelper {
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
Name n = ctx.getNameParser( "" ).parse( name );
|
Name n = ctx.getNameParser( "" ).parse( name );
|
||||||
while ( n.size() > 1 ) {
|
while ( n.size() > 1 ) {
|
||||||
String ctxName = n.get(0);
|
final String ctxName = n.get( 0 );
|
||||||
|
|
||||||
Context subctx = null;
|
Context subctx = null;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -59,11 +59,8 @@ public abstract class AbstractJoinableAssociationImpl implements JoinableAssocia
|
||||||
boolean hasRestriction,
|
boolean hasRestriction,
|
||||||
Map<String, Filter> enabledFilters) throws MappingException {
|
Map<String, Filter> enabledFilters) throws MappingException {
|
||||||
this.propertyPath = currentFetch.getPropertyPath();
|
this.propertyPath = currentFetch.getPropertyPath();
|
||||||
final OuterJoinLoadable ownerPersister = (OuterJoinLoadable) currentFetch.getOwner().retrieveFetchSourcePersister();
|
|
||||||
final int propertyNumber = ownerPersister.getEntityMetamodel().getPropertyIndex( currentFetch.getOwnerPropertyName() );
|
|
||||||
final boolean isNullable = ownerPersister.isSubclassPropertyNullable( propertyNumber );
|
|
||||||
if ( currentFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) {
|
if ( currentFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) {
|
||||||
joinType = isNullable ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN;
|
joinType = currentFetch.isNullable() ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
joinType = JoinType.NONE;
|
joinType = JoinType.NONE;
|
||||||
|
|
|
@ -27,7 +27,6 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.cfg.NotYetImplementedException;
|
import org.hibernate.cfg.NotYetImplementedException;
|
||||||
import org.hibernate.engine.internal.JoinHelper;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.loader.CollectionAliases;
|
import org.hibernate.loader.CollectionAliases;
|
||||||
|
@ -36,6 +35,8 @@ import org.hibernate.loader.EntityAliases;
|
||||||
import org.hibernate.loader.GeneratedCollectionAliases;
|
import org.hibernate.loader.GeneratedCollectionAliases;
|
||||||
import org.hibernate.loader.plan.spi.CollectionReference;
|
import org.hibernate.loader.plan.spi.CollectionReference;
|
||||||
import org.hibernate.loader.plan.spi.CollectionReturn;
|
import org.hibernate.loader.plan.spi.CollectionReturn;
|
||||||
|
import org.hibernate.loader.plan.spi.CompositeElementGraph;
|
||||||
|
import org.hibernate.loader.plan.spi.CompositeIndexGraph;
|
||||||
import org.hibernate.loader.plan.spi.EntityReference;
|
import org.hibernate.loader.plan.spi.EntityReference;
|
||||||
import org.hibernate.loader.plan.spi.EntityReturn;
|
import org.hibernate.loader.plan.spi.EntityReturn;
|
||||||
import org.hibernate.loader.plan.spi.Fetch;
|
import org.hibernate.loader.plan.spi.Fetch;
|
||||||
|
@ -46,7 +47,6 @@ import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Loadable;
|
import org.hibernate.persister.entity.Loadable;
|
||||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
|
||||||
import org.hibernate.type.EntityType;
|
import org.hibernate.type.EntityType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -214,9 +214,18 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu
|
||||||
if ( EntityReference.class.isInstance( currentFetch.getOwner() ) ) {
|
if ( EntityReference.class.isInstance( currentFetch.getOwner() ) ) {
|
||||||
lhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch.getOwner() );
|
lhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch.getOwner() );
|
||||||
}
|
}
|
||||||
else {
|
else if ( CompositeElementGraph.class.isInstance( currentFetch.getOwner() ) ) {
|
||||||
throw new NotYetImplementedException( "Cannot determine LHS alias for a FetchOwner that is not an EntityReference yet." );
|
CompositeElementGraph compositeElementGraph = (CompositeElementGraph) currentFetch.getOwner();
|
||||||
|
lhsAlias = resolveCollectionTableAlias( compositeElementGraph.getCollectionReference() );
|
||||||
}
|
}
|
||||||
|
else if ( CompositeIndexGraph.class.isInstance( currentFetch.getOwner() ) ) {
|
||||||
|
CompositeIndexGraph compositeIndexGraph = (CompositeIndexGraph) currentFetch.getOwner();
|
||||||
|
lhsAlias = resolveCollectionTableAlias( compositeIndexGraph.getCollectionReference() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new NotYetImplementedException( "Cannot determine LHS alias for FetchOwner." );
|
||||||
|
}
|
||||||
|
final String[] aliasedLhsColumnNames = StringHelper.qualify( lhsAlias, currentFetch.getColumnNames() );
|
||||||
final String rhsAlias;
|
final String rhsAlias;
|
||||||
if ( EntityReference.class.isInstance( currentFetch ) ) {
|
if ( EntityReference.class.isInstance( currentFetch ) ) {
|
||||||
rhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch );
|
rhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch );
|
||||||
|
@ -229,15 +238,6 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: can't this be found in CollectionAliases or EntityAliases? should be moved to LoadQueryAliasResolutionContextImpl
|
// TODO: can't this be found in CollectionAliases or EntityAliases? should be moved to LoadQueryAliasResolutionContextImpl
|
||||||
final OuterJoinLoadable fetchSourcePersister = (OuterJoinLoadable) currentFetch.getOwner().retrieveFetchSourcePersister();
|
|
||||||
final int propertyNumber = fetchSourcePersister.getEntityMetamodel().getPropertyIndex( currentFetch.getOwnerPropertyName() );
|
|
||||||
final String[] aliasedLhsColumnNames = JoinHelper.getAliasedLHSColumnNames(
|
|
||||||
joinableAssociation.getAssociationType(),
|
|
||||||
lhsAlias,
|
|
||||||
propertyNumber,
|
|
||||||
fetchSourcePersister,
|
|
||||||
sessionFactory
|
|
||||||
);
|
|
||||||
|
|
||||||
aliases = new JoinableAssociationAliasesImpl( lhsAlias, aliasedLhsColumnNames, rhsAlias );
|
aliases = new JoinableAssociationAliasesImpl( lhsAlias, aliasedLhsColumnNames, rhsAlias );
|
||||||
aliasesByJoinableAssociation.put( joinableAssociation, aliases );
|
aliasesByJoinableAssociation.put( joinableAssociation, aliases );
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.loader.plan.spi.FetchOwner;
|
||||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||||
|
import org.hibernate.type.EntityType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -63,6 +64,7 @@ public class LoadPlanBuildingHelper {
|
||||||
LockMode.NONE, // todo : for now
|
LockMode.NONE, // todo : for now
|
||||||
fetchOwner,
|
fetchOwner,
|
||||||
attributeDefinition.getName(),
|
attributeDefinition.getName(),
|
||||||
|
(EntityType) attributeDefinition.getType(),
|
||||||
fetchStrategy
|
fetchStrategy
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -73,7 +75,7 @@ public class LoadPlanBuildingHelper {
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||||
return new CompositeFetch(
|
return new CompositeFetch(
|
||||||
loadPlanBuildingContext.getSessionFactory(),
|
loadPlanBuildingContext.getSessionFactory(),
|
||||||
(AbstractFetchOwner) fetchOwner,
|
fetchOwner,
|
||||||
attributeDefinition.getName()
|
attributeDefinition.getName()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,20 +27,24 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||||
|
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||||
|
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractFetchOwner extends AbstractPlanNode implements FetchOwner {
|
public abstract class AbstractFetchOwner extends AbstractPlanNode implements FetchOwner {
|
||||||
private final LockMode lockMode;
|
|
||||||
|
|
||||||
private List<Fetch> fetches;
|
private List<Fetch> fetches;
|
||||||
|
|
||||||
public AbstractFetchOwner(SessionFactoryImplementor factory, LockMode lockMode) {
|
public AbstractFetchOwner(SessionFactoryImplementor factory) {
|
||||||
super( factory );
|
super( factory );
|
||||||
this.lockMode = lockMode;
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,11 +54,10 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
||||||
/**
|
/**
|
||||||
* A "copy" constructor. Used while making clones/copies of this.
|
* A "copy" constructor. Used while making clones/copies of this.
|
||||||
*
|
*
|
||||||
* @param original
|
* @param original - the original object to copy.
|
||||||
*/
|
*/
|
||||||
protected AbstractFetchOwner(AbstractFetchOwner original, CopyContext copyContext) {
|
protected AbstractFetchOwner(AbstractFetchOwner original, CopyContext copyContext) {
|
||||||
super( original );
|
super( original );
|
||||||
this.lockMode = original.lockMode;
|
|
||||||
validate();
|
validate();
|
||||||
|
|
||||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
||||||
|
@ -62,6 +65,7 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
||||||
this.fetches = Collections.emptyList();
|
this.fetches = Collections.emptyList();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// TODO: don't think this is correct...
|
||||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
||||||
for ( Fetch fetch : fetches ) {
|
for ( Fetch fetch : fetches ) {
|
||||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
||||||
|
@ -71,11 +75,6 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
||||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
||||||
}
|
}
|
||||||
|
|
||||||
public LockMode getLockMode() {
|
|
||||||
return lockMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addFetch(Fetch fetch) {
|
public void addFetch(Fetch fetch) {
|
||||||
if ( fetch.getOwner() != this ) {
|
if ( fetch.getOwner() != this ) {
|
||||||
throw new IllegalArgumentException( "Fetch and owner did not match" );
|
throw new IllegalArgumentException( "Fetch and owner did not match" );
|
||||||
|
@ -92,4 +91,55 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
||||||
public Fetch[] getFetches() {
|
public Fetch[] getFetches() {
|
||||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract FetchOwnerDelegate getFetchOwnerDelegate();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable(Fetch fetch) {
|
||||||
|
return getFetchOwnerDelegate().isNullable( fetch );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType(Fetch fetch) {
|
||||||
|
return getFetchOwnerDelegate().getType( fetch );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getColumnNames(Fetch fetch) {
|
||||||
|
return getFetchOwnerDelegate().getColumnNames( fetch );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CollectionFetch buildCollectionFetch(
|
||||||
|
AssociationAttributeDefinition attributeDefinition,
|
||||||
|
FetchStrategy fetchStrategy,
|
||||||
|
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||||
|
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
||||||
|
this,
|
||||||
|
attributeDefinition,
|
||||||
|
fetchStrategy,
|
||||||
|
loadPlanBuildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityFetch buildEntityFetch(
|
||||||
|
AssociationAttributeDefinition attributeDefinition,
|
||||||
|
FetchStrategy fetchStrategy,
|
||||||
|
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||||
|
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||||
|
this,
|
||||||
|
attributeDefinition,
|
||||||
|
fetchStrategy,
|
||||||
|
loadPlanBuildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompositeFetch buildCompositeFetch(
|
||||||
|
CompositionDefinition attributeDefinition,
|
||||||
|
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||||
|
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
package org.hibernate.loader.plan.spi;
|
package org.hibernate.loader.plan.spi;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchStyle;
|
import org.hibernate.engine.FetchStyle;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
@ -42,11 +41,10 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner
|
||||||
|
|
||||||
public AbstractSingularAttributeFetch(
|
public AbstractSingularAttributeFetch(
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
LockMode lockMode,
|
|
||||||
FetchOwner owner,
|
FetchOwner owner,
|
||||||
String ownerProperty,
|
String ownerProperty,
|
||||||
FetchStrategy fetchStrategy) {
|
FetchStrategy fetchStrategy) {
|
||||||
super( factory, lockMode );
|
super( factory );
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.ownerProperty = ownerProperty;
|
this.ownerProperty = ownerProperty;
|
||||||
this.fetchStrategy = fetchStrategy;
|
this.fetchStrategy = fetchStrategy;
|
||||||
|
@ -77,6 +75,16 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner
|
||||||
return ownerProperty;
|
return ownerProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable() {
|
||||||
|
return owner.isNullable( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getColumnNames() {
|
||||||
|
return owner.getColumnNames( this );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FetchStrategy getFetchStrategy() {
|
public FetchStrategy getFetchStrategy() {
|
||||||
return fetchStrategy;
|
return fetchStrategy;
|
||||||
|
|
|
@ -28,8 +28,10 @@ import java.sql.SQLException;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
|
import org.hibernate.engine.internal.JoinHelper;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||||
|
import org.hibernate.persister.entity.Joinable;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,6 +76,16 @@ public class CollectionFetch extends AbstractCollectionReference implements Fetc
|
||||||
return getPropertyPath().getProperty();
|
return getPropertyPath().getProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getColumnNames() {
|
||||||
|
return getOwner().getColumnNames( this );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FetchStrategy getFetchStrategy() {
|
public FetchStrategy getFetchStrategy() {
|
||||||
return fetchStrategy;
|
return fetchStrategy;
|
||||||
|
|
|
@ -1,29 +1,24 @@
|
||||||
package org.hibernate.loader.plan.spi;
|
package org.hibernate.loader.plan.spi;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.loader.PropertyPath;
|
import org.hibernate.loader.PropertyPath;
|
||||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
|
||||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
import org.hibernate.type.CompositeType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class CompositeElementGraph extends AbstractPlanNode implements FetchableCollectionElement {
|
public class CompositeElementGraph extends AbstractFetchOwner implements FetchableCollectionElement {
|
||||||
private final CollectionReference collectionReference;
|
private final CollectionReference collectionReference;
|
||||||
private final PropertyPath propertyPath;
|
private final PropertyPath propertyPath;
|
||||||
private final CollectionPersister collectionPersister;
|
private final CollectionPersister collectionPersister;
|
||||||
|
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||||
private List<Fetch> fetches;
|
|
||||||
|
|
||||||
public CompositeElementGraph(
|
public CompositeElementGraph(
|
||||||
SessionFactoryImplementor sessionFactory,
|
SessionFactoryImplementor sessionFactory,
|
||||||
|
@ -34,39 +29,24 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
|
||||||
this.collectionReference = collectionReference;
|
this.collectionReference = collectionReference;
|
||||||
this.collectionPersister = collectionReference.getCollectionPersister();
|
this.collectionPersister = collectionReference.getCollectionPersister();
|
||||||
this.propertyPath = collectionPath.append( "<elements>" );
|
this.propertyPath = collectionPath.append( "<elements>" );
|
||||||
|
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
|
||||||
|
sessionFactory,
|
||||||
|
(CompositeType) collectionPersister.getElementType(),
|
||||||
|
( (QueryableCollection) collectionPersister ).getElementColumnNames()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompositeElementGraph(CompositeElementGraph original, CopyContext copyContext) {
|
public CompositeElementGraph(CompositeElementGraph original, CopyContext copyContext) {
|
||||||
super( original );
|
super( original, copyContext );
|
||||||
this.collectionReference = original.collectionReference;
|
this.collectionReference = original.collectionReference;
|
||||||
this.collectionPersister = original.collectionPersister;
|
this.collectionPersister = original.collectionPersister;
|
||||||
this.propertyPath = original.propertyPath;
|
this.propertyPath = original.propertyPath;
|
||||||
|
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
|
||||||
if ( fetches == null || fetches.size() == 0 ) {
|
|
||||||
this.fetches = Collections.emptyList();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
|
||||||
for ( Fetch fetch : fetches ) {
|
|
||||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
|
||||||
}
|
|
||||||
this.fetches = fetchesCopy;
|
|
||||||
}
|
|
||||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addFetch(Fetch fetch) {
|
public CollectionReference getCollectionReference() {
|
||||||
if ( fetches == null ) {
|
return collectionReference;
|
||||||
fetches = new ArrayList<Fetch>();
|
|
||||||
}
|
|
||||||
fetches.add( fetch );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Fetch[] getFetches() {
|
|
||||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -83,6 +63,16 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
|
||||||
return propertyPath;
|
return propertyPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompositeElementGraph makeCopy(CopyContext copyContext) {
|
||||||
|
return new CompositeElementGraph( this, copyContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||||
|
return fetchOwnerDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CollectionFetch buildCollectionFetch(
|
public CollectionFetch buildCollectionFetch(
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
AssociationAttributeDefinition attributeDefinition,
|
||||||
|
@ -90,29 +80,4 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||||
throw new HibernateException( "Collection composite element cannot define collections" );
|
throw new HibernateException( "Collection composite element cannot define collections" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public EntityFetch buildEntityFetch(
|
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
|
||||||
FetchStrategy fetchStrategy,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
|
||||||
this,
|
|
||||||
attributeDefinition,
|
|
||||||
fetchStrategy,
|
|
||||||
loadPlanBuildingContext
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompositeFetch buildCompositeFetch(
|
|
||||||
CompositionDefinition attributeDefinition,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompositeElementGraph makeCopy(CopyContext copyContext) {
|
|
||||||
return new CompositeElementGraph( this, copyContext );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,17 +25,17 @@ package org.hibernate.loader.plan.spi;
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchStyle;
|
import org.hibernate.engine.FetchStyle;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||||
|
import org.hibernate.type.CompositeType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -43,15 +43,28 @@ import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||||
public class CompositeFetch extends AbstractSingularAttributeFetch {
|
public class CompositeFetch extends AbstractSingularAttributeFetch {
|
||||||
public static final FetchStrategy FETCH_PLAN = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
|
public static final FetchStrategy FETCH_PLAN = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
|
||||||
|
|
||||||
|
private final FetchOwnerDelegate delegate;
|
||||||
|
|
||||||
public CompositeFetch(
|
public CompositeFetch(
|
||||||
SessionFactoryImplementor sessionFactory,
|
SessionFactoryImplementor sessionFactory,
|
||||||
FetchOwner owner,
|
FetchOwner owner,
|
||||||
String ownerProperty) {
|
String ownerProperty) {
|
||||||
super( sessionFactory, LockMode.NONE, owner, ownerProperty, FETCH_PLAN );
|
super( sessionFactory, owner, ownerProperty, FETCH_PLAN );
|
||||||
|
this.delegate = new CompositeFetchOwnerDelegate(
|
||||||
|
sessionFactory,
|
||||||
|
(CompositeType) getOwner().getType( this ),
|
||||||
|
getOwner().getColumnNames( this )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompositeFetch(CompositeFetch original, CopyContext copyContext, FetchOwner fetchOwnerCopy) {
|
public CompositeFetch(CompositeFetch original, CopyContext copyContext, FetchOwner fetchOwnerCopy) {
|
||||||
super( original, copyContext, fetchOwnerCopy );
|
super( original, copyContext, fetchOwnerCopy );
|
||||||
|
this.delegate = original.getFetchOwnerDelegate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||||
|
return delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -72,13 +85,18 @@ public class CompositeFetch extends AbstractSingularAttributeFetch {
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
AssociationAttributeDefinition attributeDefinition,
|
||||||
FetchStrategy fetchStrategy,
|
FetchStrategy fetchStrategy,
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||||
|
this,
|
||||||
|
attributeDefinition,
|
||||||
|
fetchStrategy,
|
||||||
|
loadPlanBuildingContext
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompositeFetch buildCompositeFetch(
|
public CompositeFetch buildCompositeFetch(
|
||||||
CompositionDefinition attributeDefinition, LoadPlanBuildingContext loadPlanBuildingContext) {
|
CompositionDefinition attributeDefinition, LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.loader.plan.spi;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
|
import org.hibernate.persister.walking.spi.WalkingException;
|
||||||
|
import org.hibernate.type.CompositeType;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public class CompositeFetchOwnerDelegate implements FetchOwnerDelegate {
|
||||||
|
private final SessionFactoryImplementor sessionFactory;
|
||||||
|
private final CompositeType compositeType;
|
||||||
|
private final String[] columnNames;
|
||||||
|
|
||||||
|
public CompositeFetchOwnerDelegate(
|
||||||
|
SessionFactoryImplementor sessionFactory,
|
||||||
|
CompositeType compositeType,
|
||||||
|
String[] columnNames) {
|
||||||
|
this.sessionFactory = sessionFactory;
|
||||||
|
this.compositeType = compositeType;
|
||||||
|
this.columnNames = columnNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable(Fetch fetch) {
|
||||||
|
return compositeType.getPropertyNullability()[ determinePropertyIndex( fetch ) ];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType(Fetch fetch) {
|
||||||
|
return compositeType.getSubtypes()[ determinePropertyIndex( fetch ) ];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getColumnNames(Fetch fetch) {
|
||||||
|
// TODO: probably want to cache this
|
||||||
|
int begin = 0;
|
||||||
|
String[] subColumnNames = null;
|
||||||
|
for ( int i = 0; i < compositeType.getSubtypes().length; i++ ) {
|
||||||
|
final int columnSpan = compositeType.getSubtypes()[i].getColumnSpan( sessionFactory );
|
||||||
|
subColumnNames = ArrayHelper.slice( columnNames, begin, columnSpan );
|
||||||
|
if ( compositeType.getPropertyNames()[ i ].equals( fetch.getOwnerPropertyName() ) ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
begin += columnSpan;
|
||||||
|
}
|
||||||
|
return subColumnNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int determinePropertyIndex(Fetch fetch) {
|
||||||
|
// TODO: probably want to cache this
|
||||||
|
final String[] subAttributeNames = compositeType.getPropertyNames();
|
||||||
|
int subAttributeIndex = -1;
|
||||||
|
for ( int i = 0; i < subAttributeNames.length ; i++ ) {
|
||||||
|
if ( subAttributeNames[ i ].equals( fetch.getOwnerPropertyName() ) ) {
|
||||||
|
subAttributeIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( subAttributeIndex == -1 ) {
|
||||||
|
throw new WalkingException(
|
||||||
|
String.format(
|
||||||
|
"Owner property [%s] not found in composite properties [%s]",
|
||||||
|
fetch.getOwnerPropertyName(),
|
||||||
|
Arrays.asList( subAttributeNames )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return subAttributeIndex;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +1,24 @@
|
||||||
package org.hibernate.loader.plan.spi;
|
package org.hibernate.loader.plan.spi;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.loader.PropertyPath;
|
import org.hibernate.loader.PropertyPath;
|
||||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
|
||||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
import org.hibernate.type.CompositeType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCollectionIndex {
|
public class CompositeIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex {
|
||||||
private final CollectionReference collectionReference;
|
private final CollectionReference collectionReference;
|
||||||
private final PropertyPath propertyPath;
|
private final PropertyPath propertyPath;
|
||||||
private final CollectionPersister collectionPersister;
|
private final CollectionPersister collectionPersister;
|
||||||
|
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||||
private List<Fetch> fetches;
|
|
||||||
|
|
||||||
public CompositeIndexGraph(
|
public CompositeIndexGraph(
|
||||||
SessionFactoryImplementor sessionFactory,
|
SessionFactoryImplementor sessionFactory,
|
||||||
|
@ -33,39 +28,19 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
|
||||||
this.collectionReference = collectionReference;
|
this.collectionReference = collectionReference;
|
||||||
this.collectionPersister = collectionReference.getCollectionPersister();
|
this.collectionPersister = collectionReference.getCollectionPersister();
|
||||||
this.propertyPath = propertyPath.append( "<index>" );
|
this.propertyPath = propertyPath.append( "<index>" );
|
||||||
|
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
|
||||||
|
sessionFactory,
|
||||||
|
(CompositeType) collectionPersister.getIndexType(),
|
||||||
|
( (QueryableCollection) collectionPersister ).getIndexColumnNames()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CompositeIndexGraph(CompositeIndexGraph original, CopyContext copyContext) {
|
protected CompositeIndexGraph(CompositeIndexGraph original, CopyContext copyContext) {
|
||||||
super( original );
|
super( original, copyContext );
|
||||||
this.collectionReference = original.collectionReference;
|
this.collectionReference = original.collectionReference;
|
||||||
this.collectionPersister = original.collectionPersister;
|
this.collectionPersister = original.collectionPersister;
|
||||||
this.propertyPath = original.propertyPath;
|
this.propertyPath = original.propertyPath;
|
||||||
|
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
|
||||||
if ( fetches == null || fetches.size() == 0 ) {
|
|
||||||
this.fetches = Collections.emptyList();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
|
||||||
for ( Fetch fetch : fetches ) {
|
|
||||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
|
||||||
}
|
|
||||||
this.fetches = fetchesCopy;
|
|
||||||
}
|
|
||||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addFetch(Fetch fetch) {
|
|
||||||
if ( fetches == null ) {
|
|
||||||
fetches = new ArrayList<Fetch>();
|
|
||||||
}
|
|
||||||
fetches.add( fetch );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Fetch[] getFetches() {
|
|
||||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -77,12 +52,25 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
|
||||||
return collectionPersister.getOwnerEntityPersister();
|
return collectionPersister.getOwnerEntityPersister();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CollectionReference getCollectionReference() {
|
||||||
|
return collectionReference;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PropertyPath getPropertyPath() {
|
public PropertyPath getPropertyPath() {
|
||||||
return propertyPath;
|
return propertyPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
public CompositeIndexGraph makeCopy(CopyContext copyContext) {
|
||||||
|
return new CompositeIndexGraph( this, copyContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||||
|
return fetchOwnerDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
public CollectionFetch buildCollectionFetch(
|
public CollectionFetch buildCollectionFetch(
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
AssociationAttributeDefinition attributeDefinition,
|
||||||
FetchStrategy fetchStrategy,
|
FetchStrategy fetchStrategy,
|
||||||
|
@ -90,28 +78,4 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
|
||||||
throw new HibernateException( "Composite index cannot define collections" );
|
throw new HibernateException( "Composite index cannot define collections" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public EntityFetch buildEntityFetch(
|
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
|
||||||
FetchStrategy fetchStrategy,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
|
||||||
this,
|
|
||||||
attributeDefinition,
|
|
||||||
fetchStrategy,
|
|
||||||
loadPlanBuildingContext
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompositeFetch buildCompositeFetch(
|
|
||||||
CompositionDefinition attributeDefinition,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompositeIndexGraph makeCopy(CopyContext copyContext) {
|
|
||||||
return new CompositeIndexGraph( this, copyContext );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,23 @@
|
||||||
package org.hibernate.loader.plan.spi;
|
package org.hibernate.loader.plan.spi;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.loader.PropertyPath;
|
import org.hibernate.loader.PropertyPath;
|
||||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
|
||||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class EntityElementGraph extends AbstractPlanNode implements FetchableCollectionElement, EntityReference {
|
public class EntityElementGraph extends AbstractFetchOwner implements FetchableCollectionElement, EntityReference {
|
||||||
private final CollectionReference collectionReference;
|
private final CollectionReference collectionReference;
|
||||||
private final CollectionPersister collectionPersister;
|
private final CollectionPersister collectionPersister;
|
||||||
private final AssociationType elementType;
|
private final AssociationType elementType;
|
||||||
private final EntityPersister elementPersister;
|
private final EntityPersister elementPersister;
|
||||||
private final PropertyPath propertyPath;
|
private final PropertyPath propertyPath;
|
||||||
|
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||||
private List<Fetch> fetches;
|
|
||||||
|
|
||||||
private IdentifierDescription identifierDescription;
|
private IdentifierDescription identifierDescription;
|
||||||
|
|
||||||
|
@ -40,30 +31,19 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
||||||
this.collectionPersister = collectionReference.getCollectionPersister();
|
this.collectionPersister = collectionReference.getCollectionPersister();
|
||||||
this.elementType = (AssociationType) collectionPersister.getElementType();
|
this.elementType = (AssociationType) collectionPersister.getElementType();
|
||||||
this.elementPersister = (EntityPersister) this.elementType.getAssociatedJoinable( sessionFactory() );
|
this.elementPersister = (EntityPersister) this.elementType.getAssociatedJoinable( sessionFactory() );
|
||||||
this.propertyPath = collectionPath.append( "<elements>" );
|
this.propertyPath = collectionPath;
|
||||||
|
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( elementPersister );
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityElementGraph(EntityElementGraph original, CopyContext copyContext) {
|
public EntityElementGraph(EntityElementGraph original, CopyContext copyContext) {
|
||||||
super( original );
|
super( original, copyContext );
|
||||||
|
|
||||||
this.collectionReference = original.collectionReference;
|
this.collectionReference = original.collectionReference;
|
||||||
this.collectionPersister = original.collectionReference.getCollectionPersister();
|
this.collectionPersister = original.collectionReference.getCollectionPersister();
|
||||||
this.elementType = original.elementType;
|
this.elementType = original.elementType;
|
||||||
this.elementPersister = original.elementPersister;
|
this.elementPersister = original.elementPersister;
|
||||||
this.propertyPath = original.propertyPath;
|
this.propertyPath = original.propertyPath;
|
||||||
|
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
|
||||||
if ( fetches == null || fetches.size() == 0 ) {
|
|
||||||
this.fetches = Collections.emptyList();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
|
||||||
for ( Fetch fetch : fetches ) {
|
|
||||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
|
||||||
}
|
|
||||||
this.fetches = fetchesCopy;
|
|
||||||
}
|
|
||||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -86,19 +66,6 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
||||||
return identifierDescription;
|
return identifierDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addFetch(Fetch fetch) {
|
|
||||||
if ( fetches == null ) {
|
|
||||||
fetches = new ArrayList<Fetch>();
|
|
||||||
}
|
|
||||||
fetches.add( fetch );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Fetch[] getFetches() {
|
|
||||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validateFetchPlan(FetchStrategy fetchStrategy) {
|
public void validateFetchPlan(FetchStrategy fetchStrategy) {
|
||||||
}
|
}
|
||||||
|
@ -113,39 +80,6 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
||||||
return propertyPath;
|
return propertyPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public CollectionFetch buildCollectionFetch(
|
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
|
||||||
FetchStrategy fetchStrategy,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
|
||||||
this,
|
|
||||||
attributeDefinition,
|
|
||||||
fetchStrategy,
|
|
||||||
loadPlanBuildingContext
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EntityFetch buildEntityFetch(
|
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
|
||||||
FetchStrategy fetchStrategy,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
|
||||||
this,
|
|
||||||
attributeDefinition,
|
|
||||||
fetchStrategy,
|
|
||||||
loadPlanBuildingContext
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompositeFetch buildCompositeFetch(
|
|
||||||
CompositionDefinition attributeDefinition,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
||||||
this.identifierDescription = identifierDescription;
|
this.identifierDescription = identifierDescription;
|
||||||
|
@ -156,8 +90,18 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
||||||
return new EntityElementGraph( this, copyContext );
|
return new EntityElementGraph( this, copyContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CollectionReference getCollectionReference() {
|
||||||
|
return collectionReference;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "EntityElementGraph(collection=" + collectionPersister.getRole() + ", type=" + elementPersister.getEntityName() + ")";
|
return "EntityElementGraph(collection=" + collectionPersister.getRole() + ", type=" + elementPersister.getEntityName() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||||
|
return fetchOwnerDelegate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,21 +32,19 @@ import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
|
||||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
|
||||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
|
||||||
import org.hibernate.type.EntityType;
|
import org.hibernate.type.EntityType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class EntityFetch extends AbstractSingularAttributeFetch implements EntityReference {
|
public class EntityFetch extends AbstractSingularAttributeFetch implements EntityReference, Fetch {
|
||||||
|
|
||||||
private final EntityType associationType;
|
private final EntityType associationType;
|
||||||
private final EntityPersister persister;
|
private final EntityPersister persister;
|
||||||
|
private final LockMode lockMode;
|
||||||
|
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||||
|
|
||||||
private IdentifierDescription identifierDescription;
|
private IdentifierDescription identifierDescription;
|
||||||
|
|
||||||
|
@ -55,11 +53,14 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
FetchOwner owner,
|
FetchOwner owner,
|
||||||
String ownerProperty,
|
String ownerProperty,
|
||||||
|
EntityType entityType,
|
||||||
FetchStrategy fetchStrategy) {
|
FetchStrategy fetchStrategy) {
|
||||||
super( sessionFactory, lockMode, owner, ownerProperty, fetchStrategy );
|
super( sessionFactory, owner, ownerProperty, fetchStrategy );
|
||||||
|
|
||||||
this.associationType = (EntityType) owner.retrieveFetchSourcePersister().getPropertyType( ownerProperty );
|
this.associationType = entityType;
|
||||||
this.persister = sessionFactory.getEntityPersister( associationType.getAssociatedEntityName() );
|
this.persister = sessionFactory.getEntityPersister( associationType.getAssociatedEntityName() );
|
||||||
|
this.lockMode = lockMode;
|
||||||
|
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( persister );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,6 +73,8 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
||||||
super( original, copyContext, fetchOwnerCopy );
|
super( original, copyContext, fetchOwnerCopy );
|
||||||
this.associationType = original.associationType;
|
this.associationType = original.associationType;
|
||||||
this.persister = original.persister;
|
this.persister = original.persister;
|
||||||
|
this.lockMode = original.lockMode;
|
||||||
|
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityType getAssociationType() {
|
public EntityType getAssociationType() {
|
||||||
|
@ -93,45 +96,16 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
||||||
return identifierDescription;
|
return identifierDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LockMode getLockMode() {
|
||||||
|
return lockMode;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityPersister retrieveFetchSourcePersister() {
|
public EntityPersister retrieveFetchSourcePersister() {
|
||||||
return persister;
|
return persister;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CollectionFetch buildCollectionFetch(
|
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
|
||||||
FetchStrategy fetchStrategy,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
|
||||||
this,
|
|
||||||
attributeDefinition,
|
|
||||||
fetchStrategy,
|
|
||||||
loadPlanBuildingContext
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EntityFetch buildEntityFetch(
|
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
|
||||||
FetchStrategy fetchStrategy,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
|
||||||
this,
|
|
||||||
attributeDefinition,
|
|
||||||
fetchStrategy,
|
|
||||||
loadPlanBuildingContext
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompositeFetch buildCompositeFetch(
|
|
||||||
CompositionDefinition attributeDefinition,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
||||||
this.identifierDescription = identifierDescription;
|
this.identifierDescription = identifierDescription;
|
||||||
|
@ -267,4 +241,9 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
||||||
copyContext.getReturnGraphVisitationStrategy().finishingEntityFetch( this );
|
copyContext.getReturnGraphVisitationStrategy().finishingEntityFetch( this );
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||||
|
return fetchOwnerDelegate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.loader.plan.spi;
|
||||||
|
|
||||||
|
import org.hibernate.engine.internal.JoinHelper;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
|
import org.hibernate.type.AssociationType;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public class EntityFetchOwnerDelegate implements FetchOwnerDelegate {
|
||||||
|
private final EntityPersister entityPersister;
|
||||||
|
|
||||||
|
public EntityFetchOwnerDelegate(EntityPersister entityPersister) {
|
||||||
|
this.entityPersister = entityPersister;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable(Fetch fetch) {
|
||||||
|
return entityPersister.getPropertyNullability()[ determinePropertyIndex( fetch ) ];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType(Fetch fetch) {
|
||||||
|
return entityPersister.getPropertyTypes()[ determinePropertyIndex( fetch ) ];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getColumnNames(Fetch fetch) {
|
||||||
|
final OuterJoinLoadable outerJoinLoadable = (OuterJoinLoadable) entityPersister;
|
||||||
|
Type fetchType = getType( fetch );
|
||||||
|
if ( fetchType.isAssociationType() ) {
|
||||||
|
return JoinHelper.getLHSColumnNames(
|
||||||
|
(AssociationType) fetchType,
|
||||||
|
determinePropertyIndex( fetch ),
|
||||||
|
outerJoinLoadable,
|
||||||
|
outerJoinLoadable.getFactory()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return outerJoinLoadable.getPropertyColumnNames( determinePropertyIndex( fetch ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int determinePropertyIndex(Fetch fetch) {
|
||||||
|
return entityPersister.getEntityMetamodel().getPropertyIndex( fetch.getOwnerPropertyName() );
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,33 +23,24 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.loader.plan.spi;
|
package org.hibernate.loader.plan.spi;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.loader.PropertyPath;
|
import org.hibernate.loader.PropertyPath;
|
||||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
|
||||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
|
||||||
import org.hibernate.type.AssociationType;
|
import org.hibernate.type.AssociationType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class EntityIndexGraph extends AbstractPlanNode implements FetchableCollectionIndex, EntityReference {
|
public class EntityIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex, EntityReference {
|
||||||
private final CollectionReference collectionReference;
|
private final CollectionReference collectionReference;
|
||||||
private final CollectionPersister collectionPersister;
|
private final CollectionPersister collectionPersister;
|
||||||
private final AssociationType indexType;
|
private final AssociationType indexType;
|
||||||
private final EntityPersister indexPersister;
|
private final EntityPersister indexPersister;
|
||||||
private final PropertyPath propertyPath;
|
private final PropertyPath propertyPath;
|
||||||
|
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||||
private List<Fetch> fetches;
|
|
||||||
|
|
||||||
private IdentifierDescription identifierDescription;
|
private IdentifierDescription identifierDescription;
|
||||||
|
|
||||||
|
@ -63,28 +54,17 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
||||||
this.indexType = (AssociationType) collectionPersister.getIndexType();
|
this.indexType = (AssociationType) collectionPersister.getIndexType();
|
||||||
this.indexPersister = (EntityPersister) this.indexType.getAssociatedJoinable( sessionFactory() );
|
this.indexPersister = (EntityPersister) this.indexType.getAssociatedJoinable( sessionFactory() );
|
||||||
this.propertyPath = collectionPath.append( "<index>" ); // todo : do we want the <index> part?
|
this.propertyPath = collectionPath.append( "<index>" ); // todo : do we want the <index> part?
|
||||||
|
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( indexPersister );
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityIndexGraph(EntityIndexGraph original, CopyContext copyContext) {
|
public EntityIndexGraph(EntityIndexGraph original, CopyContext copyContext) {
|
||||||
super( original );
|
super( original, copyContext );
|
||||||
this.collectionReference = original.collectionReference;
|
this.collectionReference = original.collectionReference;
|
||||||
this.collectionPersister = original.collectionReference.getCollectionPersister();
|
this.collectionPersister = original.collectionReference.getCollectionPersister();
|
||||||
this.indexType = original.indexType;
|
this.indexType = original.indexType;
|
||||||
this.indexPersister = original.indexPersister;
|
this.indexPersister = original.indexPersister;
|
||||||
this.propertyPath = original.propertyPath;
|
this.propertyPath = original.propertyPath;
|
||||||
|
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
|
||||||
if ( fetches == null || fetches.size() == 0 ) {
|
|
||||||
this.fetches = Collections.emptyList();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
|
||||||
for ( Fetch fetch : fetches ) {
|
|
||||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
|
||||||
}
|
|
||||||
this.fetches = fetchesCopy;
|
|
||||||
}
|
|
||||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -107,19 +87,6 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
||||||
return identifierDescription;
|
return identifierDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addFetch(Fetch fetch) {
|
|
||||||
if ( fetches == null ) {
|
|
||||||
fetches = new ArrayList<Fetch>();
|
|
||||||
}
|
|
||||||
fetches.add( fetch );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Fetch[] getFetches() {
|
|
||||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validateFetchPlan(FetchStrategy fetchStrategy) {
|
public void validateFetchPlan(FetchStrategy fetchStrategy) {
|
||||||
}
|
}
|
||||||
|
@ -134,39 +101,6 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
||||||
return propertyPath;
|
return propertyPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public CollectionFetch buildCollectionFetch(
|
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
|
||||||
FetchStrategy fetchStrategy,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
|
||||||
this,
|
|
||||||
attributeDefinition,
|
|
||||||
fetchStrategy,
|
|
||||||
loadPlanBuildingContext
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EntityFetch buildEntityFetch(
|
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
|
||||||
FetchStrategy fetchStrategy,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
|
||||||
this,
|
|
||||||
attributeDefinition,
|
|
||||||
fetchStrategy,
|
|
||||||
loadPlanBuildingContext
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompositeFetch buildCompositeFetch(
|
|
||||||
CompositionDefinition attributeDefinition,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
||||||
this.identifierDescription = identifierDescription;
|
this.identifierDescription = identifierDescription;
|
||||||
|
@ -176,4 +110,9 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
||||||
public EntityIndexGraph makeCopy(CopyContext copyContext) {
|
public EntityIndexGraph makeCopy(CopyContext copyContext) {
|
||||||
return new EntityIndexGraph( this, copyContext );
|
return new EntityIndexGraph( this, copyContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||||
|
return fetchOwnerDelegate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,8 @@ import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.loader.PropertyPath;
|
import org.hibernate.loader.PropertyPath;
|
||||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
|
||||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
|
||||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
|
||||||
|
|
||||||
import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext;
|
import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext;
|
||||||
|
|
||||||
|
@ -50,24 +46,32 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
|
||||||
|
|
||||||
private final PropertyPath propertyPath = new PropertyPath(); // its a root
|
private final PropertyPath propertyPath = new PropertyPath(); // its a root
|
||||||
|
|
||||||
|
private final LockMode lockMode;
|
||||||
|
|
||||||
|
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||||
|
|
||||||
private IdentifierDescription identifierDescription;
|
private IdentifierDescription identifierDescription;
|
||||||
|
|
||||||
public EntityReturn(
|
public EntityReturn(
|
||||||
SessionFactoryImplementor sessionFactory,
|
SessionFactoryImplementor sessionFactory,
|
||||||
LockMode lockMode,
|
LockMode lockMode,
|
||||||
String entityName) {
|
String entityName) {
|
||||||
super( sessionFactory, lockMode );
|
super( sessionFactory );
|
||||||
|
|
||||||
this.persister = sessionFactory.getEntityPersister( entityName );
|
this.persister = sessionFactory.getEntityPersister( entityName );
|
||||||
|
this.lockMode = lockMode;
|
||||||
|
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( persister );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EntityReturn(EntityReturn original, CopyContext copyContext) {
|
protected EntityReturn(EntityReturn original, CopyContext copyContext) {
|
||||||
super( original, copyContext );
|
super( original, copyContext );
|
||||||
this.persister = original.persister;
|
this.persister = original.persister;
|
||||||
|
this.lockMode = original.lockMode;
|
||||||
|
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LockMode getLockMode() {
|
public LockMode getLockMode() {
|
||||||
return super.getLockMode();
|
return lockMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -99,42 +103,9 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
|
||||||
return propertyPath;
|
return propertyPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public CollectionFetch buildCollectionFetch(
|
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
|
||||||
FetchStrategy fetchStrategy,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
|
||||||
this,
|
|
||||||
attributeDefinition,
|
|
||||||
fetchStrategy,
|
|
||||||
loadPlanBuildingContext
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EntityFetch buildEntityFetch(
|
|
||||||
AssociationAttributeDefinition attributeDefinition,
|
|
||||||
FetchStrategy fetchStrategy,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
|
||||||
this,
|
|
||||||
attributeDefinition,
|
|
||||||
fetchStrategy,
|
|
||||||
loadPlanBuildingContext
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompositeFetch buildCompositeFetch(
|
|
||||||
CompositionDefinition attributeDefinition,
|
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
|
||||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hydrate(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
|
public void hydrate(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
|
||||||
EntityKey entityKey = context.getDictatedRootEntityKey();
|
EntityKey entityKey = getEntityKeyFromContext( context );
|
||||||
if ( entityKey != null ) {
|
if ( entityKey != null ) {
|
||||||
context.getIdentifierResolutionContext( this ).registerEntityKey( entityKey );
|
context.getIdentifierResolutionContext( this ).registerEntityKey( entityKey );
|
||||||
return;
|
return;
|
||||||
|
@ -147,6 +118,19 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private EntityKey getEntityKeyFromContext(ResultSetProcessingContext context) {
|
||||||
|
if ( context.getDictatedRootEntityKey() != null ) {
|
||||||
|
return context.getDictatedRootEntityKey();
|
||||||
|
}
|
||||||
|
else if ( context.getQueryParameters().getOptionalId() != null ) {
|
||||||
|
return context.getSession().generateEntityKey(
|
||||||
|
context.getQueryParameters().getOptionalId(),
|
||||||
|
getEntityPersister()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resolve(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
|
public void resolve(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
|
||||||
final IdentifierResolutionContext identifierResolutionContext = context.getIdentifierResolutionContext( this );
|
final IdentifierResolutionContext identifierResolutionContext = context.getIdentifierResolutionContext( this );
|
||||||
|
@ -194,4 +178,9 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
|
||||||
public EntityReturn makeCopy(CopyContext copyContext) {
|
public EntityReturn makeCopy(CopyContext copyContext) {
|
||||||
return new EntityReturn( this, copyContext );
|
return new EntityReturn( this, copyContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||||
|
return fetchOwnerDelegate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,10 @@ public interface Fetch extends CopyableFetch {
|
||||||
*/
|
*/
|
||||||
public String getOwnerPropertyName();
|
public String getOwnerPropertyName();
|
||||||
|
|
||||||
|
public boolean isNullable();
|
||||||
|
|
||||||
|
public String[] getColumnNames();
|
||||||
|
|
||||||
public FetchStrategy getFetchStrategy();
|
public FetchStrategy getFetchStrategy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contract for owners of fetches. Any non-scalar return could be a fetch owner.
|
* Contract for owners of fetches. Any non-scalar return could be a fetch owner.
|
||||||
|
@ -56,6 +57,12 @@ public interface FetchOwner {
|
||||||
*/
|
*/
|
||||||
public Fetch[] getFetches();
|
public Fetch[] getFetches();
|
||||||
|
|
||||||
|
public Type getType(Fetch fetch);
|
||||||
|
|
||||||
|
public boolean isNullable(Fetch fetch);
|
||||||
|
|
||||||
|
public String[] getColumnNames(Fetch fetch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the asserted plan valid from this owner to a fetch?
|
* Is the asserted plan valid from this owner to a fetch?
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.loader.plan.spi;
|
||||||
|
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public interface FetchOwnerDelegate {
|
||||||
|
|
||||||
|
public boolean isNullable(Fetch fetch);
|
||||||
|
|
||||||
|
public Type getType(Fetch fetch);
|
||||||
|
|
||||||
|
public String[] getColumnNames(Fetch fetch);
|
||||||
|
}
|
|
@ -23,10 +23,14 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.loader.plan.spi;
|
package org.hibernate.loader.plan.spi;
|
||||||
|
|
||||||
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface FetchableCollectionElement extends FetchOwner, CopyableReturn {
|
public interface FetchableCollectionElement extends FetchOwner, CopyableReturn {
|
||||||
@Override
|
@Override
|
||||||
public FetchableCollectionElement makeCopy(CopyContext copyContext);
|
public FetchableCollectionElement makeCopy(CopyContext copyContext);
|
||||||
|
|
||||||
|
public CollectionReference getCollectionReference();
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.jboss.logging.MDC;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.cfg.NotYetImplementedException;
|
||||||
import org.hibernate.engine.FetchStrategy;
|
import org.hibernate.engine.FetchStrategy;
|
||||||
import org.hibernate.engine.FetchTiming;
|
import org.hibernate.engine.FetchTiming;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
|
@ -44,19 +45,24 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.loader.PropertyPath;
|
import org.hibernate.loader.PropertyPath;
|
||||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||||
|
import org.hibernate.loader.plan.spi.AbstractSingularAttributeFetch;
|
||||||
import org.hibernate.loader.plan.spi.CollectionFetch;
|
import org.hibernate.loader.plan.spi.CollectionFetch;
|
||||||
import org.hibernate.loader.plan.spi.CollectionReference;
|
import org.hibernate.loader.plan.spi.CollectionReference;
|
||||||
import org.hibernate.loader.plan.spi.CollectionReturn;
|
import org.hibernate.loader.plan.spi.CollectionReturn;
|
||||||
|
import org.hibernate.loader.plan.spi.CompositeElementGraph;
|
||||||
import org.hibernate.loader.plan.spi.CompositeFetch;
|
import org.hibernate.loader.plan.spi.CompositeFetch;
|
||||||
|
import org.hibernate.loader.plan.spi.CompositeFetchOwnerDelegate;
|
||||||
import org.hibernate.loader.plan.spi.EntityFetch;
|
import org.hibernate.loader.plan.spi.EntityFetch;
|
||||||
import org.hibernate.loader.plan.spi.EntityReference;
|
import org.hibernate.loader.plan.spi.EntityReference;
|
||||||
import org.hibernate.loader.plan.spi.EntityReturn;
|
import org.hibernate.loader.plan.spi.EntityReturn;
|
||||||
import org.hibernate.loader.plan.spi.Fetch;
|
import org.hibernate.loader.plan.spi.Fetch;
|
||||||
import org.hibernate.loader.plan.spi.FetchOwner;
|
import org.hibernate.loader.plan.spi.FetchOwner;
|
||||||
|
import org.hibernate.loader.plan.spi.FetchOwnerDelegate;
|
||||||
import org.hibernate.loader.plan.spi.IdentifierDescription;
|
import org.hibernate.loader.plan.spi.IdentifierDescription;
|
||||||
import org.hibernate.loader.plan.spi.Return;
|
import org.hibernate.loader.plan.spi.Return;
|
||||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.Loadable;
|
||||||
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||||
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||||
|
@ -64,9 +70,11 @@ import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
|
||||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||||
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||||
import org.hibernate.persister.walking.spi.WalkingException;
|
import org.hibernate.persister.walking.spi.WalkingException;
|
||||||
|
import org.hibernate.type.CompositeType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext;
|
import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext;
|
||||||
|
@ -190,8 +198,13 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
|
|
||||||
final FetchOwner identifierAttributeCollector;
|
final FetchOwner identifierAttributeCollector;
|
||||||
if ( entityIdentifierDefinition.isEncapsulated() ) {
|
if ( entityIdentifierDefinition.isEncapsulated() ) {
|
||||||
|
if ( entityIdentifierDefinition.getEntityDefinition().getEntityPersister().getIdentifierType().isComponentType() ) {
|
||||||
|
identifierAttributeCollector = new EncapsulatedCompositeIdentifierAttributeCollector( entityReference );
|
||||||
|
}
|
||||||
|
else {
|
||||||
identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( entityReference );
|
identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( entityReference );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
identifierAttributeCollector = new NonEncapsulatedIdentifierAttributeCollector( entityReference );
|
identifierAttributeCollector = new NonEncapsulatedIdentifierAttributeCollector( entityReference );
|
||||||
}
|
}
|
||||||
|
@ -305,6 +318,35 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
// - the element graph pushed while starting would be popped in finishing/Entity/finishingComposite
|
// - the element graph pushed while starting would be popped in finishing/Entity/finishingComposite
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startingCompositeElement(CompositionElementDefinition compositeElementDefinition) {
|
||||||
|
System.out.println(
|
||||||
|
String.format(
|
||||||
|
"%s Starting composite collection element for (%s)",
|
||||||
|
StringHelper.repeat( ">>", fetchOwnerStack.size() ),
|
||||||
|
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishingCompositeElement(CompositionElementDefinition compositeElementDefinition) {
|
||||||
|
// pop the current fetch owner, and make sure what we just popped represents this composition
|
||||||
|
final FetchOwner poppedFetchOwner = popFromStack();
|
||||||
|
|
||||||
|
if ( ! CompositeElementGraph.class.isInstance( poppedFetchOwner ) ) {
|
||||||
|
throw new WalkingException( "Mismatched FetchOwner from stack on pop" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE : not much else we can really check here atm since on the walking spi side we do not have path
|
||||||
|
|
||||||
|
log.tracef(
|
||||||
|
"%s Finished composite element for : %s",
|
||||||
|
StringHelper.repeat( "<<", fetchOwnerStack.size() ),
|
||||||
|
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void finishingCollection(CollectionDefinition collectionDefinition) {
|
public void finishingCollection(CollectionDefinition collectionDefinition) {
|
||||||
// pop the current fetch owner, and make sure what we just popped represents this collection
|
// pop the current fetch owner, and make sure what we just popped represents this collection
|
||||||
|
@ -487,15 +529,13 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
implements FetchOwner, EntityReference, FetchStackAware {
|
implements FetchOwner, EntityReference, FetchStackAware {
|
||||||
|
|
||||||
protected final EntityReference entityReference;
|
protected final EntityReference entityReference;
|
||||||
private final PropertyPath propertyPath;
|
|
||||||
|
|
||||||
protected final List<EntityFetch> identifierFetches = new ArrayList<EntityFetch>();
|
protected final List<AbstractSingularAttributeFetch> identifierFetches = new ArrayList<AbstractSingularAttributeFetch>();
|
||||||
protected final Map<EntityFetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap
|
protected final Map<AbstractSingularAttributeFetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap
|
||||||
= new HashMap<EntityFetch, HydratedCompoundValueHandler>();
|
= new HashMap<AbstractSingularAttributeFetch, HydratedCompoundValueHandler>();
|
||||||
|
|
||||||
public AbstractIdentifierAttributeCollector(EntityReference entityReference) {
|
public AbstractIdentifierAttributeCollector(EntityReference entityReference) {
|
||||||
this.entityReference = entityReference;
|
this.entityReference = entityReference;
|
||||||
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath().append( "<id>" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -513,6 +553,11 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
return entityReference.getEntityPersister();
|
return entityReference.getEntityPersister();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNullable(Fetch fetch) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IdentifierDescription getIdentifierDescription() {
|
public IdentifierDescription getIdentifierDescription() {
|
||||||
return entityReference.getIdentifierDescription();
|
return entityReference.getIdentifierDescription();
|
||||||
|
@ -533,7 +578,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||||
// we have a key-many-to-one
|
// we have a key-many-to-one
|
||||||
//
|
//
|
||||||
// IMPL NOTE: we pass ourselves as the FetchOwner which will route the fetch back throw our #addFetch
|
// IMPL NOTE: we pass ourselves as the FetchOwner which will route the fetch back through our #addFetch
|
||||||
// impl. We collect them there and later build the IdentifierDescription
|
// impl. We collect them there and later build the IdentifierDescription
|
||||||
final EntityFetch fetch = LoadPlanBuildingHelper.buildStandardEntityFetch(
|
final EntityFetch fetch = LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||||
this,
|
this,
|
||||||
|
@ -551,7 +596,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
CompositionDefinition attributeDefinition, LoadPlanBuildingContext loadPlanBuildingContext) {
|
CompositionDefinition attributeDefinition, LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||||
// nested composition. Unusual, but not disallowed.
|
// nested composition. Unusual, but not disallowed.
|
||||||
//
|
//
|
||||||
// IMPL NOTE: we pass ourselves as the FetchOwner which will route the fetch back throw our #addFetch
|
// IMPL NOTE: we pass ourselves as the FetchOwner which will route the fetch back through our #addFetch
|
||||||
// impl. We collect them there and later build the IdentifierDescription
|
// impl. We collect them there and later build the IdentifierDescription
|
||||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch(
|
return LoadPlanBuildingHelper.buildStandardCompositeFetch(
|
||||||
this,
|
this,
|
||||||
|
@ -570,7 +615,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addFetch(Fetch fetch) {
|
public void addFetch(Fetch fetch) {
|
||||||
identifierFetches.add( (EntityFetch) fetch );
|
identifierFetches.add( (AbstractSingularAttributeFetch) fetch );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -588,11 +633,6 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
return ( (FetchOwner) entityReference ).retrieveFetchSourcePersister();
|
return ( (FetchOwner) entityReference ).retrieveFetchSourcePersister();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PropertyPath getPropertyPath() {
|
|
||||||
return propertyPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
||||||
throw new WalkingException(
|
throw new WalkingException(
|
||||||
|
@ -601,44 +641,144 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static abstract class AbstractCompositeIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
|
||||||
|
|
||||||
|
public AbstractCompositeIdentifierAttributeCollector(EntityReference entityReference) {
|
||||||
|
super( entityReference );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected static class EncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
|
protected static class EncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
|
||||||
|
private final PropertyPath propertyPath;
|
||||||
|
|
||||||
public EncapsulatedIdentifierAttributeCollector(EntityReference entityReference) {
|
public EncapsulatedIdentifierAttributeCollector(EntityReference entityReference) {
|
||||||
super( entityReference );
|
super( entityReference );
|
||||||
|
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IdentifierDescription buildIdentifierDescription() {
|
protected IdentifierDescription buildIdentifierDescription() {
|
||||||
return new IdentifierDescriptionImpl(
|
return new IdentifierDescriptionImpl(
|
||||||
entityReference,
|
entityReference,
|
||||||
identifierFetches.toArray( new EntityFetch[ identifierFetches.size() ] ),
|
identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType(Fetch fetch) {
|
||||||
|
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
|
@Override
|
||||||
public NonEncapsulatedIdentifierAttributeCollector(EntityReference entityReference) {
|
public String[] getColumnNames(Fetch fetch) {
|
||||||
|
return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertyPath getPropertyPath() {
|
||||||
|
return propertyPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class EncapsulatedCompositeIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector {
|
||||||
|
private final PropertyPath propertyPath;
|
||||||
|
|
||||||
|
public EncapsulatedCompositeIdentifierAttributeCollector(EntityReference entityReference) {
|
||||||
super( entityReference );
|
super( entityReference );
|
||||||
|
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IdentifierDescription buildIdentifierDescription() {
|
protected IdentifierDescription buildIdentifierDescription() {
|
||||||
return new IdentifierDescriptionImpl(
|
return new IdentifierDescriptionImpl(
|
||||||
entityReference,
|
entityReference,
|
||||||
identifierFetches.toArray( new EntityFetch[ identifierFetches.size() ] ),
|
identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertyPath getPropertyPath() {
|
||||||
|
return propertyPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType(Fetch fetch) {
|
||||||
|
if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format(
|
||||||
|
"Fetch owner property name [%s] is not the same as the identifier property name [%s].",
|
||||||
|
fetch.getOwnerPropertyName(),
|
||||||
|
entityReference.getEntityPersister().getIdentifierPropertyName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return entityReference.getEntityPersister().getIdentifierType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getColumnNames(Fetch fetch) {
|
||||||
|
return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector {
|
||||||
|
private final PropertyPath propertyPath;
|
||||||
|
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||||
|
|
||||||
|
public NonEncapsulatedIdentifierAttributeCollector(EntityReference entityReference) {
|
||||||
|
super( entityReference );
|
||||||
|
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath().append( "<id>" );
|
||||||
|
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
|
||||||
|
entityReference.getEntityPersister().getFactory(),
|
||||||
|
(CompositeType) entityReference.getEntityPersister().getIdentifierType(),
|
||||||
|
( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IdentifierDescription buildIdentifierDescription() {
|
||||||
|
return new IdentifierDescriptionImpl(
|
||||||
|
entityReference,
|
||||||
|
identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ),
|
||||||
fetchToHydratedStateExtractorMap
|
fetchToHydratedStateExtractorMap
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertyPath getPropertyPath() {
|
||||||
|
return propertyPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Type getType(Fetch fetch) {
|
||||||
|
if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format(
|
||||||
|
"Fetch owner property name [%s] is not the same as the identifier property name [%s].",
|
||||||
|
fetch.getOwnerPropertyName(),
|
||||||
|
entityReference.getEntityPersister().getIdentifierPropertyName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return fetchOwnerDelegate.getType( fetch );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getColumnNames(Fetch fetch) {
|
||||||
|
return fetchOwnerDelegate.getColumnNames( fetch );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class IdentifierDescriptionImpl implements IdentifierDescription {
|
private static class IdentifierDescriptionImpl implements IdentifierDescription {
|
||||||
private final EntityReference entityReference;
|
private final EntityReference entityReference;
|
||||||
private final EntityFetch[] identifierFetches;
|
private final AbstractSingularAttributeFetch[] identifierFetches;
|
||||||
private final Map<EntityFetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap;
|
private final Map<AbstractSingularAttributeFetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap;
|
||||||
|
|
||||||
private IdentifierDescriptionImpl(
|
private IdentifierDescriptionImpl(
|
||||||
EntityReference entityReference, EntityFetch[] identifierFetches,
|
EntityReference entityReference,
|
||||||
Map<EntityFetch, HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap) {
|
AbstractSingularAttributeFetch[] identifierFetches,
|
||||||
|
Map<AbstractSingularAttributeFetch, HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap) {
|
||||||
this.entityReference = entityReference;
|
this.entityReference = entityReference;
|
||||||
this.identifierFetches = identifierFetches;
|
this.identifierFetches = identifierFetches;
|
||||||
this.fetchToHydratedStateExtractorMap = fetchToHydratedStateExtractorMap;
|
this.fetchToHydratedStateExtractorMap = fetchToHydratedStateExtractorMap;
|
||||||
|
@ -656,14 +796,14 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
final Object ownerIdentifierHydratedState = ownerIdentifierResolutionContext.getHydratedForm();
|
final Object ownerIdentifierHydratedState = ownerIdentifierResolutionContext.getHydratedForm();
|
||||||
|
|
||||||
if ( ownerIdentifierHydratedState != null ) {
|
if ( ownerIdentifierHydratedState != null ) {
|
||||||
for ( EntityFetch fetch : identifierFetches ) {
|
for ( AbstractSingularAttributeFetch fetch : identifierFetches ) {
|
||||||
|
if ( fetch instanceof EntityFetch ) {
|
||||||
final IdentifierResolutionContext identifierResolutionContext =
|
final IdentifierResolutionContext identifierResolutionContext =
|
||||||
context.getIdentifierResolutionContext( fetch );
|
context.getIdentifierResolutionContext( (EntityFetch) fetch );
|
||||||
// if the identifier was already hydrated, nothing to do
|
// if the identifier was already hydrated, nothing to do
|
||||||
if ( identifierResolutionContext.getHydratedForm() != null ) {
|
if ( identifierResolutionContext.getHydratedForm() != null ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to extract the sub-hydrated value from the owners tuple array
|
// try to extract the sub-hydrated value from the owners tuple array
|
||||||
if ( fetchToHydratedStateExtractorMap != null && ownerIdentifierHydratedState != null ) {
|
if ( fetchToHydratedStateExtractorMap != null && ownerIdentifierHydratedState != null ) {
|
||||||
Serializable extracted = (Serializable) fetchToHydratedStateExtractorMap.get( fetch )
|
Serializable extracted = (Serializable) fetchToHydratedStateExtractorMap.get( fetch )
|
||||||
|
@ -675,6 +815,10 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
// if we can't, then read from result set
|
// if we can't, then read from result set
|
||||||
fetch.hydrate( resultSet, context );
|
fetch.hydrate( resultSet, context );
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
throw new NotYetImplementedException( "Cannot hydrate identifier Fetch that is not an EntityFetch" );
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,15 +833,8 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityKey resolve(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
|
public EntityKey resolve(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
|
||||||
for ( EntityFetch fetch : identifierFetches ) {
|
for ( AbstractSingularAttributeFetch fetch : identifierFetches ) {
|
||||||
final IdentifierResolutionContext identifierResolutionContext =
|
resolveIdentifierFetch( resultSet, context, fetch );
|
||||||
context.getIdentifierResolutionContext( fetch );
|
|
||||||
if ( identifierResolutionContext.getEntityKey() != null ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityKey fetchKey = fetch.resolveInIdentifier( resultSet, context );
|
|
||||||
identifierResolutionContext.registerEntityKey( fetchKey );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final IdentifierResolutionContext ownerIdentifierResolutionContext =
|
final IdentifierResolutionContext ownerIdentifierResolutionContext =
|
||||||
|
@ -710,6 +847,28 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void resolveIdentifierFetch(
|
||||||
|
ResultSet resultSet,
|
||||||
|
ResultSetProcessingContext context,
|
||||||
|
AbstractSingularAttributeFetch fetch) throws SQLException {
|
||||||
|
if ( fetch instanceof EntityFetch ) {
|
||||||
|
EntityFetch entityFetch = (EntityFetch) fetch;
|
||||||
|
final IdentifierResolutionContext identifierResolutionContext =
|
||||||
|
context.getIdentifierResolutionContext( entityFetch );
|
||||||
|
if ( identifierResolutionContext.getEntityKey() != null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityKey fetchKey = entityFetch.resolveInIdentifier( resultSet, context );
|
||||||
|
identifierResolutionContext.registerEntityKey( fetchKey );
|
||||||
|
}
|
||||||
|
else if ( fetch instanceof CompositeFetch ) {
|
||||||
|
for ( Fetch subFetch : fetch.getFetches() ) {
|
||||||
|
resolveIdentifierFetch( resultSet, context, (AbstractSingularAttributeFetch) subFetch );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class MDCStack {
|
public static class MDCStack {
|
||||||
private ArrayDeque<PropertyPath> pathStack = new ArrayDeque<PropertyPath>();
|
private ArrayDeque<PropertyPath> pathStack = new ArrayDeque<PropertyPath>();
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ public class ManyToOne extends ToOne {
|
||||||
public Type getType() throws MappingException {
|
public Type getType() throws MappingException {
|
||||||
return getMappings().getTypeResolver().getTypeFactory().manyToOne(
|
return getMappings().getTypeResolver().getTypeFactory().manyToOne(
|
||||||
getReferencedEntityName(),
|
getReferencedEntityName(),
|
||||||
|
referenceToPrimaryKey,
|
||||||
getReferencedPropertyName(),
|
getReferencedPropertyName(),
|
||||||
isLazy(),
|
isLazy(),
|
||||||
isUnwrapProxy(),
|
isUnwrapProxy(),
|
||||||
|
|
|
@ -47,6 +47,7 @@ public class OneToMany implements Value {
|
||||||
private EntityType getEntityType() {
|
private EntityType getEntityType() {
|
||||||
return mappings.getTypeResolver().getTypeFactory().manyToOne(
|
return mappings.getTypeResolver().getTypeFactory().manyToOne(
|
||||||
getReferencedEntityName(),
|
getReferencedEntityName(),
|
||||||
|
true,
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -70,6 +70,7 @@ public class OneToOne extends ToOne {
|
||||||
return getMappings().getTypeResolver().getTypeFactory().specialOneToOne(
|
return getMappings().getTypeResolver().getTypeFactory().specialOneToOne(
|
||||||
getReferencedEntityName(),
|
getReferencedEntityName(),
|
||||||
foreignKeyType,
|
foreignKeyType,
|
||||||
|
referenceToPrimaryKey,
|
||||||
referencedPropertyName,
|
referencedPropertyName,
|
||||||
isLazy(),
|
isLazy(),
|
||||||
isUnwrapProxy(),
|
isUnwrapProxy(),
|
||||||
|
@ -81,6 +82,7 @@ public class OneToOne extends ToOne {
|
||||||
return getMappings().getTypeResolver().getTypeFactory().oneToOne(
|
return getMappings().getTypeResolver().getTypeFactory().oneToOne(
|
||||||
getReferencedEntityName(),
|
getReferencedEntityName(),
|
||||||
foreignKeyType,
|
foreignKeyType,
|
||||||
|
referenceToPrimaryKey,
|
||||||
referencedPropertyName,
|
referencedPropertyName,
|
||||||
isLazy(),
|
isLazy(),
|
||||||
isUnwrapProxy(),
|
isUnwrapProxy(),
|
||||||
|
|
|
@ -40,6 +40,7 @@ public abstract class ToOne extends SimpleValue implements Fetchable {
|
||||||
private String referencedEntityName;
|
private String referencedEntityName;
|
||||||
private boolean lazy = true;
|
private boolean lazy = true;
|
||||||
protected boolean unwrapProxy;
|
protected boolean unwrapProxy;
|
||||||
|
protected boolean referenceToPrimaryKey = true;
|
||||||
|
|
||||||
protected ToOne(Mappings mappings, Table table) {
|
protected ToOne(Mappings mappings, Table table) {
|
||||||
super( mappings, table );
|
super( mappings, table );
|
||||||
|
@ -111,4 +112,12 @@ public abstract class ToOne extends SimpleValue implements Fetchable {
|
||||||
this.unwrapProxy = unwrapProxy;
|
this.unwrapProxy = unwrapProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isReferenceToPrimaryKey() {
|
||||||
|
return referenceToPrimaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReferenceToPrimaryKey(boolean referenceToPrimaryKey) {
|
||||||
|
this.referenceToPrimaryKey = referenceToPrimaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||||
import org.hibernate.cache.spi.access.AccessType;
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
import org.hibernate.cfg.NamingStrategy;
|
import org.hibernate.cfg.NamingStrategy;
|
||||||
|
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||||
import org.hibernate.engine.spi.FilterDefinition;
|
import org.hibernate.engine.spi.FilterDefinition;
|
||||||
import org.hibernate.engine.spi.NamedQueryDefinition;
|
import org.hibernate.engine.spi.NamedQueryDefinition;
|
||||||
|
@ -115,6 +116,8 @@ public interface Metadata {
|
||||||
|
|
||||||
public Iterable<NamedQueryDefinition> getNamedQueryDefinitions();
|
public Iterable<NamedQueryDefinition> getNamedQueryDefinitions();
|
||||||
|
|
||||||
|
public Map<String, NamedEntityGraphDefinition> getNamedEntityGraphMap();
|
||||||
|
|
||||||
public Iterable<NamedSQLQueryDefinition> getNamedNativeQueryDefinitions();
|
public Iterable<NamedSQLQueryDefinition> getNamedNativeQueryDefinitions();
|
||||||
|
|
||||||
public Map<String, ResultSetMappingDefinition> getResultSetMappingDefinitions();
|
public Map<String, ResultSetMappingDefinition> getResultSetMappingDefinitions();
|
||||||
|
|
|
@ -47,6 +47,7 @@ import org.hibernate.boot.spi.CacheRegionDefinition;
|
||||||
import org.hibernate.cache.spi.access.AccessType;
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
import org.hibernate.cfg.NamingStrategy;
|
import org.hibernate.cfg.NamingStrategy;
|
||||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||||
|
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
@ -134,7 +135,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
private final MappingDefaults mappingDefaults;
|
private final MappingDefaults mappingDefaults;
|
||||||
private final ObjectNameNormalizer nameNormalizer;
|
private final ObjectNameNormalizer nameNormalizer;
|
||||||
|
|
||||||
private Map<String, TypeDefinition> typeDefinitionMap = new HashMap<String, TypeDefinition>();
|
private final Map<String, TypeDefinition> typeDefinitionMap = new HashMap<String, TypeDefinition>();
|
||||||
private Map<String, FilterDefinition> filterDefinitionMap = new HashMap<String, FilterDefinition>();
|
private Map<String, FilterDefinition> filterDefinitionMap = new HashMap<String, FilterDefinition>();
|
||||||
|
|
||||||
private Map<String, EntityBinding> entityBindingMap = new HashMap<String, EntityBinding>();
|
private Map<String, EntityBinding> entityBindingMap = new HashMap<String, EntityBinding>();
|
||||||
|
@ -145,6 +146,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
private Map<String, NamedQueryDefinition> namedQueryDefs = new HashMap<String, NamedQueryDefinition>();
|
private Map<String, NamedQueryDefinition> namedQueryDefs = new HashMap<String, NamedQueryDefinition>();
|
||||||
private Map<String, NamedSQLQueryDefinition> namedNativeQueryDefs = new HashMap<String, NamedSQLQueryDefinition>();
|
private Map<String, NamedSQLQueryDefinition> namedNativeQueryDefs = new HashMap<String, NamedSQLQueryDefinition>();
|
||||||
private Map<String, ResultSetMappingDefinition> resultSetMappings = new HashMap<String, ResultSetMappingDefinition>();
|
private Map<String, ResultSetMappingDefinition> resultSetMappings = new HashMap<String, ResultSetMappingDefinition>();
|
||||||
|
private final Map<String, NamedEntityGraphDefinition> namedEntityGraphMap = new HashMap<String, NamedEntityGraphDefinition>( );
|
||||||
|
|
||||||
private boolean globallyQuotedIdentifiers = false;
|
private boolean globallyQuotedIdentifiers = false;
|
||||||
|
|
||||||
|
@ -375,6 +377,19 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
||||||
return typeDefinitionMap.get( registrationKey );
|
return typeDefinitionMap.get( registrationKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addNamedEntityGraph(NamedEntityGraphDefinition definition) {
|
||||||
|
final String name = definition.getRegisteredName();
|
||||||
|
final NamedEntityGraphDefinition previous = namedEntityGraphMap.put( name, definition );
|
||||||
|
if ( previous != null ) {
|
||||||
|
throw new DuplicateMappingException( "NamedEntityGraph", name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, NamedEntityGraphDefinition> getNamedEntityGraphMap() {
|
||||||
|
return namedEntityGraphMap;
|
||||||
|
}
|
||||||
|
|
||||||
// filter definitions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// filter definitions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
package org.hibernate.metamodel.spi;
|
package org.hibernate.metamodel.spi;
|
||||||
|
|
||||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||||
|
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||||
import org.hibernate.engine.spi.FilterDefinition;
|
import org.hibernate.engine.spi.FilterDefinition;
|
||||||
import org.hibernate.engine.spi.Mapping;
|
import org.hibernate.engine.spi.Mapping;
|
||||||
|
@ -69,6 +70,8 @@ public interface MetadataImplementor extends Metadata, BindingContext, Mapping {
|
||||||
|
|
||||||
public void addNamedNativeQuery(NamedSQLQueryDefinition def);
|
public void addNamedNativeQuery(NamedSQLQueryDefinition def);
|
||||||
|
|
||||||
|
public void addNamedEntityGraph(NamedEntityGraphDefinition def);
|
||||||
|
|
||||||
public void addNamedQuery(NamedQueryDefinition def);
|
public void addNamedQuery(NamedQueryDefinition def);
|
||||||
|
|
||||||
public void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition);
|
public void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition);
|
||||||
|
|
|
@ -101,10 +101,14 @@ import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Loadable;
|
import org.hibernate.persister.entity.Loadable;
|
||||||
import org.hibernate.persister.entity.PropertyMapping;
|
import org.hibernate.persister.entity.PropertyMapping;
|
||||||
import org.hibernate.persister.entity.Queryable;
|
import org.hibernate.persister.entity.Queryable;
|
||||||
|
import org.hibernate.persister.walking.internal.CompositionSingularSubAttributesHelper;
|
||||||
|
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.AttributeSource;
|
||||||
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
|
||||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
import org.hibernate.sql.Alias;
|
import org.hibernate.sql.Alias;
|
||||||
|
@ -2342,7 +2346,6 @@ public abstract class AbstractCollectionPersister
|
||||||
|
|
||||||
public abstract FilterAliasGenerator getFilterAliasGenerator(final String rootAlias);
|
public abstract FilterAliasGenerator getFilterAliasGenerator(final String rootAlias);
|
||||||
|
|
||||||
|
|
||||||
// ColectionDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ColectionDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2408,12 +2411,42 @@ public abstract class AbstractCollectionPersister
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompositionDefinition toCompositeDefinition() {
|
public CompositionElementDefinition toCompositeElementDefinition() {
|
||||||
|
final String propertyName = role.substring( entityName.length() + 1 );
|
||||||
|
final int propertyIndex = ownerPersister.getEntityMetamodel().getPropertyIndex( propertyName );
|
||||||
|
|
||||||
if ( ! getType().isComponentType() ) {
|
if ( ! getType().isComponentType() ) {
|
||||||
throw new IllegalStateException( "Cannot treat entity collection element type as composite" );
|
throw new IllegalStateException( "Cannot treat entity collection element type as composite" );
|
||||||
}
|
}
|
||||||
// todo : implement
|
|
||||||
throw new NotYetImplementedException();
|
return new CompositionElementDefinition() {
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return getElementType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeSource getSource() {
|
||||||
|
// TODO: what if this is a collection w/in an encapsulated composition attribute?
|
||||||
|
// should return the encapsulated composition attribute instead???
|
||||||
|
return getOwnerEntityPersister();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<AttributeDefinition> getAttributes() {
|
||||||
|
return CompositionSingularSubAttributesHelper.getCompositionElementSubAttributes( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CollectionDefinition getCollectionDefinition() {
|
||||||
|
return AbstractCollectionPersister.this;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,6 @@ import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl;
|
||||||
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
|
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
|
||||||
import org.hibernate.cache.spi.entry.StructuredCacheEntry;
|
import org.hibernate.cache.spi.entry.StructuredCacheEntry;
|
||||||
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
|
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
|
||||||
import org.hibernate.cfg.NotYetImplementedException;
|
|
||||||
import org.hibernate.dialect.lock.LockingStrategy;
|
import org.hibernate.dialect.lock.LockingStrategy;
|
||||||
import org.hibernate.engine.OptimisticLockStyle;
|
import org.hibernate.engine.OptimisticLockStyle;
|
||||||
import org.hibernate.engine.internal.StatefulPersistenceContext;
|
import org.hibernate.engine.internal.StatefulPersistenceContext;
|
||||||
|
@ -120,12 +119,9 @@ import org.hibernate.metamodel.spi.relational.DerivedValue;
|
||||||
import org.hibernate.metamodel.spi.relational.Table;
|
import org.hibernate.metamodel.spi.relational.Table;
|
||||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||||
import org.hibernate.metamodel.spi.relational.Value;
|
import org.hibernate.metamodel.spi.relational.Value;
|
||||||
|
import org.hibernate.persister.walking.internal.EntityIdentifierDefinitionHelper;
|
||||||
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||||
import org.hibernate.persister.walking.spi.AttributeSource;
|
|
||||||
import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition;
|
|
||||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
|
||||||
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||||
import org.hibernate.persister.walking.spi.NonEncapsulatedEntityIdentifierDefinition;
|
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
import org.hibernate.property.BackrefPropertyAccessor;
|
import org.hibernate.property.BackrefPropertyAccessor;
|
||||||
import org.hibernate.sql.Alias;
|
import org.hibernate.sql.Alias;
|
||||||
|
@ -5290,80 +5286,20 @@ public abstract class AbstractEntityPersister
|
||||||
final Type idType = getIdentifierType();
|
final Type idType = getIdentifierType();
|
||||||
|
|
||||||
if ( !idType.isComponentType() ) {
|
if ( !idType.isComponentType() ) {
|
||||||
entityIdentifierDefinition = buildEncapsulatedIdentifierDefinition();
|
entityIdentifierDefinition =
|
||||||
|
EntityIdentifierDefinitionHelper.buildSimpleEncapsulatedIdentifierDefinition( this );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final CompositeType cidType = (CompositeType) idType;
|
final CompositeType cidType = (CompositeType) idType;
|
||||||
if ( !cidType.isEmbedded() ) {
|
if ( !cidType.isEmbedded() ) {
|
||||||
entityIdentifierDefinition = buildEncapsulatedIdentifierDefinition();
|
entityIdentifierDefinition =
|
||||||
|
EntityIdentifierDefinitionHelper.buildEncapsulatedCompositeIdentifierDefinition( this );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
entityIdentifierDefinition = new NonEncapsulatedEntityIdentifierDefinition() {
|
entityIdentifierDefinition =
|
||||||
@Override
|
EntityIdentifierDefinitionHelper.buildNonEncapsulatedCompositeIdentifierDefinition( this );
|
||||||
public Iterable<AttributeDefinition> getAttributes() {
|
|
||||||
// todo : implement
|
|
||||||
throw new NotYetImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class getSeparateIdentifierMappingClass() {
|
|
||||||
// todo : implement
|
|
||||||
throw new NotYetImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEncapsulated() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EntityDefinition getEntityDefinition() {
|
|
||||||
return AbstractEntityPersister.this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private EntityIdentifierDefinition buildEncapsulatedIdentifierDefinition() {
|
|
||||||
final AttributeDefinition simpleIdentifierAttributeAdapter = new AttributeDefinition() {
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return entityMetamodel.getIdentifierProperty().getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return entityMetamodel.getIdentifierProperty().getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AttributeSource getSource() {
|
|
||||||
return AbstractEntityPersister.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "<identifier-property:" + getName() + ">";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return new EncapsulatedEntityIdentifierDefinition() {
|
|
||||||
@Override
|
|
||||||
public AttributeDefinition getAttributeDefinition() {
|
|
||||||
return simpleIdentifierAttributeAdapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEncapsulated() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EntityDefinition getEntityDefinition() {
|
|
||||||
return AbstractEntityPersister.this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void collectAttributeDefinitions() {
|
private void collectAttributeDefinitions() {
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
package org.hibernate.persister.walking.internal;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
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.CascadeStyles;
|
||||||
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
|
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||||
|
import org.hibernate.loader.PropertyPath;
|
||||||
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
|
import org.hibernate.persister.entity.AbstractEntityPersister;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
|
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
||||||
|
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.AssociationKey;
|
||||||
|
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.AttributeSource;
|
||||||
|
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.WalkingException;
|
||||||
|
import org.hibernate.type.AssociationType;
|
||||||
|
import org.hibernate.type.CompositeType;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public class CompositionSingularSubAttributesHelper {
|
||||||
|
|
||||||
|
public static Iterable<AttributeDefinition> getIdentifierSubAttributes(
|
||||||
|
final AbstractEntityPersister entityPersister) {
|
||||||
|
return getSingularSubAttributes(
|
||||||
|
entityPersister,
|
||||||
|
entityPersister,
|
||||||
|
(CompositeType) entityPersister.getIdentifierType(),
|
||||||
|
entityPersister.getTableName(),
|
||||||
|
entityPersister.getRootTableIdentifierColumnNames()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Iterable<AttributeDefinition> getCompositionElementSubAttributes(
|
||||||
|
CompositionElementDefinition compositionElementDefinition) {
|
||||||
|
final QueryableCollection collectionPersister =
|
||||||
|
(QueryableCollection) compositionElementDefinition.getCollectionDefinition().getCollectionPersister();
|
||||||
|
return getSingularSubAttributes(
|
||||||
|
compositionElementDefinition.getSource(),
|
||||||
|
(OuterJoinLoadable) collectionPersister.getOwnerEntityPersister(),
|
||||||
|
(CompositeType) collectionPersister.getElementType(),
|
||||||
|
collectionPersister.getTableName(),
|
||||||
|
collectionPersister.getElementColumnNames()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Iterable<AttributeDefinition> getSingularSubAttributes(
|
||||||
|
final AttributeSource source,
|
||||||
|
final OuterJoinLoadable ownerEntityPersister,
|
||||||
|
final CompositeType compositeType,
|
||||||
|
final String lhsTableName,
|
||||||
|
final String[] lhsColumns) {
|
||||||
|
return new Iterable<AttributeDefinition>() {
|
||||||
|
@Override
|
||||||
|
public Iterator<AttributeDefinition> iterator() {
|
||||||
|
return new Iterator<AttributeDefinition>() {
|
||||||
|
private final int numberOfAttributes = compositeType.getSubtypes().length;
|
||||||
|
private int currentSubAttributeNumber = 0;
|
||||||
|
private int currentColumnPosition = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return currentSubAttributeNumber < numberOfAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeDefinition next() {
|
||||||
|
final int subAttributeNumber = currentSubAttributeNumber;
|
||||||
|
currentSubAttributeNumber++;
|
||||||
|
|
||||||
|
final String name = compositeType.getPropertyNames()[subAttributeNumber];
|
||||||
|
final Type type = compositeType.getSubtypes()[subAttributeNumber];
|
||||||
|
|
||||||
|
final int columnPosition = currentColumnPosition;
|
||||||
|
final int columnSpan = type.getColumnSpan( ownerEntityPersister.getFactory() );
|
||||||
|
final String[] subAttributeLhsColumns = ArrayHelper.slice( lhsColumns, columnPosition, columnSpan );
|
||||||
|
|
||||||
|
currentColumnPosition += columnSpan;
|
||||||
|
|
||||||
|
if ( type.isAssociationType() ) {
|
||||||
|
final AssociationType aType = (AssociationType) type;
|
||||||
|
return new AssociationAttributeDefinition() {
|
||||||
|
@Override
|
||||||
|
public AssociationKey getAssociationKey() {
|
||||||
|
/* TODO: is this always correct? */
|
||||||
|
//return new AssociationKey(
|
||||||
|
// joinable.getTableName(),
|
||||||
|
// JoinHelper.getRHSColumnNames( aType, getEntityPersister().getFactory() )
|
||||||
|
//);
|
||||||
|
return new AssociationKey(
|
||||||
|
lhsTableName,
|
||||||
|
subAttributeLhsColumns
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCollection() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityDefinition toEntityDefinition() {
|
||||||
|
return (EntityPersister) aType.getAssociatedJoinable( ownerEntityPersister.getFactory() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CollectionDefinition toCollectionDefinition() {
|
||||||
|
throw new WalkingException( "A collection cannot be mapped to a composite ID sub-attribute." );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) {
|
||||||
|
return new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CascadeStyle determineCascadeStyle() {
|
||||||
|
return CascadeStyles.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HydratedCompoundValueHandler getHydratedCompoundValueExtractor() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeSource getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if ( type.isComponentType() ) {
|
||||||
|
return new CompositionDefinition() {
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeSource getSource() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<AttributeDefinition> getAttributes() {
|
||||||
|
return CompositionSingularSubAttributesHelper.getSingularSubAttributes(
|
||||||
|
this,
|
||||||
|
ownerEntityPersister,
|
||||||
|
(CompositeType) type,
|
||||||
|
lhsTableName,
|
||||||
|
subAttributeLhsColumns
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new AttributeDefinition() {
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeSource getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException( "Remove operation not supported here" );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.persister.walking.internal;
|
||||||
|
|
||||||
|
import org.hibernate.persister.entity.AbstractEntityPersister;
|
||||||
|
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.AttributeSource;
|
||||||
|
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.NonEncapsulatedEntityIdentifierDefinition;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public class EntityIdentifierDefinitionHelper {
|
||||||
|
|
||||||
|
public static EntityIdentifierDefinition buildSimpleEncapsulatedIdentifierDefinition(final AbstractEntityPersister entityPersister) {
|
||||||
|
return new EncapsulatedEntityIdentifierDefinition() {
|
||||||
|
@Override
|
||||||
|
public AttributeDefinition getAttributeDefinition() {
|
||||||
|
return new AttributeDefinitionAdapter( entityPersister);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEncapsulated() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityDefinition getEntityDefinition() {
|
||||||
|
return entityPersister;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EntityIdentifierDefinition buildEncapsulatedCompositeIdentifierDefinition(
|
||||||
|
final AbstractEntityPersister entityPersister) {
|
||||||
|
|
||||||
|
return new EncapsulatedEntityIdentifierDefinition() {
|
||||||
|
@Override
|
||||||
|
public AttributeDefinition getAttributeDefinition() {
|
||||||
|
return new CompositionDefinitionAdapter( entityPersister );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEncapsulated() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityDefinition getEntityDefinition() {
|
||||||
|
return entityPersister;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EntityIdentifierDefinition buildNonEncapsulatedCompositeIdentifierDefinition(final AbstractEntityPersister entityPersister) {
|
||||||
|
return new NonEncapsulatedEntityIdentifierDefinition() {
|
||||||
|
@Override
|
||||||
|
public Iterable<AttributeDefinition> getAttributes() {
|
||||||
|
return CompositionSingularSubAttributesHelper.getIdentifierSubAttributes( entityPersister );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class getSeparateIdentifierMappingClass() {
|
||||||
|
return entityPersister.getEntityMetamodel().getIdentifierProperty().getType().getReturnedClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEncapsulated() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityDefinition getEntityDefinition() {
|
||||||
|
return entityPersister;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AttributeDefinitionAdapter implements AttributeDefinition {
|
||||||
|
private final AbstractEntityPersister entityPersister;
|
||||||
|
|
||||||
|
AttributeDefinitionAdapter(AbstractEntityPersister entityPersister) {
|
||||||
|
this.entityPersister = entityPersister;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return entityPersister.getEntityMetamodel().getIdentifierProperty().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return entityPersister.getEntityMetamodel().getIdentifierProperty().getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AttributeSource getSource() {
|
||||||
|
return entityPersister;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "<identifier-property:" + getName() + ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractEntityPersister getEntityPersister() {
|
||||||
|
return entityPersister;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CompositionDefinitionAdapter extends AttributeDefinitionAdapter implements CompositionDefinition {
|
||||||
|
|
||||||
|
CompositionDefinitionAdapter(AbstractEntityPersister entityPersister) {
|
||||||
|
super( entityPersister );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "<identifier-property:" + getName() + ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<AttributeDefinition> getAttributes() {
|
||||||
|
return CompositionSingularSubAttributesHelper.getIdentifierSubAttributes( getEntityPersister() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,7 +42,7 @@ import org.hibernate.type.AssociationType;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class Helper {
|
public class FetchStrategyHelper {
|
||||||
/**
|
/**
|
||||||
* Determine the fetch-style (if one) explicitly set for this association via fetch profiles.
|
* Determine the fetch-style (if one) explicitly set for this association via fetch profiles.
|
||||||
* <p/>
|
* <p/>
|
|
@ -55,6 +55,9 @@ public interface AssociationVisitationStrategy {
|
||||||
public void startingComposite(CompositionDefinition compositionDefinition);
|
public void startingComposite(CompositionDefinition compositionDefinition);
|
||||||
public void finishingComposite(CompositionDefinition compositionDefinition);
|
public void finishingComposite(CompositionDefinition compositionDefinition);
|
||||||
|
|
||||||
|
public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition);
|
||||||
|
public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition);
|
||||||
|
|
||||||
public boolean startingAttribute(AttributeDefinition attributeDefinition);
|
public boolean startingAttribute(AttributeDefinition attributeDefinition);
|
||||||
public void finishingAttribute(AttributeDefinition attributeDefinition);
|
public void finishingAttribute(AttributeDefinition attributeDefinition);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,5 +35,5 @@ public interface CollectionElementDefinition {
|
||||||
|
|
||||||
public EntityDefinition toEntityDefinition();
|
public EntityDefinition toEntityDefinition();
|
||||||
|
|
||||||
public CompositionDefinition toCompositeDefinition();
|
public CompositionElementDefinition toCompositeElementDefinition();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.persister.walking.spi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public interface CompositionElementDefinition extends CompositionDefinition{
|
||||||
|
public CollectionDefinition getCollectionDefinition();
|
||||||
|
}
|
|
@ -114,10 +114,10 @@ public class MetadataDrivenModelGraphVisitor {
|
||||||
log.debug( "Visiting attribute path : " + subPath.getFullPath() );
|
log.debug( "Visiting attribute path : " + subPath.getFullPath() );
|
||||||
|
|
||||||
final boolean continueWalk;
|
final boolean continueWalk;
|
||||||
if ( attributeDefinition.getType().isAssociationType() ) {
|
if ( attributeDefinition.getType().isAssociationType() &&
|
||||||
continueWalk =
|
isDuplicateAssociationKey( ( (AssociationAttributeDefinition) attributeDefinition ).getAssociationKey() ) ) {
|
||||||
! isDuplicateAssociation( ( (AssociationAttributeDefinition) attributeDefinition ).getAssociationKey() ) &&
|
log.debug( "Property path deemed to be circular : " + subPath.getFullPath() );
|
||||||
strategy.startingAttribute( attributeDefinition );
|
continueWalk = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
continueWalk = strategy.startingAttribute( attributeDefinition );
|
continueWalk = strategy.startingAttribute( attributeDefinition );
|
||||||
|
@ -143,6 +143,8 @@ public class MetadataDrivenModelGraphVisitor {
|
||||||
private void visitAssociation(AssociationAttributeDefinition attribute) {
|
private void visitAssociation(AssociationAttributeDefinition attribute) {
|
||||||
// todo : do "too deep" checks; but see note about adding depth to PropertyPath
|
// todo : do "too deep" checks; but see note about adding depth to PropertyPath
|
||||||
|
|
||||||
|
addAssociationKey( attribute.getAssociationKey() );
|
||||||
|
|
||||||
if ( attribute.isCollection() ) {
|
if ( attribute.isCollection() ) {
|
||||||
visitCollectionDefinition( attribute.toCollectionDefinition() );
|
visitCollectionDefinition( attribute.toCollectionDefinition() );
|
||||||
}
|
}
|
||||||
|
@ -200,7 +202,7 @@ public class MetadataDrivenModelGraphVisitor {
|
||||||
strategy.startingCollectionElements( elementDefinition );
|
strategy.startingCollectionElements( elementDefinition );
|
||||||
|
|
||||||
if ( elementDefinition.getType().isComponentType() ) {
|
if ( elementDefinition.getType().isComponentType() ) {
|
||||||
visitCompositeDefinition( elementDefinition.toCompositeDefinition() );
|
visitCompositeElementDefinition( elementDefinition.toCompositeElementDefinition() );
|
||||||
}
|
}
|
||||||
else if ( elementDefinition.getType().isEntityType() ) {
|
else if ( elementDefinition.getType().isEntityType() ) {
|
||||||
visitEntityDefinition( elementDefinition.toEntityDefinition() );
|
visitEntityDefinition( elementDefinition.toEntityDefinition() );
|
||||||
|
@ -209,18 +211,37 @@ public class MetadataDrivenModelGraphVisitor {
|
||||||
strategy.finishingCollectionElements( elementDefinition );
|
strategy.finishingCollectionElements( elementDefinition );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void visitCompositeElementDefinition(CompositionElementDefinition compositionElementDefinition) {
|
||||||
|
strategy.startingCompositeElement( compositionElementDefinition );
|
||||||
|
|
||||||
|
visitAttributes( compositionElementDefinition );
|
||||||
|
|
||||||
|
strategy.finishingCompositeElement( compositionElementDefinition );
|
||||||
|
}
|
||||||
|
|
||||||
private final Set<AssociationKey> visitedAssociationKeys = new HashSet<AssociationKey>();
|
private final Set<AssociationKey> visitedAssociationKeys = new HashSet<AssociationKey>();
|
||||||
|
|
||||||
protected boolean isDuplicateAssociation(AssociationKey associationKey) {
|
/**
|
||||||
boolean isDuplicate = !visitedAssociationKeys.add( associationKey );
|
* Add association key to indicate the association is being visited.
|
||||||
if ( isDuplicate ) {
|
* @param associationKey - the association key.
|
||||||
log.debug( "Property path deemed to be circular : " + currentPropertyPath.getFullPath() );
|
* @throws WalkingException if the association with the specified association key
|
||||||
return true;
|
* has already been visited.
|
||||||
}
|
*/
|
||||||
else {
|
protected void addAssociationKey(AssociationKey associationKey) {
|
||||||
return false;
|
if ( ! visitedAssociationKeys.add( associationKey ) ) {
|
||||||
|
throw new WalkingException(
|
||||||
|
String.format( "Association has already been visited: %s", associationKey )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has an association with the specified key been visited already?
|
||||||
|
* @param associationKey - the association key.
|
||||||
|
* @return true, if the association with the specified association key has already been visited;
|
||||||
|
* false, otherwise.
|
||||||
|
*/
|
||||||
|
protected boolean isDuplicateAssociationKey(AssociationKey associationKey) {
|
||||||
|
return visitedAssociationKeys.contains( associationKey );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ public abstract class AbstractCompositeBasedAttribute
|
||||||
private final int ownerAttributeNumber;
|
private final int ownerAttributeNumber;
|
||||||
|
|
||||||
public AbstractCompositeBasedAttribute(
|
public AbstractCompositeBasedAttribute(
|
||||||
AbstractCompositionDefinition source,
|
AbstractCompositionAttribute source,
|
||||||
SessionFactoryImplementor sessionFactory,
|
SessionFactoryImplementor sessionFactory,
|
||||||
int attributeNumber,
|
int attributeNumber,
|
||||||
String attributeName,
|
String attributeName,
|
||||||
|
@ -55,7 +55,7 @@ public abstract class AbstractCompositeBasedAttribute
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractCompositionDefinition getSource() {
|
public AbstractCompositionAttribute getSource() {
|
||||||
return (AbstractCompositionDefinition) super.getSource();
|
return (AbstractCompositionAttribute) super.getSource();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,9 @@ import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames;
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractCompositionDefinition extends AbstractNonIdentifierAttribute implements
|
public abstract class AbstractCompositionAttribute extends AbstractNonIdentifierAttribute implements
|
||||||
CompositionDefinition {
|
CompositionDefinition {
|
||||||
protected AbstractCompositionDefinition(
|
protected AbstractCompositionAttribute(
|
||||||
AttributeSource source,
|
AttributeSource source,
|
||||||
SessionFactoryImplementor sessionFactory,
|
SessionFactoryImplementor sessionFactory,
|
||||||
int attributeNumber,
|
int attributeNumber,
|
||||||
|
@ -72,21 +72,21 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
|
||||||
public Iterator<AttributeDefinition> iterator() {
|
public Iterator<AttributeDefinition> iterator() {
|
||||||
return new Iterator<AttributeDefinition>() {
|
return new Iterator<AttributeDefinition>() {
|
||||||
private final int numberOfAttributes = getType().getSubtypes().length;
|
private final int numberOfAttributes = getType().getSubtypes().length;
|
||||||
private int currentAttributeNumber = 0;
|
private int currentSubAttributeNumber = 0;
|
||||||
private int currentColumnPosition = 0;
|
private int currentColumnPosition = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return currentAttributeNumber < numberOfAttributes;
|
return currentSubAttributeNumber < numberOfAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AttributeDefinition next() {
|
public AttributeDefinition next() {
|
||||||
final int attributeNumber = currentAttributeNumber;
|
final int subAttributeNumber = currentSubAttributeNumber;
|
||||||
currentAttributeNumber++;
|
currentSubAttributeNumber++;
|
||||||
|
|
||||||
final String name = getType().getPropertyNames()[attributeNumber];
|
final String name = getType().getPropertyNames()[subAttributeNumber];
|
||||||
final Type type = getType().getSubtypes()[attributeNumber];
|
final Type type = getType().getSubtypes()[subAttributeNumber];
|
||||||
|
|
||||||
int columnPosition = currentColumnPosition;
|
int columnPosition = currentColumnPosition;
|
||||||
currentColumnPosition += type.getColumnSpan( sessionFactory() );
|
currentColumnPosition += type.getColumnSpan( sessionFactory() );
|
||||||
|
@ -101,13 +101,13 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
|
||||||
getLHSTableName(
|
getLHSTableName(
|
||||||
aType,
|
aType,
|
||||||
attributeNumber(),
|
attributeNumber(),
|
||||||
(OuterJoinLoadable) joinable
|
(OuterJoinLoadable) locateOwningPersister()
|
||||||
),
|
),
|
||||||
getLHSColumnNames(
|
getLHSColumnNames(
|
||||||
aType,
|
aType,
|
||||||
attributeNumber(),
|
attributeNumber(),
|
||||||
columnPosition,
|
columnPosition,
|
||||||
(OuterJoinLoadable) joinable,
|
(OuterJoinLoadable) locateOwningPersister(),
|
||||||
sessionFactory()
|
sessionFactory()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -120,63 +120,63 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CompositeBasedAssociationAttribute(
|
return new CompositeBasedAssociationAttribute(
|
||||||
AbstractCompositionDefinition.this,
|
AbstractCompositionAttribute.this,
|
||||||
sessionFactory(),
|
sessionFactory(),
|
||||||
currentAttributeNumber,
|
subAttributeNumber,
|
||||||
name,
|
name,
|
||||||
(AssociationType) type,
|
(AssociationType) type,
|
||||||
new BaselineAttributeInformation.Builder()
|
new BaselineAttributeInformation.Builder()
|
||||||
.setInsertable( AbstractCompositionDefinition.this.isInsertable() )
|
.setInsertable( AbstractCompositionAttribute.this.isInsertable() )
|
||||||
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
|
.setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
|
||||||
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
|
.setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
|
||||||
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
|
.setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
|
||||||
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
|
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
|
||||||
.setDirtyCheckable( true )
|
.setDirtyCheckable( true )
|
||||||
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
|
.setVersionable( AbstractCompositionAttribute.this.isVersionable() )
|
||||||
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
|
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
|
||||||
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
|
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
|
||||||
.createInformation(),
|
.createInformation(),
|
||||||
AbstractCompositionDefinition.this.attributeNumber(),
|
AbstractCompositionAttribute.this.attributeNumber(),
|
||||||
associationKey
|
associationKey
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if ( type.isComponentType() ) {
|
else if ( type.isComponentType() ) {
|
||||||
return new CompositionBasedCompositionAttribute(
|
return new CompositionBasedCompositionAttribute(
|
||||||
AbstractCompositionDefinition.this,
|
AbstractCompositionAttribute.this,
|
||||||
sessionFactory(),
|
sessionFactory(),
|
||||||
currentAttributeNumber,
|
subAttributeNumber,
|
||||||
name,
|
name,
|
||||||
(CompositeType) type,
|
(CompositeType) type,
|
||||||
new BaselineAttributeInformation.Builder()
|
new BaselineAttributeInformation.Builder()
|
||||||
.setInsertable( AbstractCompositionDefinition.this.isInsertable() )
|
.setInsertable( AbstractCompositionAttribute.this.isInsertable() )
|
||||||
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
|
.setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
|
||||||
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
|
.setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
|
||||||
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
|
.setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
|
||||||
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
|
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
|
||||||
.setDirtyCheckable( true )
|
.setDirtyCheckable( true )
|
||||||
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
|
.setVersionable( AbstractCompositionAttribute.this.isVersionable() )
|
||||||
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
|
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
|
||||||
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
|
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
|
||||||
.createInformation()
|
.createInformation()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new CompositeBasedBasicAttribute(
|
return new CompositeBasedBasicAttribute(
|
||||||
AbstractCompositionDefinition.this,
|
AbstractCompositionAttribute.this,
|
||||||
sessionFactory(),
|
sessionFactory(),
|
||||||
currentAttributeNumber,
|
subAttributeNumber,
|
||||||
name,
|
name,
|
||||||
type,
|
type,
|
||||||
new BaselineAttributeInformation.Builder()
|
new BaselineAttributeInformation.Builder()
|
||||||
.setInsertable( AbstractCompositionDefinition.this.isInsertable() )
|
.setInsertable( AbstractCompositionAttribute.this.isInsertable() )
|
||||||
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
|
.setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
|
||||||
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
|
.setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
|
||||||
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
|
.setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
|
||||||
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
|
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
|
||||||
.setDirtyCheckable( true )
|
.setDirtyCheckable( true )
|
||||||
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
|
.setVersionable( AbstractCompositionAttribute.this.isVersionable() )
|
||||||
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
|
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
|
||||||
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
|
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
|
||||||
.createInformation()
|
.createInformation()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,7 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
|
||||||
return ( (EntityDefinition) getSource() ).getEntityPersister();
|
return ( (EntityDefinition) getSource() ).getEntityPersister();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return ( (AbstractCompositionDefinition) getSource() ).locateOwningPersister();
|
return ( (AbstractCompositionAttribute) getSource() ).locateOwningPersister();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ import org.hibernate.persister.collection.CollectionPersister;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Joinable;
|
import org.hibernate.persister.entity.Joinable;
|
||||||
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
||||||
import org.hibernate.persister.walking.internal.Helper;
|
import org.hibernate.persister.walking.internal.FetchStrategyHelper;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||||
import org.hibernate.persister.walking.spi.AssociationKey;
|
import org.hibernate.persister.walking.spi.AssociationKey;
|
||||||
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||||
|
@ -55,7 +55,7 @@ public class CompositeBasedAssociationAttribute
|
||||||
private Joinable joinable;
|
private Joinable joinable;
|
||||||
|
|
||||||
public CompositeBasedAssociationAttribute(
|
public CompositeBasedAssociationAttribute(
|
||||||
AbstractCompositionDefinition source,
|
AbstractCompositionAttribute source,
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
int attributeNumber,
|
int attributeNumber,
|
||||||
String attributeName,
|
String attributeName,
|
||||||
|
@ -130,7 +130,7 @@ public class CompositeBasedAssociationAttribute
|
||||||
EntityPersister owningPersister,
|
EntityPersister owningPersister,
|
||||||
PropertyPath propertyPath,
|
PropertyPath propertyPath,
|
||||||
int ownerAttributeNumber) {
|
int ownerAttributeNumber) {
|
||||||
return Helper.determineFetchStyleByProfile(
|
return FetchStrategyHelper.determineFetchStyleByProfile(
|
||||||
loadQueryInfluencers,
|
loadQueryInfluencers,
|
||||||
owningPersister,
|
owningPersister,
|
||||||
propertyPath,
|
propertyPath,
|
||||||
|
@ -139,11 +139,11 @@ public class CompositeBasedAssociationAttribute
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FetchStyle determineFetchStyleByMetadata(FetchMode fetchMode, AssociationType type) {
|
protected FetchStyle determineFetchStyleByMetadata(FetchMode fetchMode, AssociationType type) {
|
||||||
return Helper.determineFetchStyleByMetadata( fetchMode, type, sessionFactory() );
|
return FetchStrategyHelper.determineFetchStyleByMetadata( fetchMode, type, sessionFactory() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private FetchTiming determineFetchTiming(FetchStyle style) {
|
private FetchTiming determineFetchTiming(FetchStyle style) {
|
||||||
return Helper.determineFetchTiming( style, getType(), sessionFactory() );
|
return FetchStrategyHelper.determineFetchTiming( style, getType(), sessionFactory() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityPersister locateOwningPersister() {
|
private EntityPersister locateOwningPersister() {
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.hibernate.type.CompositeType;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class CompositionBasedCompositionAttribute
|
public class CompositionBasedCompositionAttribute
|
||||||
extends AbstractCompositionDefinition
|
extends AbstractCompositionAttribute
|
||||||
implements CompositionDefinition {
|
implements CompositionDefinition {
|
||||||
public CompositionBasedCompositionAttribute(
|
public CompositionBasedCompositionAttribute(
|
||||||
CompositionDefinition source,
|
CompositionDefinition source,
|
||||||
|
|
|
@ -34,7 +34,7 @@ import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Joinable;
|
import org.hibernate.persister.entity.Joinable;
|
||||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||||
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
||||||
import org.hibernate.persister.walking.internal.Helper;
|
import org.hibernate.persister.walking.internal.FetchStrategyHelper;
|
||||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||||
import org.hibernate.persister.walking.spi.AssociationKey;
|
import org.hibernate.persister.walking.spi.AssociationKey;
|
||||||
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||||
|
@ -129,14 +129,14 @@ public class EntityBasedAssociationAttribute
|
||||||
public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) {
|
public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) {
|
||||||
final EntityPersister owningPersister = getSource().getEntityPersister();
|
final EntityPersister owningPersister = getSource().getEntityPersister();
|
||||||
|
|
||||||
FetchStyle style = Helper.determineFetchStyleByProfile(
|
FetchStyle style = FetchStrategyHelper.determineFetchStyleByProfile(
|
||||||
loadQueryInfluencers,
|
loadQueryInfluencers,
|
||||||
owningPersister,
|
owningPersister,
|
||||||
propertyPath,
|
propertyPath,
|
||||||
attributeNumber()
|
attributeNumber()
|
||||||
);
|
);
|
||||||
if ( style == null ) {
|
if ( style == null ) {
|
||||||
style = Helper.determineFetchStyleByMetadata(
|
style = FetchStrategyHelper.determineFetchStyleByMetadata(
|
||||||
( (OuterJoinLoadable) getSource().getEntityPersister() ).getFetchMode( attributeNumber() ),
|
( (OuterJoinLoadable) getSource().getEntityPersister() ).getFetchMode( attributeNumber() ),
|
||||||
getType(),
|
getType(),
|
||||||
sessionFactory()
|
sessionFactory()
|
||||||
|
@ -144,7 +144,7 @@ public class EntityBasedAssociationAttribute
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FetchStrategy(
|
return new FetchStrategy(
|
||||||
Helper.determineFetchTiming( style, getType(), sessionFactory() ),
|
FetchStrategyHelper.determineFetchTiming( style, getType(), sessionFactory() ),
|
||||||
style
|
style
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ package org.hibernate.tuple.entity;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.tuple.component.AbstractCompositionDefinition;
|
import org.hibernate.tuple.component.AbstractCompositionAttribute;
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||||
import org.hibernate.tuple.BaselineAttributeInformation;
|
import org.hibernate.tuple.BaselineAttributeInformation;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
|
@ -34,7 +34,7 @@ import org.hibernate.type.CompositeType;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class EntityBasedCompositionAttribute
|
public class EntityBasedCompositionAttribute
|
||||||
extends AbstractCompositionDefinition
|
extends AbstractCompositionAttribute
|
||||||
implements CompositionDefinition {
|
implements CompositionDefinition {
|
||||||
|
|
||||||
public EntityBasedCompositionAttribute(
|
public EntityBasedCompositionAttribute(
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.type;
|
package org.hibernate.type;
|
||||||
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
@ -34,7 +35,11 @@ import org.hibernate.Filter;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.engine.internal.ForeignKeys;
|
import org.hibernate.engine.internal.ForeignKeys;
|
||||||
import org.hibernate.engine.spi.*;
|
import org.hibernate.engine.spi.EntityUniqueKey;
|
||||||
|
import org.hibernate.engine.spi.Mapping;
|
||||||
|
import org.hibernate.engine.spi.PersistenceContext;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
import org.hibernate.internal.util.ReflectHelper;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.persister.entity.Joinable;
|
import org.hibernate.persister.entity.Joinable;
|
||||||
|
@ -53,6 +58,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
protected final String uniqueKeyPropertyName;
|
protected final String uniqueKeyPropertyName;
|
||||||
private final boolean eager;
|
private final boolean eager;
|
||||||
private final boolean unwrapProxy;
|
private final boolean unwrapProxy;
|
||||||
|
private final boolean referenceToPrimaryKey;
|
||||||
|
|
||||||
private transient Class returnedClass;
|
private transient Class returnedClass;
|
||||||
|
|
||||||
|
@ -67,29 +73,46 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
* @param unwrapProxy Is unwrapping of proxies allowed for this association; unwrapping
|
* @param unwrapProxy Is unwrapping of proxies allowed for this association; unwrapping
|
||||||
* says to return the "implementation target" of lazy prooxies; typically only possible
|
* says to return the "implementation target" of lazy prooxies; typically only possible
|
||||||
* with lazy="no-proxy".
|
* with lazy="no-proxy".
|
||||||
|
*
|
||||||
|
* @deprecated Use {@link #EntityType(org.hibernate.type.TypeFactory.TypeScope, String, boolean, String, boolean, boolean)} instead.
|
||||||
|
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
protected EntityType(
|
protected EntityType(
|
||||||
TypeFactory.TypeScope scope,
|
TypeFactory.TypeScope scope,
|
||||||
String entityName,
|
String entityName,
|
||||||
String uniqueKeyPropertyName,
|
String uniqueKeyPropertyName,
|
||||||
boolean eager,
|
boolean eager,
|
||||||
boolean unwrapProxy) {
|
boolean unwrapProxy) {
|
||||||
this(scope, entityName, uniqueKeyPropertyName, eager, unwrapProxy, null);
|
this( scope, entityName, uniqueKeyPropertyName == null, uniqueKeyPropertyName, eager, unwrapProxy );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the requested entity type mapping.
|
||||||
|
*
|
||||||
|
* @param scope The type scope
|
||||||
|
* @param entityName The name of the associated entity.
|
||||||
|
* @param referenceToPrimaryKey True if association references a primary key.
|
||||||
|
* @param uniqueKeyPropertyName The property-ref name, or null if we
|
||||||
|
* reference the PK of the associated entity.
|
||||||
|
* @param eager Is eager fetching enabled.
|
||||||
|
* @param unwrapProxy Is unwrapping of proxies allowed for this association; unwrapping
|
||||||
|
* says to return the "implementation target" of lazy prooxies; typically only possible
|
||||||
|
* with lazy="no-proxy".
|
||||||
|
*/
|
||||||
protected EntityType(
|
protected EntityType(
|
||||||
TypeFactory.TypeScope scope,
|
TypeFactory.TypeScope scope,
|
||||||
String entityName,
|
String entityName,
|
||||||
|
boolean referenceToPrimaryKey,
|
||||||
String uniqueKeyPropertyName,
|
String uniqueKeyPropertyName,
|
||||||
boolean eager,
|
boolean eager,
|
||||||
boolean unwrapProxy,
|
boolean unwrapProxy) {
|
||||||
Class returnedClass) {
|
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
this.associatedEntityName = entityName;
|
this.associatedEntityName = entityName;
|
||||||
this.uniqueKeyPropertyName = uniqueKeyPropertyName;
|
this.uniqueKeyPropertyName = uniqueKeyPropertyName;
|
||||||
this.eager = eager;
|
this.eager = eager;
|
||||||
this.unwrapProxy = unwrapProxy;
|
this.unwrapProxy = unwrapProxy;
|
||||||
this.returnedClass = returnedClass;
|
this.referenceToPrimaryKey = referenceToPrimaryKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,11 +169,13 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
* @return True if this association reference the PK of the associated entity.
|
* @return True if this association reference the PK of the associated entity.
|
||||||
*/
|
*/
|
||||||
public boolean isReferenceToPrimaryKey() {
|
public boolean isReferenceToPrimaryKey() {
|
||||||
return uniqueKeyPropertyName==null;
|
return referenceToPrimaryKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRHSUniqueKeyPropertyName() {
|
public String getRHSUniqueKeyPropertyName() {
|
||||||
return uniqueKeyPropertyName;
|
// Return null if this type references a PK. This is important for
|
||||||
|
// associations' use of mappedBy referring to a derived ID.
|
||||||
|
return referenceToPrimaryKey ? null : uniqueKeyPropertyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLHSPropertyName() {
|
public String getLHSPropertyName() {
|
||||||
|
@ -397,14 +422,15 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
if ( isNull( owner, session ) ) {
|
if ( isNull( owner, session ) ) {
|
||||||
return null; //EARLY EXIT!
|
return null; //EARLY EXIT!
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isReferenceToPrimaryKey() ) {
|
if ( isReferenceToPrimaryKey() ) {
|
||||||
return resolveIdentifier( (Serializable) value, session );
|
return resolveIdentifier( (Serializable) value, session );
|
||||||
}
|
}
|
||||||
else {
|
else if ( uniqueKeyPropertyName != null ) {
|
||||||
return loadByUniqueKey( getAssociatedEntityName(), uniqueKeyPropertyName, value, session );
|
return loadByUniqueKey( getAssociatedEntityName(), uniqueKeyPropertyName, value, session );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getSemiResolvedType(SessionFactoryImplementor factory) {
|
public Type getSemiResolvedType(SessionFactoryImplementor factory) {
|
||||||
|
@ -412,7 +438,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final Object getIdentifier(Object value, SessionImplementor session) throws HibernateException {
|
protected final Object getIdentifier(Object value, SessionImplementor session) throws HibernateException {
|
||||||
if ( isReferenceToPrimaryKey() ) {
|
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null) {
|
||||||
return ForeignKeys.getEntityIdentifierIfNotUnsaved( getAssociatedEntityName(), value, session ); //tolerates nulls
|
return ForeignKeys.getEntityIdentifierIfNotUnsaved( getAssociatedEntityName(), value, session ); //tolerates nulls
|
||||||
}
|
}
|
||||||
else if ( value == null ) {
|
else if ( value == null ) {
|
||||||
|
@ -516,7 +542,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
* or unique key property name.
|
* or unique key property name.
|
||||||
*/
|
*/
|
||||||
public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingException {
|
public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingException {
|
||||||
if ( isReferenceToPrimaryKey() ) {
|
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
|
||||||
return getIdentifierType(factory);
|
return getIdentifierType(factory);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -538,7 +564,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
*/
|
*/
|
||||||
public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory)
|
public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory)
|
||||||
throws MappingException {
|
throws MappingException {
|
||||||
if ( isReferenceToPrimaryKey() ) {
|
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
|
||||||
return factory.getIdentifierPropertyName( getAssociatedEntityName() );
|
return factory.getIdentifierPropertyName( getAssociatedEntityName() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -67,9 +67,15 @@ public class ManyToOneType extends EntityType {
|
||||||
* @param lazy Should the association be handled lazily
|
* @param lazy Should the association be handled lazily
|
||||||
*/
|
*/
|
||||||
public ManyToOneType(TypeFactory.TypeScope scope, String referencedEntityName, boolean lazy) {
|
public ManyToOneType(TypeFactory.TypeScope scope, String referencedEntityName, boolean lazy) {
|
||||||
this( scope, referencedEntityName, null, lazy, true, false, false );
|
this( scope, referencedEntityName, true, null, lazy, true, false, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #ManyToOneType(TypeFactory.TypeScope, String, boolean, String, boolean, boolean, boolean, boolean ) } instead.
|
||||||
|
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public ManyToOneType(
|
public ManyToOneType(
|
||||||
TypeFactory.TypeScope scope,
|
TypeFactory.TypeScope scope,
|
||||||
String referencedEntityName,
|
String referencedEntityName,
|
||||||
|
@ -78,20 +84,18 @@ public class ManyToOneType extends EntityType {
|
||||||
boolean unwrapProxy,
|
boolean unwrapProxy,
|
||||||
boolean ignoreNotFound,
|
boolean ignoreNotFound,
|
||||||
boolean isLogicalOneToOne) {
|
boolean isLogicalOneToOne) {
|
||||||
super( scope, referencedEntityName, uniqueKeyPropertyName, !lazy, unwrapProxy );
|
this( scope, referencedEntityName, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy, ignoreNotFound, isLogicalOneToOne );
|
||||||
this.ignoreNotFound = ignoreNotFound;
|
|
||||||
this.isLogicalOneToOne = isLogicalOneToOne;
|
|
||||||
}
|
}
|
||||||
public ManyToOneType(
|
public ManyToOneType(
|
||||||
TypeFactory.TypeScope scope,
|
TypeFactory.TypeScope scope,
|
||||||
String referencedEntityName,
|
String referencedEntityName,
|
||||||
|
boolean referenceToPrimaryKey,
|
||||||
String uniqueKeyPropertyName,
|
String uniqueKeyPropertyName,
|
||||||
boolean lazy,
|
boolean lazy,
|
||||||
boolean unwrapProxy,
|
boolean unwrapProxy,
|
||||||
boolean ignoreNotFound,
|
boolean ignoreNotFound,
|
||||||
boolean isLogicalOneToOne,
|
boolean isLogicalOneToOne) {
|
||||||
Class returnedClass) {
|
super( scope, referencedEntityName, referenceToPrimaryKey, uniqueKeyPropertyName, !lazy, unwrapProxy );
|
||||||
super( scope, referencedEntityName, uniqueKeyPropertyName, !lazy, unwrapProxy, returnedClass );
|
|
||||||
this.ignoreNotFound = ignoreNotFound;
|
this.ignoreNotFound = ignoreNotFound;
|
||||||
this.isLogicalOneToOne = isLogicalOneToOne;
|
this.isLogicalOneToOne = isLogicalOneToOne;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,12 @@ public class OneToOneType extends EntityType {
|
||||||
private final String propertyName;
|
private final String propertyName;
|
||||||
private final String entityName;
|
private final String entityName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #OneToOneType(TypeFactory.TypeScope, String, ForeignKeyDirection, boolean, String, boolean, boolean, String, String)}
|
||||||
|
* instead.
|
||||||
|
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public OneToOneType(
|
public OneToOneType(
|
||||||
TypeFactory.TypeScope scope,
|
TypeFactory.TypeScope scope,
|
||||||
String referencedEntityName,
|
String referencedEntityName,
|
||||||
|
@ -56,23 +62,20 @@ public class OneToOneType extends EntityType {
|
||||||
boolean unwrapProxy,
|
boolean unwrapProxy,
|
||||||
String entityName,
|
String entityName,
|
||||||
String propertyName) {
|
String propertyName) {
|
||||||
super( scope, referencedEntityName, uniqueKeyPropertyName, !lazy, unwrapProxy );
|
this( scope, referencedEntityName, foreignKeyType, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy, entityName, propertyName );
|
||||||
this.foreignKeyType = foreignKeyType;
|
|
||||||
this.propertyName = propertyName;
|
|
||||||
this.entityName = entityName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OneToOneType(
|
public OneToOneType(
|
||||||
TypeFactory.TypeScope scope,
|
TypeFactory.TypeScope scope,
|
||||||
String referencedEntityName,
|
String referencedEntityName,
|
||||||
ForeignKeyDirection foreignKeyType,
|
ForeignKeyDirection foreignKeyType,
|
||||||
|
boolean referenceToPrimaryKey,
|
||||||
String uniqueKeyPropertyName,
|
String uniqueKeyPropertyName,
|
||||||
boolean lazy,
|
boolean lazy,
|
||||||
boolean unwrapProxy,
|
boolean unwrapProxy,
|
||||||
String entityName,
|
String entityName,
|
||||||
String propertyName,
|
String propertyName) {
|
||||||
Class returnedClass) {
|
super( scope, referencedEntityName, referenceToPrimaryKey, uniqueKeyPropertyName, !lazy, unwrapProxy );
|
||||||
super( scope, referencedEntityName, uniqueKeyPropertyName, !lazy, unwrapProxy, returnedClass );
|
|
||||||
this.foreignKeyType = foreignKeyType;
|
this.foreignKeyType = foreignKeyType;
|
||||||
this.propertyName = propertyName;
|
this.propertyName = propertyName;
|
||||||
this.entityName = entityName;
|
this.entityName = entityName;
|
||||||
|
|
18
hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java
Executable file → Normal file
18
hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java
Executable file → Normal file
|
@ -43,6 +43,10 @@ import org.hibernate.metamodel.spi.relational.Size;
|
||||||
*/
|
*/
|
||||||
public class SpecialOneToOneType extends OneToOneType {
|
public class SpecialOneToOneType extends OneToOneType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #SpecialOneToOneType(org.hibernate.type.TypeFactory.TypeScope, String, ForeignKeyDirection, boolean, String, boolean, boolean, String, String)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public SpecialOneToOneType(
|
public SpecialOneToOneType(
|
||||||
TypeFactory.TypeScope scope,
|
TypeFactory.TypeScope scope,
|
||||||
String referencedEntityName,
|
String referencedEntityName,
|
||||||
|
@ -52,10 +56,24 @@ public class SpecialOneToOneType extends OneToOneType {
|
||||||
boolean unwrapProxy,
|
boolean unwrapProxy,
|
||||||
String entityName,
|
String entityName,
|
||||||
String propertyName) {
|
String propertyName) {
|
||||||
|
this( scope, referencedEntityName, foreignKeyType, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy, entityName, propertyName );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpecialOneToOneType(
|
||||||
|
TypeFactory.TypeScope scope,
|
||||||
|
String referencedEntityName,
|
||||||
|
ForeignKeyDirection foreignKeyType,
|
||||||
|
boolean referenceToPrimaryKey,
|
||||||
|
String uniqueKeyPropertyName,
|
||||||
|
boolean lazy,
|
||||||
|
boolean unwrapProxy,
|
||||||
|
String entityName,
|
||||||
|
String propertyName) {
|
||||||
super(
|
super(
|
||||||
scope,
|
scope,
|
||||||
referencedEntityName,
|
referencedEntityName,
|
||||||
foreignKeyType,
|
foreignKeyType,
|
||||||
|
referenceToPrimaryKey,
|
||||||
uniqueKeyPropertyName,
|
uniqueKeyPropertyName,
|
||||||
lazy,
|
lazy,
|
||||||
unwrapProxy,
|
unwrapProxy,
|
||||||
|
|
|
@ -27,8 +27,6 @@ import java.io.Serializable;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.classic.Lifecycle;
|
import org.hibernate.classic.Lifecycle;
|
||||||
|
@ -39,6 +37,7 @@ import org.hibernate.tuple.component.ComponentMetamodel;
|
||||||
import org.hibernate.usertype.CompositeUserType;
|
import org.hibernate.usertype.CompositeUserType;
|
||||||
import org.hibernate.usertype.ParameterizedType;
|
import org.hibernate.usertype.ParameterizedType;
|
||||||
import org.hibernate.usertype.UserType;
|
import org.hibernate.usertype.UserType;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used internally to build instances of {@link Type}, specifically it builds instances of
|
* Used internally to build instances of {@link Type}, specifically it builds instances of
|
||||||
|
@ -208,6 +207,11 @@ public final class TypeFactory implements Serializable {
|
||||||
|
|
||||||
// one-to-one type builders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// one-to-one type builders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #oneToOne(String, ForeignKeyDirection, String, boolean, boolean, String, String, boolean)} instead.
|
||||||
|
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public EntityType oneToOne(
|
public EntityType oneToOne(
|
||||||
String persistentClass,
|
String persistentClass,
|
||||||
ForeignKeyDirection foreignKeyType,
|
ForeignKeyDirection foreignKeyType,
|
||||||
|
@ -216,10 +220,28 @@ public final class TypeFactory implements Serializable {
|
||||||
boolean unwrapProxy,
|
boolean unwrapProxy,
|
||||||
String entityName,
|
String entityName,
|
||||||
String propertyName) {
|
String propertyName) {
|
||||||
return new OneToOneType( typeScope, persistentClass, foreignKeyType, uniqueKeyPropertyName,
|
return oneToOne( persistentClass, foreignKeyType, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy, entityName,
|
||||||
lazy, unwrapProxy, entityName, propertyName );
|
propertyName );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public EntityType oneToOne(
|
||||||
|
String persistentClass,
|
||||||
|
ForeignKeyDirection foreignKeyType,
|
||||||
|
boolean referenceToPrimaryKey,
|
||||||
|
String uniqueKeyPropertyName,
|
||||||
|
boolean lazy,
|
||||||
|
boolean unwrapProxy,
|
||||||
|
String entityName,
|
||||||
|
String propertyName) {
|
||||||
|
return new OneToOneType( typeScope, persistentClass, foreignKeyType, referenceToPrimaryKey,
|
||||||
|
uniqueKeyPropertyName, lazy, unwrapProxy, entityName, propertyName );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #specialOneToOne(String, ForeignKeyDirection, String, boolean, boolean, String, String, boolean)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public EntityType specialOneToOne(
|
public EntityType specialOneToOne(
|
||||||
String persistentClass,
|
String persistentClass,
|
||||||
ForeignKeyDirection foreignKeyType,
|
ForeignKeyDirection foreignKeyType,
|
||||||
|
@ -228,34 +250,21 @@ public final class TypeFactory implements Serializable {
|
||||||
boolean unwrapProxy,
|
boolean unwrapProxy,
|
||||||
String entityName,
|
String entityName,
|
||||||
String propertyName) {
|
String propertyName) {
|
||||||
return new SpecialOneToOneType( typeScope, persistentClass, foreignKeyType, uniqueKeyPropertyName,
|
return specialOneToOne( persistentClass, foreignKeyType, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy,
|
||||||
lazy, unwrapProxy, entityName, propertyName );
|
entityName, propertyName );
|
||||||
}
|
|
||||||
|
|
||||||
public EntityType oneToOne(
|
|
||||||
String persistentClass,
|
|
||||||
ForeignKeyDirection foreignKeyType,
|
|
||||||
String uniqueKeyPropertyName,
|
|
||||||
boolean lazy,
|
|
||||||
boolean unwrapProxy,
|
|
||||||
String entityName,
|
|
||||||
String propertyName,
|
|
||||||
Class returnedClass) {
|
|
||||||
return new OneToOneType( typeScope, persistentClass, foreignKeyType, uniqueKeyPropertyName,
|
|
||||||
lazy, unwrapProxy, entityName, propertyName, returnedClass );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityType specialOneToOne(
|
public EntityType specialOneToOne(
|
||||||
String persistentClass,
|
String persistentClass,
|
||||||
ForeignKeyDirection foreignKeyType,
|
ForeignKeyDirection foreignKeyType,
|
||||||
|
boolean referenceToPrimaryKey,
|
||||||
String uniqueKeyPropertyName,
|
String uniqueKeyPropertyName,
|
||||||
boolean lazy,
|
boolean lazy,
|
||||||
boolean unwrapProxy,
|
boolean unwrapProxy,
|
||||||
String entityName,
|
String entityName,
|
||||||
String propertyName,
|
String propertyName) {
|
||||||
Class returnedClass) {
|
return new SpecialOneToOneType( typeScope, persistentClass, foreignKeyType, referenceToPrimaryKey,
|
||||||
return new SpecialOneToOneType( typeScope, persistentClass, foreignKeyType, uniqueKeyPropertyName,
|
uniqueKeyPropertyName, lazy, unwrapProxy, entityName, propertyName );
|
||||||
lazy, unwrapProxy, entityName, propertyName, returnedClass );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,6 +278,11 @@ public final class TypeFactory implements Serializable {
|
||||||
return new ManyToOneType( typeScope, persistentClass, lazy );
|
return new ManyToOneType( typeScope, persistentClass, lazy );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #manyToOne(String, boolean, String, boolean, boolean, boolean, boolean)} instead.
|
||||||
|
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public EntityType manyToOne(
|
public EntityType manyToOne(
|
||||||
String persistentClass,
|
String persistentClass,
|
||||||
String uniqueKeyPropertyName,
|
String uniqueKeyPropertyName,
|
||||||
|
@ -276,9 +290,23 @@ public final class TypeFactory implements Serializable {
|
||||||
boolean unwrapProxy,
|
boolean unwrapProxy,
|
||||||
boolean ignoreNotFound,
|
boolean ignoreNotFound,
|
||||||
boolean isLogicalOneToOne) {
|
boolean isLogicalOneToOne) {
|
||||||
|
return manyToOne( persistentClass, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy, ignoreNotFound,
|
||||||
|
isLogicalOneToOne );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public EntityType manyToOne(
|
||||||
|
String persistentClass,
|
||||||
|
boolean referenceToPrimaryKey,
|
||||||
|
String uniqueKeyPropertyName,
|
||||||
|
boolean lazy,
|
||||||
|
boolean unwrapProxy,
|
||||||
|
boolean ignoreNotFound,
|
||||||
|
boolean isLogicalOneToOne) {
|
||||||
return new ManyToOneType(
|
return new ManyToOneType(
|
||||||
typeScope,
|
typeScope,
|
||||||
persistentClass,
|
persistentClass,
|
||||||
|
referenceToPrimaryKey,
|
||||||
uniqueKeyPropertyName,
|
uniqueKeyPropertyName,
|
||||||
lazy,
|
lazy,
|
||||||
unwrapProxy,
|
unwrapProxy,
|
||||||
|
@ -287,26 +315,6 @@ public final class TypeFactory implements Serializable {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityType manyToOne(
|
|
||||||
String persistentClass,
|
|
||||||
String uniqueKeyPropertyName,
|
|
||||||
boolean lazy,
|
|
||||||
boolean unwrapProxy,
|
|
||||||
boolean ignoreNotFound,
|
|
||||||
boolean isLogicalOneToOne,
|
|
||||||
Class returnedClass) {
|
|
||||||
return new ManyToOneType(
|
|
||||||
typeScope,
|
|
||||||
persistentClass,
|
|
||||||
uniqueKeyPropertyName,
|
|
||||||
lazy,
|
|
||||||
unwrapProxy,
|
|
||||||
ignoreNotFound,
|
|
||||||
isLogicalOneToOne ,
|
|
||||||
returnedClass
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// collection type builders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// collection type builders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
public CollectionType array(String role, String propertyRef, Class elementClass) {
|
public CollectionType array(String role, String propertyRef, Class elementClass) {
|
||||||
|
|
|
@ -0,0 +1,352 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.loader;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.Embedded;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
|
import org.hibernate.engine.spi.QueryParameters;
|
||||||
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
|
import org.hibernate.jdbc.Work;
|
||||||
|
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
|
||||||
|
import org.hibernate.loader.internal.LoadQueryAliasResolutionContextImpl;
|
||||||
|
import org.hibernate.loader.internal.ResultSetProcessorImpl;
|
||||||
|
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
|
||||||
|
import org.hibernate.loader.plan.spi.LoadPlan;
|
||||||
|
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
|
||||||
|
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
|
||||||
|
import org.hibernate.loader.spi.NamedParameterContext;
|
||||||
|
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.test.component.cascading.toone.PersonalInfo;
|
||||||
|
import org.hibernate.testing.FailureExpected;
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] { Person.class, Customer.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimpleNestedCompositeAttributeProcessing() throws Exception {
|
||||||
|
// create some test data
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Person person = new Person();
|
||||||
|
person.id = 1;
|
||||||
|
person.name = "Joe Blow";
|
||||||
|
person.address = new Address();
|
||||||
|
person.address.address1 = "1313 Mockingbird Lane";
|
||||||
|
person.address.city = "Pleasantville";
|
||||||
|
person.address.country = "USA";
|
||||||
|
AddressType addressType = new AddressType();
|
||||||
|
addressType.typeName = "snail mail";
|
||||||
|
person.address.type = addressType;
|
||||||
|
session.save( person );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Person personGotten = (Person) session.get( Person.class, person.id );
|
||||||
|
assertEquals( person.id, personGotten.id );
|
||||||
|
assertEquals( person.address.address1, personGotten.address.address1 );
|
||||||
|
assertEquals( person.address.city, personGotten.address.city );
|
||||||
|
assertEquals( person.address.country, personGotten.address.country );
|
||||||
|
assertEquals( person.address.type.typeName, personGotten.address.type.typeName );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
List results = getResults( sessionFactory().getEntityPersister( Person.class.getName() ) );
|
||||||
|
assertEquals( 1, results.size() );
|
||||||
|
Object result = results.get( 0 );
|
||||||
|
assertNotNull( result );
|
||||||
|
|
||||||
|
Person personWork = ExtraAssertions.assertTyping( Person.class, result );
|
||||||
|
assertEquals( person.id, personWork.id );
|
||||||
|
assertEquals( person.address.address1, personWork.address.address1 );
|
||||||
|
assertEquals( person.address.city, personWork.address.city );
|
||||||
|
assertEquals( person.address.country, personWork.address.country );
|
||||||
|
assertEquals( person.address.type.typeName, personGotten.address.type.typeName );
|
||||||
|
|
||||||
|
// clean up test data
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.createQuery( "delete Person" ).executeUpdate();
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNestedCompositeElementCollectionProcessing() throws Exception {
|
||||||
|
// create some test data
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Person person = new Person();
|
||||||
|
person.id = 1;
|
||||||
|
person.name = "Joe Blow";
|
||||||
|
session.save( person );
|
||||||
|
Customer customer = new Customer();
|
||||||
|
customer.id = 1L;
|
||||||
|
Investment investment1 = new Investment();
|
||||||
|
investment1.description = "stock";
|
||||||
|
investment1.date = new Date();
|
||||||
|
investment1.monetaryAmount = new MonetaryAmount();
|
||||||
|
investment1.monetaryAmount.currency = MonetaryAmount.CurrencyCode.USD;
|
||||||
|
investment1.monetaryAmount.amount = BigDecimal.valueOf( 1234, 2 );
|
||||||
|
investment1.performedBy = person;
|
||||||
|
Investment investment2 = new Investment();
|
||||||
|
investment2.description = "bond";
|
||||||
|
investment2.date = new Date();
|
||||||
|
investment2.monetaryAmount = new MonetaryAmount();
|
||||||
|
investment2.monetaryAmount.currency = MonetaryAmount.CurrencyCode.EUR;
|
||||||
|
investment2.monetaryAmount.amount = BigDecimal.valueOf( 98176, 1 );
|
||||||
|
customer.investments.add( investment1 );
|
||||||
|
customer.investments.add( investment2 );
|
||||||
|
session.save( customer );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Customer customerGotten = (Customer) session.get( Customer.class, customer.id );
|
||||||
|
assertEquals( customer.id, customerGotten.id );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
List results = getResults( sessionFactory().getEntityPersister( Customer.class.getName() ) );
|
||||||
|
|
||||||
|
assertEquals( 2, results.size() );
|
||||||
|
assertSame( results.get( 0 ), results.get( 1 ) );
|
||||||
|
Object result = results.get( 0 );
|
||||||
|
assertNotNull( result );
|
||||||
|
|
||||||
|
Customer customerWork = ExtraAssertions.assertTyping( Customer.class, result );
|
||||||
|
|
||||||
|
// clean up test data
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.delete( customerWork.investments.get( 0 ).performedBy );
|
||||||
|
session.delete( customerWork );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<?> getResults(EntityPersister entityPersister ) {
|
||||||
|
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
|
||||||
|
sessionFactory(),
|
||||||
|
LoadQueryInfluencers.NONE
|
||||||
|
);
|
||||||
|
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
|
||||||
|
final LoadQueryAliasResolutionContext aliasResolutionContext =
|
||||||
|
new LoadQueryAliasResolutionContextImpl(
|
||||||
|
sessionFactory(),
|
||||||
|
0,
|
||||||
|
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
|
||||||
|
);
|
||||||
|
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
|
||||||
|
LoadQueryInfluencers.NONE,
|
||||||
|
plan
|
||||||
|
);
|
||||||
|
final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext );
|
||||||
|
|
||||||
|
final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan );
|
||||||
|
final List results = new ArrayList();
|
||||||
|
|
||||||
|
final Session workSession = openSession();
|
||||||
|
workSession.beginTransaction();
|
||||||
|
workSession.doWork(
|
||||||
|
new Work() {
|
||||||
|
@Override
|
||||||
|
public void execute(Connection connection) throws SQLException {
|
||||||
|
PreparedStatement ps = connection.prepareStatement( sql );
|
||||||
|
ps.setInt( 1, 1 );
|
||||||
|
ResultSet resultSet = ps.executeQuery();
|
||||||
|
results.addAll(
|
||||||
|
resultSetProcessor.extractResults(
|
||||||
|
NoOpLoadPlanAdvisor.INSTANCE,
|
||||||
|
resultSet,
|
||||||
|
(SessionImplementor) workSession,
|
||||||
|
new QueryParameters(),
|
||||||
|
new NamedParameterContext() {
|
||||||
|
@Override
|
||||||
|
public int[] getNamedParameterLocations(String name) {
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
aliasResolutionContext,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
resultSet.close();
|
||||||
|
ps.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
workSession.getTransaction().commit();
|
||||||
|
workSession.close();
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Person" )
|
||||||
|
public static class Person implements Serializable {
|
||||||
|
@Id
|
||||||
|
Integer id;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
Address address;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class Address implements Serializable {
|
||||||
|
String address1;
|
||||||
|
String city;
|
||||||
|
String country;
|
||||||
|
AddressType type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class AddressType {
|
||||||
|
String typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Customer" )
|
||||||
|
public static class Customer {
|
||||||
|
private Long id;
|
||||||
|
private List<Investment> investments = new ArrayList<Investment>();
|
||||||
|
|
||||||
|
@Id
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ElementCollection(fetch = FetchType.EAGER)
|
||||||
|
public List<Investment> getInvestments() {
|
||||||
|
return investments;
|
||||||
|
}
|
||||||
|
public void setInvestments(List<Investment> investments) {
|
||||||
|
this.investments = investments;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class Investment {
|
||||||
|
private MonetaryAmount monetaryAmount;
|
||||||
|
private String description;
|
||||||
|
private Date date;
|
||||||
|
private Person performedBy;
|
||||||
|
|
||||||
|
@Embedded
|
||||||
|
public MonetaryAmount getMonetaryAmount() {
|
||||||
|
return monetaryAmount;
|
||||||
|
}
|
||||||
|
public void setMonetaryAmount(MonetaryAmount monetaryAmount) {
|
||||||
|
this.monetaryAmount = monetaryAmount;
|
||||||
|
}
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
public Date getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
public void setDate(Date date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
@ManyToOne
|
||||||
|
public Person getPerformedBy() {
|
||||||
|
return performedBy;
|
||||||
|
}
|
||||||
|
public void setPerformedBy(Person performedBy) {
|
||||||
|
this.performedBy = performedBy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class MonetaryAmount {
|
||||||
|
public static enum CurrencyCode {
|
||||||
|
USD,
|
||||||
|
EUR
|
||||||
|
}
|
||||||
|
private BigDecimal amount;
|
||||||
|
@Column(length = 3)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private CurrencyCode currency;
|
||||||
|
|
||||||
|
public BigDecimal getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
public void setAmount(BigDecimal amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CurrencyCode getCurrency() {
|
||||||
|
return currency;
|
||||||
|
}
|
||||||
|
public void setCurrency(CurrencyCode currency) {
|
||||||
|
this.currency = currency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,434 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.loader;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.EmbeddedId;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hibernate.LockOptions;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
|
import org.hibernate.engine.spi.QueryParameters;
|
||||||
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
|
import org.hibernate.jdbc.Work;
|
||||||
|
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
|
||||||
|
import org.hibernate.loader.internal.LoadQueryAliasResolutionContextImpl;
|
||||||
|
import org.hibernate.loader.internal.ResultSetProcessorImpl;
|
||||||
|
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
|
||||||
|
import org.hibernate.loader.plan.spi.LoadPlan;
|
||||||
|
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
|
||||||
|
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
|
||||||
|
import org.hibernate.loader.spi.NamedParameterContext;
|
||||||
|
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public class EncapsulatedCompositeIdResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] { Parent.class, CardField.class, Card.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimpleCompositeId() throws Exception {
|
||||||
|
|
||||||
|
// create some test data
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Parent parent = new Parent();
|
||||||
|
parent.id = new ParentPK();
|
||||||
|
parent.id.firstName = "Joe";
|
||||||
|
parent.id.lastName = "Blow";
|
||||||
|
session.save( parent );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Parent parentGotten = (Parent) session.get( Parent.class, parent.id );
|
||||||
|
assertEquals( parent, parentGotten );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
final List results = getResults(
|
||||||
|
sessionFactory().getEntityPersister( Parent.class.getName() ),
|
||||||
|
new Callback() {
|
||||||
|
@Override
|
||||||
|
public void bind(PreparedStatement ps) throws SQLException {
|
||||||
|
ps.setString( 1, "Joe" );
|
||||||
|
ps.setString( 2, "Blow" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryParameters getQueryParameters() {
|
||||||
|
return new QueryParameters();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertEquals( 1, results.size() );
|
||||||
|
Object result = results.get( 0 );
|
||||||
|
assertNotNull( result );
|
||||||
|
|
||||||
|
Parent parentWork = ExtraAssertions.assertTyping( Parent.class, result );
|
||||||
|
assertEquals( parent, parentWork );
|
||||||
|
|
||||||
|
// clean up test data
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.createQuery( "delete Parent" ).executeUpdate();
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCompositeIdWithKeyManyToOne() throws Exception {
|
||||||
|
final String cardId = "ace-of-spades";
|
||||||
|
|
||||||
|
// create some test data
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Card card = new Card( cardId );
|
||||||
|
final CardField cardField = new CardField( card, 1 );
|
||||||
|
session.persist( card );
|
||||||
|
session.persist( cardField );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Card cardProxy = (Card) session.load( Card.class, cardId );
|
||||||
|
final CardFieldPK cardFieldPK = new CardFieldPK( cardProxy, 1 );
|
||||||
|
CardField cardFieldGotten = (CardField) session.get( CardField.class, cardFieldPK );
|
||||||
|
|
||||||
|
//assertEquals( card, cardGotten );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
final EntityPersister entityPersister = sessionFactory().getEntityPersister( CardField.class.getName() );
|
||||||
|
|
||||||
|
final List results = getResults(
|
||||||
|
entityPersister,
|
||||||
|
new Callback() {
|
||||||
|
@Override
|
||||||
|
public void bind(PreparedStatement ps) throws SQLException {
|
||||||
|
ps.setString( 1, cardField.primaryKey.card.id );
|
||||||
|
ps.setInt( 2, cardField.primaryKey.fieldNumber );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryParameters getQueryParameters() {
|
||||||
|
QueryParameters qp = new QueryParameters();
|
||||||
|
qp.setPositionalParameterTypes( new Type[] { entityPersister.getIdentifierType() } );
|
||||||
|
qp.setPositionalParameterValues( new Object[] { cardFieldPK } );
|
||||||
|
qp.setOptionalObject( null );
|
||||||
|
qp.setOptionalEntityName( entityPersister.getEntityName() );
|
||||||
|
qp.setOptionalId( cardFieldPK );
|
||||||
|
qp.setLockOptions( LockOptions.NONE );
|
||||||
|
return qp;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertEquals( 1, results.size() );
|
||||||
|
Object result = results.get( 0 );
|
||||||
|
assertNotNull( result );
|
||||||
|
|
||||||
|
CardField cardFieldWork = ExtraAssertions.assertTyping( CardField.class, result );
|
||||||
|
assertEquals( cardFieldGotten, cardFieldWork );
|
||||||
|
|
||||||
|
// clean up test data
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.createQuery( "delete CardField" ).executeUpdate();
|
||||||
|
session.createQuery( "delete Card" ).executeUpdate();
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List getResults(final EntityPersister entityPersister, final Callback callback) {
|
||||||
|
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
|
||||||
|
sessionFactory(),
|
||||||
|
LoadQueryInfluencers.NONE
|
||||||
|
);
|
||||||
|
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
|
||||||
|
final LoadQueryAliasResolutionContext aliasResolutionContext =
|
||||||
|
new LoadQueryAliasResolutionContextImpl(
|
||||||
|
sessionFactory(),
|
||||||
|
0,
|
||||||
|
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
|
||||||
|
);
|
||||||
|
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
|
||||||
|
LoadQueryInfluencers.NONE,
|
||||||
|
plan
|
||||||
|
);
|
||||||
|
final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext );
|
||||||
|
|
||||||
|
final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan );
|
||||||
|
final List results = new ArrayList();
|
||||||
|
|
||||||
|
final Session workSession = openSession();
|
||||||
|
workSession.beginTransaction();
|
||||||
|
workSession.doWork(
|
||||||
|
new Work() {
|
||||||
|
@Override
|
||||||
|
public void execute(Connection connection) throws SQLException {
|
||||||
|
PreparedStatement ps = connection.prepareStatement( sql );
|
||||||
|
callback.bind( ps );
|
||||||
|
ResultSet resultSet = ps.executeQuery();
|
||||||
|
//callback.beforeExtractResults( workSession );
|
||||||
|
results.addAll(
|
||||||
|
resultSetProcessor.extractResults(
|
||||||
|
NoOpLoadPlanAdvisor.INSTANCE,
|
||||||
|
resultSet,
|
||||||
|
(SessionImplementor) workSession,
|
||||||
|
callback.getQueryParameters(),
|
||||||
|
new NamedParameterContext() {
|
||||||
|
@Override
|
||||||
|
public int[] getNamedParameterLocations(String name) {
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
aliasResolutionContext,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
resultSet.close();
|
||||||
|
ps.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
workSession.getTransaction().commit();
|
||||||
|
workSession.close();
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private interface Callback {
|
||||||
|
void bind(PreparedStatement ps) throws SQLException;
|
||||||
|
QueryParameters getQueryParameters ();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity ( name = "Parent" )
|
||||||
|
public static class Parent {
|
||||||
|
@EmbeddedId
|
||||||
|
public ParentPK id;
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) return true;
|
||||||
|
if ( !( o instanceof Parent ) ) return false;
|
||||||
|
|
||||||
|
final Parent parent = (Parent) o;
|
||||||
|
|
||||||
|
if ( !id.equals( parent.id ) ) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return id.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class ParentPK implements Serializable {
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) return true;
|
||||||
|
if ( !( o instanceof ParentPK ) ) return false;
|
||||||
|
|
||||||
|
final ParentPK parentPk = (ParentPK) o;
|
||||||
|
|
||||||
|
if ( !firstName.equals( parentPk.firstName ) ) return false;
|
||||||
|
if ( !lastName.equals( parentPk.lastName ) ) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result;
|
||||||
|
result = firstName.hashCode();
|
||||||
|
result = 29 * result + lastName.hashCode();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity ( name = "CardField" )
|
||||||
|
public static class CardField implements Serializable {
|
||||||
|
|
||||||
|
@EmbeddedId
|
||||||
|
private CardFieldPK primaryKey;
|
||||||
|
|
||||||
|
CardField(Card card, int fieldNumber) {
|
||||||
|
this.primaryKey = new CardFieldPK(card, fieldNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
CardField() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CardFieldPK getPrimaryKey() {
|
||||||
|
return primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrimaryKey(CardFieldPK primaryKey) {
|
||||||
|
this.primaryKey = primaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( o == null || getClass() != o.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CardField cardField = (CardField) o;
|
||||||
|
|
||||||
|
if ( primaryKey != null ? !primaryKey.equals( cardField.primaryKey ) : cardField.primaryKey != null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return primaryKey != null ? primaryKey.hashCode() : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class CardFieldPK implements Serializable {
|
||||||
|
@ManyToOne(optional = false)
|
||||||
|
private Card card;
|
||||||
|
|
||||||
|
private int fieldNumber;
|
||||||
|
|
||||||
|
public CardFieldPK(Card card, int fieldNumber) {
|
||||||
|
this.card = card;
|
||||||
|
this.fieldNumber = fieldNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
CardFieldPK() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Card getCard() {
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCard(Card card) {
|
||||||
|
this.card = card;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFieldNumber() {
|
||||||
|
return fieldNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldNumber(int fieldNumber) {
|
||||||
|
this.fieldNumber = fieldNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( o == null || getClass() != o.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CardFieldPK that = (CardFieldPK) o;
|
||||||
|
|
||||||
|
if ( fieldNumber != that.fieldNumber ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( card != null ? !card.equals( that.card ) : that.card != null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = card != null ? card.hashCode() : 0;
|
||||||
|
result = 31 * result + fieldNumber;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity ( name = "Card" )
|
||||||
|
public static class Card implements Serializable {
|
||||||
|
@Id
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
public Card(String id) {
|
||||||
|
this();
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
Card() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,7 +69,7 @@ import static org.junit.Assert.assertTrue;
|
||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
@FailureExpectedWithNewMetamodel
|
@FailureExpectedWithNewMetamodel
|
||||||
public class EntityWithCollectionResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
public class EntityWithNonLazyCollectionResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
protected Class<?>[] getAnnotatedClasses() {
|
|
@ -0,0 +1,215 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.loader;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
|
import org.hibernate.engine.spi.QueryParameters;
|
||||||
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
|
import org.hibernate.jdbc.Work;
|
||||||
|
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
|
||||||
|
import org.hibernate.loader.internal.LoadQueryAliasResolutionContextImpl;
|
||||||
|
import org.hibernate.loader.internal.ResultSetProcessorImpl;
|
||||||
|
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
|
||||||
|
import org.hibernate.loader.plan.spi.LoadPlan;
|
||||||
|
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
|
||||||
|
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
|
||||||
|
import org.hibernate.loader.spi.NamedParameterContext;
|
||||||
|
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
|
||||||
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public class EntityWithNonLazyOneToManyListResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] { Poster.class, Message.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEntityWithList() throws Exception {
|
||||||
|
final EntityPersister entityPersister = sessionFactory().getEntityPersister( Poster.class.getName() );
|
||||||
|
|
||||||
|
// create some test data
|
||||||
|
Session session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Poster poster = new Poster();
|
||||||
|
poster.pid = 0;
|
||||||
|
poster.name = "John Doe";
|
||||||
|
Message message1 = new Message();
|
||||||
|
message1.mid = 1;
|
||||||
|
message1.msgTxt = "Howdy!";
|
||||||
|
message1.poster = poster;
|
||||||
|
poster.messages.add( message1 );
|
||||||
|
Message message2 = new Message();
|
||||||
|
message2.mid = 2;
|
||||||
|
message2.msgTxt = "Bye!";
|
||||||
|
message2.poster = poster;
|
||||||
|
poster.messages.add( message2 );
|
||||||
|
session.save( poster );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
Poster posterGotten = (Poster) session.get( Poster.class, poster.pid );
|
||||||
|
assertEquals( 0, posterGotten.pid.intValue() );
|
||||||
|
assertEquals( poster.name, posterGotten.name );
|
||||||
|
assertTrue( Hibernate.isInitialized( posterGotten.messages ) );
|
||||||
|
assertEquals( 2, posterGotten.messages.size() );
|
||||||
|
assertEquals( message1.msgTxt, posterGotten.messages.get( 0 ).msgTxt );
|
||||||
|
assertEquals( message2.msgTxt, posterGotten.messages.get( 1 ).msgTxt );
|
||||||
|
assertSame( posterGotten, posterGotten.messages.get( 0 ).poster );
|
||||||
|
assertSame( posterGotten, posterGotten.messages.get( 1 ).poster );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
|
||||||
|
{
|
||||||
|
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
|
||||||
|
sessionFactory(),
|
||||||
|
LoadQueryInfluencers.NONE
|
||||||
|
);
|
||||||
|
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
|
||||||
|
final LoadQueryAliasResolutionContext aliasResolutionContext =
|
||||||
|
new LoadQueryAliasResolutionContextImpl(
|
||||||
|
sessionFactory(),
|
||||||
|
0,
|
||||||
|
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
|
||||||
|
);
|
||||||
|
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
|
||||||
|
LoadQueryInfluencers.NONE,
|
||||||
|
plan
|
||||||
|
);
|
||||||
|
final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext );
|
||||||
|
|
||||||
|
final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan );
|
||||||
|
final List results = new ArrayList();
|
||||||
|
|
||||||
|
final Session workSession = openSession();
|
||||||
|
workSession.beginTransaction();
|
||||||
|
workSession.doWork(
|
||||||
|
new Work() {
|
||||||
|
@Override
|
||||||
|
public void execute(Connection connection) throws SQLException {
|
||||||
|
PreparedStatement ps = connection.prepareStatement( sql );
|
||||||
|
ps.setInt( 1, 0 );
|
||||||
|
ResultSet resultSet = ps.executeQuery();
|
||||||
|
results.addAll(
|
||||||
|
resultSetProcessor.extractResults(
|
||||||
|
NoOpLoadPlanAdvisor.INSTANCE,
|
||||||
|
resultSet,
|
||||||
|
(SessionImplementor) workSession,
|
||||||
|
new QueryParameters(),
|
||||||
|
new NamedParameterContext() {
|
||||||
|
@Override
|
||||||
|
public int[] getNamedParameterLocations(String name) {
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
aliasResolutionContext,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
resultSet.close();
|
||||||
|
ps.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assertEquals( 2, results.size() );
|
||||||
|
Object result1 = results.get( 0 );
|
||||||
|
assertNotNull( result1 );
|
||||||
|
assertSame( result1, results.get( 1 ) );
|
||||||
|
|
||||||
|
Poster workPoster = ExtraAssertions.assertTyping( Poster.class, result1 );
|
||||||
|
assertEquals( 0, workPoster.pid.intValue() );
|
||||||
|
assertEquals( poster.name, workPoster.name );
|
||||||
|
assertTrue( Hibernate.isInitialized( workPoster.messages ) );
|
||||||
|
assertEquals( 2, workPoster.messages.size() );
|
||||||
|
assertTrue( Hibernate.isInitialized( posterGotten.messages ) );
|
||||||
|
assertEquals( 2, workPoster.messages.size() );
|
||||||
|
assertEquals( message1.msgTxt, workPoster.messages.get( 0 ).msgTxt );
|
||||||
|
assertEquals( message2.msgTxt, workPoster.messages.get( 1 ).msgTxt );
|
||||||
|
assertSame( workPoster, workPoster.messages.get( 0 ).poster );
|
||||||
|
assertSame( workPoster, workPoster.messages.get( 1 ).poster );
|
||||||
|
workSession.getTransaction().commit();
|
||||||
|
workSession.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up test data
|
||||||
|
session = openSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
session.delete( poster );
|
||||||
|
session.getTransaction().commit();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Message" )
|
||||||
|
public static class Message {
|
||||||
|
@Id
|
||||||
|
private Integer mid;
|
||||||
|
private String msgTxt;
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn
|
||||||
|
private Poster poster;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Poster" )
|
||||||
|
public static class Poster {
|
||||||
|
@Id
|
||||||
|
private Integer pid;
|
||||||
|
private String name;
|
||||||
|
@OneToMany(mappedBy = "poster", fetch = FetchType.EAGER, cascade = CascadeType.ALL )
|
||||||
|
private List<Message> messages = new ArrayList<Message>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,7 +72,7 @@ import static org.junit.Assert.fail;
|
||||||
* @author Gail Badner
|
* @author Gail Badner
|
||||||
*/
|
*/
|
||||||
@FailureExpectedWithNewMetamodel
|
@FailureExpectedWithNewMetamodel
|
||||||
public class EntityWithOneToManyResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
public class EntityWithNonLazyOneToManySetResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
protected Class<?>[] getAnnotatedClasses() {
|
|
@ -38,6 +38,7 @@ import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
||||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||||
|
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
|
||||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||||
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||||
import org.hibernate.persister.walking.spi.MetadataDrivenModelGraphVisitor;
|
import org.hibernate.persister.walking.spi.MetadataDrivenModelGraphVisitor;
|
||||||
|
@ -168,6 +169,28 @@ public class BasicWalkingTest extends BaseCoreFunctionalTestCase {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition) {
|
||||||
|
System.out.println(
|
||||||
|
String.format(
|
||||||
|
"%s Starting composite (%s)",
|
||||||
|
StringHelper.repeat( ">>", ++depth ),
|
||||||
|
compositionElementDefinition.toString()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition) {
|
||||||
|
System.out.println(
|
||||||
|
String.format(
|
||||||
|
"%s Finishing composite (%s)",
|
||||||
|
StringHelper.repeat( ">>", depth-- ),
|
||||||
|
compositionElementDefinition.toString()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean startingAttribute(AttributeDefinition attributeDefinition) {
|
public boolean startingAttribute(AttributeDefinition attributeDefinition) {
|
||||||
System.out.println(
|
System.out.println(
|
||||||
|
|
|
@ -26,6 +26,9 @@ package org.hibernate.test.annotations.derivedidentities.bidirectional;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.Query;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.testing.FailureExpected;
|
import org.hibernate.testing.FailureExpected;
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
@ -35,6 +38,7 @@ import org.junit.Test;
|
||||||
@FailureExpected(jiraKey = "HHH-5695")
|
@FailureExpected(jiraKey = "HHH-5695")
|
||||||
public class OneToOneWithDerivedIdentityTest extends BaseCoreFunctionalTestCase {
|
public class OneToOneWithDerivedIdentityTest extends BaseCoreFunctionalTestCase {
|
||||||
@Test
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-5695")
|
||||||
public void testInsertFooAndBarWithDerivedId() {
|
public void testInsertFooAndBarWithDerivedId() {
|
||||||
Session s = openSession();
|
Session s = openSession();
|
||||||
s.beginTransaction();
|
s.beginTransaction();
|
||||||
|
@ -81,11 +85,50 @@ public class OneToOneWithDerivedIdentityTest extends BaseCoreFunctionalTestCase
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-6813")
|
||||||
|
// Regression test utilizing multiple types of queries.
|
||||||
|
public void testCase() {
|
||||||
|
Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
Person p = new Person();
|
||||||
|
p.setName( "Alfio" );
|
||||||
|
PersonInfo pi = new PersonInfo();
|
||||||
|
pi.setId( p );
|
||||||
|
pi.setInfo( "Some information" );
|
||||||
|
s.persist( p );
|
||||||
|
s.persist( pi );
|
||||||
|
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.clear();
|
||||||
|
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
Query q = s.getNamedQuery( "PersonQuery" );
|
||||||
|
List<Person> persons = q.list();
|
||||||
|
assertEquals( persons.size(), 1 );
|
||||||
|
assertEquals( persons.get( 0 ).getName(), "Alfio" );
|
||||||
|
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.clear();
|
||||||
|
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
p = (Person) s.get( Person.class, persons.get( 0 ).getId() );
|
||||||
|
assertEquals( p.getName(), "Alfio" );
|
||||||
|
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
return new Class<?>[] {
|
return new Class<?>[] {
|
||||||
Foo.class,
|
Foo.class,
|
||||||
Bar.class
|
Bar.class,
|
||||||
|
Person.class,
|
||||||
|
PersonInfo.class
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package org.hibernate.test.annotations.derivedidentities.bidirectional;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@NamedQuery(name="PersonQuery", query="SELECT p FROM Person p")
|
||||||
|
public class Person
|
||||||
|
implements Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy=GenerationType.AUTO)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@Basic
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToOne(mappedBy="id")
|
||||||
|
private PersonInfo personInfo;
|
||||||
|
|
||||||
|
public Integer getId()
|
||||||
|
{
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
int hash = 0;
|
||||||
|
hash += (this.id != null ? this.id.hashCode() : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object object)
|
||||||
|
{
|
||||||
|
if (!(object instanceof Person)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Person other = (Person)object;
|
||||||
|
|
||||||
|
return ((this.id != null) || (other.id == null)) && ((this.id == null) || (this.id.equals(other.id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "nogroup.hibertest.Person[ id=" + this.id + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersonInfo getPersonInfo()
|
||||||
|
{
|
||||||
|
return this.personInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonInfo(PersonInfo personInfo)
|
||||||
|
{
|
||||||
|
this.personInfo = personInfo;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.hibernate.test.annotations.derivedidentities.bidirectional;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class PersonInfo
|
||||||
|
implements Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@OneToOne
|
||||||
|
private Person id;
|
||||||
|
|
||||||
|
@Basic
|
||||||
|
private String info;
|
||||||
|
|
||||||
|
public Person getId()
|
||||||
|
{
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Person id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInfo() {
|
||||||
|
return this.info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInfo(String info) {
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
int hash = 0;
|
||||||
|
hash += (this.id != null ? this.id.hashCode() : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object object)
|
||||||
|
{
|
||||||
|
if (!(object instanceof PersonInfo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PersonInfo other = (PersonInfo)object;
|
||||||
|
|
||||||
|
return ((this.id != null) || (other.id == null)) && ((this.id == null) || (this.id.equals(other.id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "nogroup.hibertest.PersonInfo[ id=" + this.id + " ]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,7 +38,7 @@ import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder;
|
import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder;
|
||||||
import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport;
|
import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport;
|
||||||
import org.hibernate.engine.jdbc.internal.ResultSetWrapperImpl;
|
import org.hibernate.engine.jdbc.internal.ResultSetWrapperImpl;
|
||||||
import org.hibernate.engine.jdbc.internal.TypeInfo;
|
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.engine.jdbc.spi.ResultSetWrapper;
|
import org.hibernate.engine.jdbc.spi.ResultSetWrapper;
|
||||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||||
|
|
|
@ -1007,7 +1007,8 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
||||||
sessionFactory,
|
sessionFactory,
|
||||||
settings,
|
settings,
|
||||||
configurationValues,
|
configurationValues,
|
||||||
serviceRegistry.getService( ConfigurationService.class ).getSettings()
|
serviceRegistry.getService( ConfigurationService.class ).getSettings(),
|
||||||
|
metadata
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -68,7 +68,7 @@ public abstract class AbstractScannerImpl implements Scanner {
|
||||||
|
|
||||||
if ( persistenceUnit.getPersistenceUnitRootUrl() != null ) {
|
if ( persistenceUnit.getPersistenceUnitRootUrl() != null ) {
|
||||||
final ArchiveDescriptor descriptor = buildArchiveDescriptor( persistenceUnit.getPersistenceUnitRootUrl(), true, scanOptions );
|
final ArchiveDescriptor descriptor = buildArchiveDescriptor( persistenceUnit.getPersistenceUnitRootUrl(), true, scanOptions );
|
||||||
final ArchiveContext context = buildArchiveContext( persistenceUnit, false, resultCollector );
|
final ArchiveContext context = buildArchiveContext( persistenceUnit, true, resultCollector );
|
||||||
descriptor.visitArchive( context );
|
descriptor.visitArchive( context );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,42 +162,42 @@ public abstract class AbstractGraphNode<T> implements GraphNodeImplementor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X> Subgraph<X> addSubgraph(Attribute<T, X> attribute) {
|
public <X> SubgraphImpl<X> addSubgraph(Attribute<T, X> attribute) {
|
||||||
return addAttribute( attribute ).makeSubgraph();
|
return addAttribute( attribute ).makeSubgraph();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X> Subgraph<? extends X> addSubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
public <X> SubgraphImpl<? extends X> addSubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||||
return addAttribute( attribute ).makeSubgraph( type );
|
return addAttribute( attribute ).makeSubgraph( type );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X> Subgraph<X> addSubgraph(String attributeName) {
|
public <X> SubgraphImpl<X> addSubgraph(String attributeName) {
|
||||||
return addAttribute( attributeName ).makeSubgraph();
|
return addAttribute( attributeName ).makeSubgraph();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X> Subgraph<X> addSubgraph(String attributeName, Class<X> type) {
|
public <X> SubgraphImpl<X> addSubgraph(String attributeName, Class<X> type) {
|
||||||
return addAttribute( attributeName ).makeSubgraph( type );
|
return addAttribute( attributeName ).makeSubgraph( type );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X> Subgraph<X> addKeySubgraph(Attribute<T, X> attribute) {
|
public <X> SubgraphImpl<X> addKeySubgraph(Attribute<T, X> attribute) {
|
||||||
return addAttribute( attribute ).makeKeySubgraph();
|
return addAttribute( attribute ).makeKeySubgraph();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X> Subgraph<? extends X> addKeySubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
public <X> SubgraphImpl<? extends X> addKeySubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||||
return addAttribute( attribute ).makeKeySubgraph( type );
|
return addAttribute( attribute ).makeKeySubgraph( type );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X> Subgraph<X> addKeySubgraph(String attributeName) {
|
public <X> SubgraphImpl<X> addKeySubgraph(String attributeName) {
|
||||||
return addAttribute( attributeName ).makeKeySubgraph();
|
return addAttribute( attributeName ).makeKeySubgraph();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X> Subgraph<X> addKeySubgraph(String attributeName, Class<X> type) {
|
public <X> SubgraphImpl<X> addKeySubgraph(String attributeName, Class<X> type) {
|
||||||
return addAttribute( attributeName ).makeKeySubgraph( type );
|
return addAttribute( attributeName ).makeKeySubgraph( type );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,16 +108,16 @@ public class AttributeNodeImpl<T> implements AttributeNode<T>, AttributeNodeImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> Subgraph<T> makeSubgraph() {
|
public <T> SubgraphImpl<T> makeSubgraph() {
|
||||||
return (Subgraph<T>) internalMakeSubgraph( null );
|
return (SubgraphImpl<T>) internalMakeSubgraph( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X extends T> Subgraph<X> makeSubgraph(Class<X> type) {
|
public <X extends T> SubgraphImpl<X> makeSubgraph(Class<X> type) {
|
||||||
return (Subgraph<X>) internalMakeSubgraph( type );
|
return (SubgraphImpl<X>) internalMakeSubgraph( type );
|
||||||
}
|
}
|
||||||
|
|
||||||
private Subgraph internalMakeSubgraph(Class type) {
|
private SubgraphImpl internalMakeSubgraph(Class type) {
|
||||||
if ( attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.BASIC
|
if ( attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.BASIC
|
||||||
|| attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED ) {
|
|| attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED ) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
@ -193,12 +193,17 @@ public class AttributeNodeImpl<T> implements AttributeNode<T>, AttributeNodeImpl
|
||||||
return type.isAssignableFrom( entityPersister.getMappedClass() );
|
return type.isAssignableFrom( entityPersister.getMappedClass() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> Subgraph<T> makeKeySubgraph() {
|
@SuppressWarnings("unchecked")
|
||||||
return (SubgraphImpl<T>) makeKeySubgraph( null );
|
public <T> SubgraphImpl<T> makeKeySubgraph() {
|
||||||
|
return (SubgraphImpl<T>) internalMakeKeySubgraph( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <X extends T> Subgraph<X> makeKeySubgraph(Class<X> type) {
|
public <X extends T> SubgraphImpl<X> makeKeySubgraph(Class<X> type) {
|
||||||
|
return (SubgraphImpl<X>) internalMakeKeySubgraph( type );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubgraphImpl internalMakeKeySubgraph(Class type) {
|
||||||
if ( ! attribute.isCollection() ) {
|
if ( ! attribute.isCollection() ) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
String.format( "Non-collection attribute [%s] cannot be target of key subgraph", getAttributeName() )
|
String.format( "Non-collection attribute [%s] cannot be target of key subgraph", getAttributeName() )
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue