HHH-7841 - Redesign Loader

This commit is contained in:
Steve Ebersole 2013-03-04 15:58:16 -06:00
parent c259e157b0
commit a102bf2c31
70 changed files with 5048 additions and 335 deletions

View File

@ -0,0 +1,50 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.engine;
/**
* Describes the strategy for fetching an association
* <p/>
* todo not really a fan of the name. not sure of a better one though.
* I'd almost rather see this be called the style, but then what to call FetchStyle? HowToFetch?
*
* @author Steve Ebersole
*/
public class FetchStrategy {
private final FetchTiming timing;
private final FetchStyle style;
public FetchStrategy(FetchTiming timing, FetchStyle style) {
this.timing = timing;
this.style = style;
}
public FetchTiming getTiming() {
return timing;
}
public FetchStyle getStyle() {
return style;
}
}

View File

@ -0,0 +1,60 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.internal;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
/**
* A LoadPlan building strategy for cascade processing; meaning, it builds the LoadPlan for loading related to
* cascading a particular action across associations
*
* @author Steve Ebersole
*/
public class CascadeLoadPlanBuilderStrategy extends SingleRootReturnLoadPlanBuilderStrategy {
private static final FetchStrategy EAGER = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
private static final FetchStrategy DELAYED = new FetchStrategy( FetchTiming.DELAYED, FetchStyle.SELECT );
private final CascadingAction cascadeActionToMatch;
public CascadeLoadPlanBuilderStrategy(
CascadingAction cascadeActionToMatch,
SessionFactoryImplementor sessionFactory,
LoadQueryInfluencers loadQueryInfluencers,
String rootAlias,
int suffixSeed) {
super( sessionFactory, loadQueryInfluencers, rootAlias, suffixSeed );
this.cascadeActionToMatch = cascadeActionToMatch;
}
@Override
protected FetchStrategy determineFetchPlan(AssociationAttributeDefinition attributeDefinition) {
return attributeDefinition.determineCascadeStyle().doCascade( cascadeActionToMatch ) ? EAGER : DELAYED;
}
}

View File

@ -0,0 +1,59 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.internal;
import java.util.Collections;
import java.util.List;
import org.hibernate.loader.plan.spi.LoadPlan;
import org.hibernate.loader.plan.spi.Return;
/**
* Implementation of LoadPlan.
*
* @author Steve Ebersole
*/
public class LoadPlanImpl implements LoadPlan {
private final boolean hasScalars;
private final List<Return> returns;
public LoadPlanImpl(boolean hasScalars, List<Return> returns) {
this.hasScalars = hasScalars;
this.returns = returns;
}
public LoadPlanImpl(boolean hasScalars, Return rootReturn) {
this( hasScalars, Collections.singletonList( rootReturn ) );
}
@Override
public boolean hasAnyScalarReturns() {
return hasScalars;
}
@Override
public List<Return> getReturns() {
return returns;
}
}

View File

@ -0,0 +1,268 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.internal;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.DefaultEntityAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.GeneratedCollectionAliases;
import org.hibernate.loader.PropertyPath;
import org.hibernate.loader.plan.spi.AbstractFetchOwner;
import org.hibernate.loader.plan.spi.AbstractLoadPlanBuilderStrategy;
import org.hibernate.loader.plan.spi.CollectionFetch;
import org.hibernate.loader.plan.spi.CollectionReturn;
import org.hibernate.loader.plan.spi.CompositeFetch;
import org.hibernate.loader.plan.spi.EntityFetch;
import org.hibernate.loader.plan.spi.EntityReturn;
import org.hibernate.loader.plan.spi.FetchOwner;
import org.hibernate.loader.plan.spi.LoadPlan;
import org.hibernate.loader.plan.spi.LoadPlanBuilderStrategy;
import org.hibernate.loader.plan.spi.Return;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CompositeDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
/**
* LoadPlanBuilderStrategy implementation used for building LoadPlans with a single processing RootEntity LoadPlan building.
*
* Really this is a single-root LoadPlan building strategy for building LoadPlans for:<ul>
* <li>entity load plans</li>
* <li>cascade load plans</li>
* <li>collection initializer plans</li>
* </ul>
*
* @author Steve Ebersole
*/
public class SingleRootReturnLoadPlanBuilderStrategy
extends AbstractLoadPlanBuilderStrategy
implements LoadPlanBuilderStrategy {
private final LoadQueryInfluencers loadQueryInfluencers;
private final String rootAlias;
private int currentSuffixBase;
private Return rootReturn;
private PropertyPath propertyPath = new PropertyPath( "" );
public SingleRootReturnLoadPlanBuilderStrategy(
SessionFactoryImplementor sessionFactory,
LoadQueryInfluencers loadQueryInfluencers,
String rootAlias,
int suffixSeed) {
super( sessionFactory );
this.loadQueryInfluencers = loadQueryInfluencers;
this.rootAlias = rootAlias;
this.currentSuffixBase = suffixSeed;
}
@Override
protected boolean supportsRootEntityReturns() {
return true;
}
@Override
protected boolean supportsRootCollectionReturns() {
return true;
}
@Override
protected void addRootReturn(Return rootReturn) {
if ( this.rootReturn != null ) {
throw new HibernateException( "Root return already identified" );
}
this.rootReturn = rootReturn;
}
@Override
public LoadPlan buildLoadPlan() {
return new LoadPlanImpl( false, rootReturn );
}
@Override
protected FetchStrategy determineFetchPlan(AssociationAttributeDefinition attributeDefinition) {
FetchStrategy fetchStrategy = attributeDefinition.determineFetchPlan( loadQueryInfluencers, propertyPath );
if ( fetchStrategy.getTiming() == FetchTiming.IMMEDIATE && fetchStrategy.getStyle() == FetchStyle.JOIN ) {
// see if we need to alter the join fetch to another form for any reason
fetchStrategy = adjustJoinFetchIfNeeded( attributeDefinition, fetchStrategy );
}
return fetchStrategy;
}
protected FetchStrategy adjustJoinFetchIfNeeded(
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy) {
if ( currentDepth() > sessionFactory().getSettings().getMaximumFetchDepth() ) {
return new FetchStrategy( fetchStrategy.getTiming(), FetchStyle.SELECT );
}
if ( attributeDefinition.getType().isCollectionType() && isTooManyCollections() ) {
// todo : have this revert to batch or subselect fetching once "sql gen redesign" is in place
return new FetchStrategy( fetchStrategy.getTiming(), FetchStyle.SELECT );
}
return fetchStrategy;
}
@Override
protected boolean isTooManyCollections() {
return false;
}
@Override
protected EntityReturn buildRootEntityReturn(EntityDefinition entityDefinition) {
final String entityName = entityDefinition.getEntityPersister().getEntityName();
return new EntityReturn(
sessionFactory(),
rootAlias,
LockMode.NONE, // todo : for now
entityName,
StringHelper.generateAlias( StringHelper.unqualifyEntityName( entityName ), currentDepth() ),
new DefaultEntityAliases(
(Loadable) entityDefinition.getEntityPersister(),
Integer.toString( currentSuffixBase++ ) + '_'
)
);
}
@Override
protected CollectionReturn buildRootCollectionReturn(CollectionDefinition collectionDefinition) {
final CollectionPersister persister = collectionDefinition.getCollectionPersister();
final String collectionRole = persister.getRole();
final CollectionAliases collectionAliases = new GeneratedCollectionAliases(
collectionDefinition.getCollectionPersister(),
Integer.toString( currentSuffixBase++ ) + '_'
);
final Type elementType = collectionDefinition.getCollectionPersister().getElementType();
final EntityAliases elementAliases;
if ( elementType.isEntityType() ) {
final EntityType entityElementType = (EntityType) elementType;
elementAliases = new DefaultEntityAliases(
(Loadable) entityElementType.getAssociatedJoinable( sessionFactory() ),
Integer.toString( currentSuffixBase++ ) + '_'
);
}
else {
elementAliases = null;
}
return new CollectionReturn(
sessionFactory(),
rootAlias,
LockMode.NONE, // todo : for now
persister.getOwnerEntityPersister().getEntityName(),
StringHelper.unqualify( collectionRole ),
collectionAliases,
elementAliases
);
}
@Override
protected CollectionFetch buildCollectionFetch(
FetchOwner fetchOwner,
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy) {
final CollectionDefinition collectionDefinition = attributeDefinition.toCollectionDefinition();
final CollectionAliases collectionAliases = new GeneratedCollectionAliases(
collectionDefinition.getCollectionPersister(),
Integer.toString( currentSuffixBase++ ) + '_'
);
final Type elementType = collectionDefinition.getCollectionPersister().getElementType();
final EntityAliases elementAliases;
if ( elementType.isEntityType() ) {
final EntityType entityElementType = (EntityType) elementType;
elementAliases = new DefaultEntityAliases(
(Loadable) entityElementType.getAssociatedJoinable( sessionFactory() ),
Integer.toString( currentSuffixBase++ ) + '_'
);
}
else {
elementAliases = null;
}
return new CollectionFetch(
sessionFactory(),
createImplicitAlias(),
LockMode.NONE, // todo : for now
(AbstractFetchOwner) fetchOwner,
fetchStrategy,
attributeDefinition.getName(),
collectionAliases,
elementAliases
);
}
@Override
protected EntityFetch buildEntityFetch(
FetchOwner fetchOwner,
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy) {
final EntityDefinition entityDefinition = attributeDefinition.toEntityDefinition();
return new EntityFetch(
sessionFactory(),
createImplicitAlias(),
LockMode.NONE, // todo : for now
(AbstractFetchOwner) fetchOwner,
attributeDefinition.getName(),
fetchStrategy,
StringHelper.generateAlias( entityDefinition.getEntityPersister().getEntityName(), currentDepth() ),
new DefaultEntityAliases(
(Loadable) entityDefinition.getEntityPersister(),
Integer.toString( currentSuffixBase++ ) + '_'
)
);
}
@Override
protected CompositeFetch buildCompositeFetch(FetchOwner fetchOwner, CompositeDefinition attributeDefinition) {
return new CompositeFetch(
sessionFactory(),
createImplicitAlias(),
(AbstractFetchOwner) fetchOwner,
attributeDefinition.getName()
);
}
private int implicitAliasUniqueness = 0;
private String createImplicitAlias() {
return "ia" + implicitAliasUniqueness++;
}
}

View File

@ -0,0 +1,88 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath;
/**
* @author Steve Ebersole
*/
public abstract class AbstractFetch extends AbstractFetchOwner implements Fetch {
private final FetchOwner owner;
private final String ownerProperty;
private final FetchStrategy fetchStrategy;
private final PropertyPath propertyPath;
public AbstractFetch(
SessionFactoryImplementor factory,
String alias,
LockMode lockMode,
AbstractFetchOwner owner,
String ownerProperty,
FetchStrategy fetchStrategy) {
super( factory, alias, lockMode );
this.owner = owner;
this.ownerProperty = ownerProperty;
this.fetchStrategy = fetchStrategy;
owner.addFetch( this );
this.propertyPath = owner.getPropertyPath().append( ownerProperty );
}
@Override
public FetchOwner getOwner() {
return owner;
}
@Override
public String getOwnerPropertyName() {
return ownerProperty;
}
@Override
public FetchStrategy getFetchStrategy() {
return fetchStrategy;
}
@Override
public void validateFetchPlan(FetchStrategy fetchStrategy) {
if ( fetchStrategy.getStyle() == FetchStyle.JOIN ) {
if ( this.fetchStrategy.getStyle() != FetchStyle.JOIN ) {
throw new HibernateException( "Cannot specify join fetch from owner that is a non-joined fetch" );
}
}
}
@Override
public PropertyPath getPropertyPath() {
return propertyPath;
}
}

View File

@ -0,0 +1,75 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.ArrayList;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
/**
* @author Steve Ebersole
*/
public abstract class AbstractFetchOwner extends AbstractPlanNode implements FetchOwner {
private final String alias;
private final LockMode lockMode;
private List<Fetch> fetches;
public AbstractFetchOwner(SessionFactoryImplementor factory, String alias, LockMode lockMode) {
super( factory );
this.alias = alias;
if ( alias == null ) {
throw new HibernateException( "alias must be specified" );
}
this.lockMode = lockMode;
}
public String getAlias() {
return alias;
}
public LockMode getLockMode() {
return lockMode;
}
void addFetch(Fetch fetch) {
if ( fetch.getOwner() != this ) {
throw new IllegalArgumentException( "Fetch and owner did not match" );
}
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() ] );
}
}

View File

@ -0,0 +1,212 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.ArrayDeque;
import org.hibernate.HibernateException;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CompositeDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.type.Type;
/**
* @author Steve Ebersole
*/
public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilderStrategy {
private final SessionFactoryImplementor sessionFactory;
private ArrayDeque<FetchOwner> fetchOwnerStack = new ArrayDeque<FetchOwner>();
protected AbstractLoadPlanBuilderStrategy(SessionFactoryImplementor sessionFactory) {
this.sessionFactory = sessionFactory;
}
public SessionFactoryImplementor sessionFactory() {
return sessionFactory;
}
protected FetchOwner currentFetchOwner() {
return fetchOwnerStack.peekLast();
}
@Override
public void start() {
// nothing to do
}
@Override
public void finish() {
// nothing to do
}
@Override
public void startingEntity(EntityDefinition entityDefinition) {
if ( fetchOwnerStack.isEmpty() ) {
// this is a root...
if ( ! supportsRootEntityReturns() ) {
throw new HibernateException( "This strategy does not support root entity returns" );
}
final EntityReturn entityReturn = buildRootEntityReturn( entityDefinition );
addRootReturn( entityReturn );
fetchOwnerStack.push( entityReturn );
}
// otherwise this call should represent a fetch which should have been handled in #startingAttribute
}
protected boolean supportsRootEntityReturns() {
return false;
}
protected abstract void addRootReturn(Return rootReturn);
@Override
public void finishingEntity(EntityDefinition entityDefinition) {
// nothing to do
}
@Override
public void startingCollection(CollectionDefinition collectionDefinition) {
if ( fetchOwnerStack.isEmpty() ) {
// this is a root...
if ( ! supportsRootCollectionReturns() ) {
throw new HibernateException( "This strategy does not support root collection returns" );
}
final CollectionReturn collectionReturn = buildRootCollectionReturn( collectionDefinition );
addRootReturn( collectionReturn );
fetchOwnerStack.push( collectionReturn );
}
}
protected boolean supportsRootCollectionReturns() {
return false;
}
@Override
public void finishingCollection(CollectionDefinition collectionDefinition) {
// nothing to do
}
@Override
public void startingComposite(CompositeDefinition compositeDefinition) {
if ( fetchOwnerStack.isEmpty() ) {
throw new HibernateException( "A component cannot be the root of a walk nor a graph" );
}
}
@Override
public void finishingComposite(CompositeDefinition compositeDefinition) {
// nothing to do
}
@Override
public boolean startingAttribute(AttributeDefinition attributeDefinition) {
final Type attributeType = attributeDefinition.getType();
final boolean isComponentType = attributeType.isComponentType();
final boolean isBasicType = ! ( isComponentType || attributeType.isAssociationType() );
if ( isBasicType ) {
return true;
}
else if ( isComponentType ) {
return handleCompositeAttribute( (CompositeDefinition) attributeDefinition );
}
else {
return handleAssociationAttribute( (AssociationAttributeDefinition) attributeDefinition );
}
}
@Override
public void finishingAttribute(AttributeDefinition attributeDefinition) {
final Type attributeType = attributeDefinition.getType();
final boolean isComponentType = attributeType.isComponentType();
final boolean isBasicType = ! ( isComponentType || attributeType.isAssociationType() );
if ( ! isBasicType ) {
fetchOwnerStack.removeLast();
}
}
protected boolean handleCompositeAttribute(CompositeDefinition attributeDefinition) {
final FetchOwner fetchOwner = fetchOwnerStack.peekLast();
final CompositeFetch fetch = buildCompositeFetch( fetchOwner, attributeDefinition );
fetchOwnerStack.addLast( fetch );
return true;
}
protected boolean handleAssociationAttribute(AssociationAttributeDefinition attributeDefinition) {
final FetchStrategy fetchStrategy = determineFetchPlan( attributeDefinition );
if ( fetchStrategy.getTiming() != FetchTiming.IMMEDIATE ) {
return false;
}
final FetchOwner fetchOwner = fetchOwnerStack.peekLast();
fetchOwner.validateFetchPlan( fetchStrategy );
final Fetch associationFetch;
if ( attributeDefinition.isCollection() ) {
associationFetch = buildCollectionFetch( fetchOwner, attributeDefinition, fetchStrategy );
}
else {
associationFetch = buildEntityFetch( fetchOwner, attributeDefinition, fetchStrategy );
}
fetchOwnerStack.addLast( associationFetch );
return true;
}
protected abstract FetchStrategy determineFetchPlan(AssociationAttributeDefinition attributeDefinition);
protected int currentDepth() {
return fetchOwnerStack.size();
}
protected boolean isTooManyCollections() {
return false;
}
protected abstract EntityReturn buildRootEntityReturn(EntityDefinition entityDefinition);
protected abstract CollectionReturn buildRootCollectionReturn(CollectionDefinition collectionDefinition);
protected abstract CollectionFetch buildCollectionFetch(
FetchOwner fetchOwner,
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy);
protected abstract EntityFetch buildEntityFetch(
FetchOwner fetchOwner,
AssociationAttributeDefinition attributeDefinition,
FetchStrategy fetchStrategy);
protected abstract CompositeFetch buildCompositeFetch(FetchOwner fetchOwner, CompositeDefinition attributeDefinition);
}

View File

@ -0,0 +1,43 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.spi.SessionFactoryImplementor;
/**
* Base class for LoadPlan nodes to hold references to the session factory.
*
* @author Steve Ebersole
*/
public abstract class AbstractPlanNode {
private final SessionFactoryImplementor sessionFactory;
public AbstractPlanNode(SessionFactoryImplementor sessionFactory) {
this.sessionFactory = sessionFactory;
}
protected SessionFactoryImplementor sessionFactory() {
return sessionFactory;
}
}

View File

@ -0,0 +1,80 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.EntityPersister;
/**
* @author Steve Ebersole
*/
public class CollectionFetch extends AbstractFetch implements CollectionReference {
private final CollectionAliases collectionAliases;
private final EntityAliases elementEntityAliases;
private final CollectionPersister persister;
public CollectionFetch(
SessionFactoryImplementor sessionFactory,
String alias,
LockMode lockMode,
AbstractFetchOwner owner,
FetchStrategy fetchStrategy,
String ownerProperty,
CollectionAliases collectionAliases,
EntityAliases elementEntityAliases) {
super( sessionFactory, alias, lockMode, owner, ownerProperty, fetchStrategy );
this.collectionAliases = collectionAliases;
this.elementEntityAliases = elementEntityAliases;
final String role = owner.retrieveFetchSourcePersister().getEntityName() + '.' + getOwnerPropertyName();
this.persister = sessionFactory.getCollectionPersister( role );
}
@Override
public CollectionAliases getCollectionAliases() {
return collectionAliases;
}
@Override
public EntityAliases getElementEntityAliases() {
return elementEntityAliases;
}
@Override
public CollectionPersister getCollectionPersister() {
return persister;
}
@Override
public EntityPersister retrieveFetchSourcePersister() {
return ( (QueryableCollection) getCollectionPersister() ).getElementPersister();
}
}

View File

@ -0,0 +1,73 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.LockMode;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.persister.collection.CollectionPersister;
/**
* Represents a reference to an owned collection either as a return or as a fetch
*
* @author Steve Ebersole
*/
public interface CollectionReference {
/**
* Retrieve the alias associated with the persister (entity/collection).
*
* @return The alias
*/
public String getAlias();
/**
* Retrieve the lock mode associated with this return.
*
* @return The lock mode.
*/
public LockMode getLockMode();
/**
* Retrieves the CollectionPersister describing the collection associated with this Return.
*
* @return The CollectionPersister.
*/
public CollectionPersister getCollectionPersister();
/**
* Returns the description of the aliases in the JDBC ResultSet that identify values "belonging" to the
* this collection.
*
* @return The ResultSet alias descriptor for the collection
*/
public CollectionAliases getCollectionAliases();
/**
* If the elements of this collection are entities, this methods returns the JDBC ResultSet alias descriptions
* for that entity; {@code null} indicates a non-entity collection.
*
* @return The ResultSet alias descriptor for the collection's entity element, or {@code null}
*/
public EntityAliases getElementEntityAliases();
}

View File

@ -0,0 +1,113 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.EntityPersister;
/**
* @author Steve Ebersole
*/
public class CollectionReturn extends AbstractFetchOwner implements Return, FetchOwner, CollectionReference {
private final String ownerEntityName;
private final String ownerProperty;
private final CollectionAliases collectionAliases;
private final EntityAliases elementEntityAliases;
private final CollectionPersister persister;
private final PropertyPath propertyPath = new PropertyPath(); // its a root
public CollectionReturn(
SessionFactoryImplementor sessionFactory,
String alias,
LockMode lockMode,
String ownerEntityName,
String ownerProperty,
CollectionAliases collectionAliases,
EntityAliases elementEntityAliases) {
super( sessionFactory, alias, lockMode );
this.ownerEntityName = ownerEntityName;
this.ownerProperty = ownerProperty;
this.collectionAliases = collectionAliases;
this.elementEntityAliases = elementEntityAliases;
final String role = ownerEntityName + '.' + ownerProperty;
this.persister = sessionFactory.getCollectionPersister( role );
}
/**
* Returns the class owning the collection.
*
* @return The class owning the collection.
*/
public String getOwnerEntityName() {
return ownerEntityName;
}
/**
* Returns the name of the property representing the collection from the {@link #getOwnerEntityName}.
*
* @return The name of the property representing the collection on the owner class.
*/
public String getOwnerProperty() {
return ownerProperty;
}
@Override
public CollectionAliases getCollectionAliases() {
return collectionAliases;
}
@Override
public EntityAliases getElementEntityAliases() {
return elementEntityAliases;
}
@Override
public CollectionPersister getCollectionPersister() {
return persister;
}
@Override
public void validateFetchPlan(FetchStrategy fetchStrategy) {
}
@Override
public EntityPersister retrieveFetchSourcePersister() {
return ( (QueryableCollection) persister ).getElementPersister();
}
@Override
public PropertyPath getPropertyPath() {
return propertyPath;
}
}

View File

@ -0,0 +1,51 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister;
/**
* @author Steve Ebersole
*/
public class CompositeFetch extends AbstractFetch implements Fetch {
public static final FetchStrategy FETCH_PLAN = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
public CompositeFetch(
SessionFactoryImplementor sessionFactory,
String alias,
AbstractFetchOwner owner,
String ownerProperty) {
super( sessionFactory, alias, LockMode.NONE, owner, ownerProperty, FETCH_PLAN );
}
@Override
public EntityPersister retrieveFetchSourcePersister() {
return getOwner().retrieveFetchSourcePersister();
}
}

View File

@ -0,0 +1,78 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.EntityAliases;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.EntityType;
/**
* @author Steve Ebersole
*/
public class EntityFetch extends AbstractFetch implements EntityReference {
private final String sqlTableAlias;
private final EntityAliases entityAliases;
private final EntityPersister persister;
public EntityFetch(
SessionFactoryImplementor sessionFactory,
String alias,
LockMode lockMode,
AbstractFetchOwner owner,
String ownerProperty,
FetchStrategy fetchStrategy,
String sqlTableAlias,
EntityAliases entityAliases) {
super( sessionFactory, alias, lockMode, owner, ownerProperty, fetchStrategy );
this.sqlTableAlias = sqlTableAlias;
this.entityAliases = entityAliases;
final EntityType type = (EntityType) owner.retrieveFetchSourcePersister().getPropertyType( ownerProperty );
this.persister = sessionFactory.getEntityPersister( type.getAssociatedEntityName() );
}
@Override
public EntityPersister getEntityPersister() {
return persister;
}
@Override
public EntityAliases getEntityAliases() {
return entityAliases;
}
@Override
public String getSqlTableAlias() {
return sqlTableAlias;
}
@Override
public EntityPersister retrieveFetchSourcePersister() {
return persister;
}
}

View File

@ -0,0 +1,73 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.LockMode;
import org.hibernate.loader.EntityAliases;
import org.hibernate.persister.entity.EntityPersister;
/**
* Represents a reference to an entity either as a return or as a fetch
*
* @author Steve Ebersole
*/
public interface EntityReference {
/**
* Retrieve the alias associated with the persister (entity/collection).
*
* @return The alias
*/
public String getAlias();
/**
* Retrieve the lock mode associated with this return.
*
* @return The lock mode.
*/
public LockMode getLockMode();
/**
* Retrieves the EntityPersister describing the entity associated with this Return.
*
* @return The EntityPersister.
*/
public EntityPersister getEntityPersister();
/**
* Returns the description of the aliases in the JDBC ResultSet that identify values "belonging" to the this entity.
*
* @return The ResultSet alias descriptor.
*/
public EntityAliases getEntityAliases();
/**
* Obtain the SQL table alias associated with this entity.
*
* TODO : eventually this needs to not be a String, but a representation like I did for the Antlr3 branch
* (AliasRoot, I think it was called)
*
* @return The SQL table alias for this entity
*/
public String getSqlTableAlias();
}

View File

@ -0,0 +1,96 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.LockMode;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.entity.EntityPersister;
/**
* @author Steve Ebersole
*/
public class EntityReturn extends AbstractFetchOwner implements Return, FetchOwner, EntityReference {
private final EntityAliases entityAliases;
private final String sqlTableAlias;
private final EntityPersister persister;
private final PropertyPath propertyPath = new PropertyPath(); // its a root
public EntityReturn(
SessionFactoryImplementor sessionFactory,
String alias,
LockMode lockMode,
String entityName,
String sqlTableAlias,
EntityAliases entityAliases) {
super( sessionFactory, alias, lockMode );
this.entityAliases = entityAliases;
this.sqlTableAlias = sqlTableAlias;
this.persister = sessionFactory.getEntityPersister( entityName );
}
@Override
public String getAlias() {
return super.getAlias();
}
@Override
public LockMode getLockMode() {
return super.getLockMode();
}
@Override
public EntityPersister getEntityPersister() {
return persister;
}
@Override
public EntityAliases getEntityAliases() {
return entityAliases;
}
@Override
public String getSqlTableAlias() {
return sqlTableAlias;
}
@Override
public void validateFetchPlan(FetchStrategy fetchStrategy) {
}
@Override
public EntityPersister retrieveFetchSourcePersister() {
return getEntityPersister();
}
@Override
public PropertyPath getPropertyPath() {
return propertyPath;
}
}

View File

@ -0,0 +1,59 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.FetchStrategy;
import org.hibernate.loader.PropertyPath;
/**
* Contract for associations that are being fetched.
* <p/>
* NOTE : can represent components/embeddables
*
* @author Steve Ebersole
*/
public interface Fetch extends FetchOwner {
/**
* Obtain the owner of this fetch.
*
* @return The fetch owner.
*/
public FetchOwner getOwner();
/**
* Obtain the name of the property, relative to the owner, being fetched.
*
* @return The fetched property name.
*/
public String getOwnerPropertyName();
public FetchStrategy getFetchStrategy();
/**
* Get the property path to this fetch
*
* @return The property path
*/
public PropertyPath getPropertyPath();
}

View File

@ -0,0 +1,68 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.FetchStrategy;
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.entity.EntityPersister;
/**
* Contract for owners of fetches. Any non-scalar return could be a fetch owner.
*
* @author Steve Ebersole
*/
public interface FetchOwner {
/**
* Convenient constant for returning no fetches from {@link #getFetches()}
*/
public static final Fetch[] NO_FETCHES = new Fetch[0];
/**
* Retrieve the fetches owned by this return.
*
* @return The owned fetches.
*/
public Fetch[] getFetches();
/**
* Is the asserted plan valid from this owner to a fetch?
*
* @param fetchStrategy The pla to validate
*/
public void validateFetchPlan(FetchStrategy fetchStrategy);
/**
* Retrieve the EntityPersister that is the base for any property references in the fetches it owns.
*
* @return The EntityPersister, for property name resolution.
*/
public EntityPersister retrieveFetchSourcePersister();
/**
* Get the property path to this fetch owner
*
* @return The property path
*/
public PropertyPath getPropertyPath();
}

View File

@ -0,0 +1,61 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.List;
/**
* Describes a plan for performing a load of results.
*
* Generally speaking there are 3 forms of load plans:<ul>
* <li>
* An entity load plan for handling get/load handling. This form will typically have a single
* return (of type {@link EntityReturn}) defined by {@link #getReturns()}, possibly defining fetches.
* </li>
* <li>
* A collection initializer, used to load the contents of a collection. This form will typically have a
* single return (of type {@link CollectionReturn} defined by {@link #getReturns()}, possibly defining fetches
* </li>
* <li>
* A query load plan which can contain multiple returns of mixed type (though implementing {@link Return}).
* Again, may possibly define fetches.
* </li>
* </ul>
*
* @author Steve Ebersole
*/
public interface LoadPlan {
/**
* Convenient form of checking {@link #getReturns()} for scalar root returns.
*
* @return {@code true} if {@link #getReturns()} contained any scalar returns; {@code false} otherwise.
*/
public boolean hasAnyScalarReturns();
public List<Return> getReturns();
// todo : would also like to see "call back" style access for handling "subsequent actions" such as:
// 1) follow-on locking
// 2) join fetch conversions to subselect fetches
}

View File

@ -0,0 +1,64 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.walking.spi.MetadataDrivenModelGraphVisitor;
/**
* Coordinates building of a {@link LoadPlan} between the {@link org.hibernate.persister.walking.spi.MetadataDrivenModelGraphVisitor} and
* {@link LoadPlanBuilderStrategy}
*
* @author Steve Ebersole
*/
public class LoadPlanBuilder {
/**
* Coordinates building a LoadPlan that defines just a single root entity return (may have fetches).
* <p/>
* Typically this includes building load plans for entity loading or cascade loading.
*
* @param strategy The strategy defining the load plan shaping
* @param persister The persister for the entity forming the root of the load plan.
*
* @return The built load plan.
*/
public static LoadPlan buildRootEntityLoadPlan(LoadPlanBuilderStrategy strategy, EntityPersister persister) {
MetadataDrivenModelGraphVisitor.visitEntity( strategy, persister );
return strategy.buildLoadPlan();
}
/**
* Coordinates building a LoadPlan that defines just a single root collection return (may have fetches).
*
* @param strategy The strategy defining the load plan shaping
* @param persister The persister for the collection forming the root of the load plan.
*
* @return The built load plan.
*/
public static LoadPlan buildRootCollectionLoadPlan(LoadPlanBuilderStrategy strategy, CollectionPersister persister) {
MetadataDrivenModelGraphVisitor.visitCollection( strategy, persister );
return strategy.buildLoadPlan();
}
}

View File

@ -0,0 +1,40 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.persister.walking.spi.AssociationVisitationStrategy;
/**
* Specialized {@link org.hibernate.persister.walking.spi.AssociationVisitationStrategy} implementation for building {@link LoadPlan} instances.
*
* @author Steve Ebersole
*/
public interface LoadPlanBuilderStrategy extends AssociationVisitationStrategy {
/**
* After visitation is done, build the load plan.
*
* @return The load plan
*/
public LoadPlan buildLoadPlan();
}

View File

@ -0,0 +1,40 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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;
/**
* Represents a return value in the query results. Not the same as a result (column) in the JDBC ResultSet!
* <p/>
* This is merely a unifying contract; it defines no behavior.
* <p/>
* Return is distinctly different from a {@link Fetch}.
*
* @see ScalarReturn
* @see EntityReturn
* @see CollectionReturn
*
* @author Steve Ebersole
*/
public interface Return {
}

View File

@ -0,0 +1,138 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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;
/**
* @author Steve Ebersole
*/
public interface ReturnVisitationStrategy {
/**
* Notification we are preparing to start visitation.
*/
public void start();
/**
* Notification we are finished visitation.
*/
public void finish();
/**
* Notification that a new root return branch is being started. Will be followed by calls to one of the following
* based on the type of return:<ul>
* <li>{@link #handleScalarReturn}</li>
* <li>{@link #handleEntityReturn}</li>
* <li>{@link #handleCollectionReturn}</li>
* </ul>
*
* @param rootReturn The root return at the root of the branch.
*/
public void startingRootReturn(Return rootReturn);
/**
* Notification that we are finishing up processing a root return branch
*
* @param rootReturn The RootReturn we are finishing up processing.
*/
public void finishingRootReturn(Return rootReturn);
/**
* Notification that a scalar return is being processed. Will be surrounded by calls to {@link #startingRootReturn}
* and {@link #finishingRootReturn}
*
* @param scalarReturn The scalar return
*/
public void handleScalarReturn(ScalarReturn scalarReturn);
/**
* Notification that a root entity return is being processed. Will be surrounded by calls to
* {@link #startingRootReturn} and {@link #finishingRootReturn}
*
* @param rootEntityReturn The root entity return
*/
public void handleEntityReturn(EntityReturn rootEntityReturn);
/**
* Notification that a root collection return is being processed. Will be surrounded by calls to
* {@link #startingRootReturn} and {@link #finishingRootReturn}
*
* @param rootCollectionReturn The root collection return
*/
public void handleCollectionReturn(CollectionReturn rootCollectionReturn);
/**
* Notification that we are about to start processing the fetches for the given fetch owner.
*
* @param fetchOwner The fetch owner.
*/
public void startingFetches(FetchOwner fetchOwner);
/**
* Notification that we are finishing up processing the fetches for the given fetch owner.
*
* @param fetchOwner The fetch owner.
*/
public void finishingFetches(FetchOwner fetchOwner);
/**
* Notification we are starting the processing of an entity fetch
*
* @param entityFetch The entity fetch
*/
public void startingEntityFetch(EntityFetch entityFetch);
/**
* Notification that we are finishing up the processing of an entity fetch
*
* @param entityFetch The entity fetch
*/
public void finishingEntityFetch(EntityFetch entityFetch);
/**
* Notification we are starting the processing of a collection fetch
*
* @param collectionFetch The collection fetch
*/
public void startingCollectionFetch(CollectionFetch collectionFetch);
/**
* Notification that we are finishing up the processing of a collection fetch
*
* @param collectionFetch The collection fetch
*/
public void finishingCollectionFetch(CollectionFetch collectionFetch);
/**
* Notification we are starting the processing of a component fetch
*
* @param fetch The composite fetch
*/
public void startingCompositeFetch(CompositeFetch fetch);
/**
* Notification that we are finishing up the processing of a composite fetch
*
* @param fetch The composite fetch
*/
public void finishingCompositeFetch(CompositeFetch fetch);
}

View File

@ -0,0 +1,116 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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;
/**
* Visitor for processing {@link Return} graphs
*
* @author Steve Ebersole
*/
public class ReturnVisitor {
public static void visit(Return[] rootReturns, ReturnVisitationStrategy strategy) {
new ReturnVisitor( strategy ).visitReturns( rootReturns );
}
private final ReturnVisitationStrategy strategy;
public ReturnVisitor(ReturnVisitationStrategy strategy) {
this.strategy = strategy;
}
private void visitReturns(Return[] rootReturns) {
strategy.start();
for ( Return rootReturn : rootReturns ) {
visitRootReturn( rootReturn );
}
strategy.finish();
}
private void visitRootReturn(Return rootReturn) {
strategy.startingRootReturn( rootReturn );
if ( org.hibernate.loader.plan.spi.ScalarReturn.class.isInstance( rootReturn ) ) {
strategy.handleScalarReturn( (ScalarReturn) rootReturn );
}
else {
visitNonScalarRootReturn( rootReturn );
}
strategy.finishingRootReturn( rootReturn );
}
private void visitNonScalarRootReturn(Return rootReturn) {
if ( EntityReturn.class.isInstance( rootReturn ) ) {
strategy.handleEntityReturn( (EntityReturn) rootReturn );
visitFetches( (EntityReturn) rootReturn );
}
else if ( CollectionReturn.class.isInstance( rootReturn ) ) {
strategy.handleCollectionReturn( (CollectionReturn) rootReturn );
visitFetches( (CollectionReturn) rootReturn );
}
else {
throw new IllegalStateException(
"Unexpected return type encountered; expecting a non-scalar root return, but found " +
rootReturn.getClass().getName()
);
}
}
private void visitFetches(FetchOwner fetchOwner) {
strategy.startingFetches( fetchOwner );
for ( Fetch fetch : fetchOwner.getFetches() ) {
visitFetch( fetch );
}
strategy.finishingFetches( fetchOwner );
}
private void visitFetch(Fetch fetch) {
if ( EntityFetch.class.isInstance( fetch ) ) {
strategy.startingEntityFetch( (EntityFetch) fetch );
visitFetches( fetch );
strategy.finishingEntityFetch( (EntityFetch) fetch );
}
else if ( CollectionFetch.class.isInstance( fetch ) ) {
strategy.startingCollectionFetch( (CollectionFetch) fetch );
visitFetches( fetch );
strategy.finishingCollectionFetch( (CollectionFetch) fetch );
}
else if ( CompositeFetch.class.isInstance( fetch ) ) {
strategy.startingCompositeFetch( (CompositeFetch) fetch );
visitFetches( fetch );
strategy.finishingCompositeFetch( (CompositeFetch) fetch );
}
else {
throw new IllegalStateException(
"Unexpected return type encountered; expecting a fetch return, but found " +
fetch.getClass().getName()
);
}
}
}

View File

@ -0,0 +1,52 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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.spi.SessionFactoryImplementor;
import org.hibernate.type.Type;
/**
* Represent a simple scalar return within a query result. Generally this would be values of basic (String, Integer,
* etc) or composite types.
*
* @author Steve Ebersole
*/
public class ScalarReturn extends AbstractPlanNode implements Return {
private final Type type;
private final String columnAlias;
public ScalarReturn(SessionFactoryImplementor factory, Type type, String columnAlias) {
super( factory );
this.type = type;
this.columnAlias = columnAlias;
}
public Type getType() {
return type;
}
public String getColumnAlias() {
return columnAlias;
}
}

View File

@ -79,6 +79,11 @@ import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
import org.hibernate.persister.walking.spi.CompositeDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.Alias;
import org.hibernate.sql.SelectFragment;
@ -90,6 +95,7 @@ import org.hibernate.sql.ordering.antlr.FormulaReference;
import org.hibernate.sql.ordering.antlr.OrderByAliasResolver;
import org.hibernate.sql.ordering.antlr.OrderByTranslation;
import org.hibernate.sql.ordering.antlr.SqlValueReference;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
@ -1934,4 +1940,79 @@ public abstract class AbstractCollectionPersister
public abstract FilterAliasGenerator getFilterAliasGenerator(final String rootAlias);
// ColectionDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public CollectionPersister getCollectionPersister() {
return this;
}
@Override
public CollectionIndexDefinition getIndexDefinition() {
if ( ! hasIndex() ) {
return null;
}
return new CollectionIndexDefinition() {
@Override
public CollectionDefinition getCollectionDefinition() {
return AbstractCollectionPersister.this;
}
@Override
public Type getType() {
return getIndexType();
}
@Override
public EntityDefinition toEntityDefinition() {
if ( getType().isComponentType() ) {
throw new IllegalStateException( "Cannot treat composite collection index type as entity" );
}
return (EntityPersister) ( (AssociationType) getIndexType() ).getAssociatedJoinable( getFactory() );
}
@Override
public CompositeDefinition toCompositeDefinition() {
if ( ! getType().isComponentType() ) {
throw new IllegalStateException( "Cannot treat entity collection index type as composite" );
}
// todo : implement
throw new NotYetImplementedException();
}
};
}
@Override
public CollectionElementDefinition getElementDefinition() {
return new CollectionElementDefinition() {
@Override
public CollectionDefinition getCollectionDefinition() {
return AbstractCollectionPersister.this;
}
@Override
public Type getType() {
return getElementType();
}
@Override
public EntityDefinition toEntityDefinition() {
if ( getType().isComponentType() ) {
throw new IllegalStateException( "Cannot treat composite collection element type as entity" );
}
return getElementPersister();
}
@Override
public CompositeDefinition toCompositeDefinition() {
if ( ! getType().isComponentType() ) {
throw new IllegalStateException( "Cannot treat entity collection element type as composite" );
}
// todo : implement
throw new NotYetImplementedException();
}
};
}
}

View File

@ -38,6 +38,7 @@ import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.type.CollectionType;
import org.hibernate.type.Type;
@ -60,7 +61,7 @@ import org.hibernate.type.Type;
* @see org.hibernate.collection.spi.PersistentCollection
* @author Gavin King
*/
public interface CollectionPersister {
public interface CollectionPersister extends CollectionDefinition {
/**
* Initialize the given collection with the given key
*/

View File

@ -59,6 +59,7 @@ import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl;
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
import org.hibernate.cache.spi.entry.StructuredCacheEntry;
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.dialect.lock.LockingStrategy;
import org.hibernate.engine.OptimisticLockStyle;
import org.hibernate.engine.internal.StatefulPersistenceContext;
@ -91,7 +92,6 @@ import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.Expectations;
import org.hibernate.jdbc.TooManyRowsAffectedException;
import org.hibernate.loader.entity.BatchingEntityLoader;
import org.hibernate.loader.entity.BatchingEntityLoaderBuilder;
import org.hibernate.loader.entity.CascadeEntityLoader;
import org.hibernate.loader.entity.EntityLoader;
@ -109,6 +109,7 @@ import org.hibernate.metamodel.binding.SimpleValueBinding;
import org.hibernate.metamodel.binding.SingularAttributeBinding;
import org.hibernate.metamodel.relational.DerivedValue;
import org.hibernate.metamodel.relational.Value;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.property.BackrefPropertyAccessor;
import org.hibernate.sql.Alias;
@ -504,7 +505,7 @@ public abstract class AbstractEntityPersister
this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy;
isLazyPropertiesCacheable = persistentClass.isLazyPropertiesCacheable();
this.entityMetamodel = new EntityMetamodel( persistentClass, factory );
this.entityMetamodel = new EntityMetamodel( persistentClass, this, factory );
this.entityTuplizer = this.entityMetamodel.getTuplizer();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -834,7 +835,7 @@ public abstract class AbstractEntityPersister
entityBinding.getHierarchyDetails().getCaching() == null ?
false :
entityBinding.getHierarchyDetails().getCaching().isCacheLazyProperties();
this.entityMetamodel = new EntityMetamodel( entityBinding, factory );
this.entityMetamodel = new EntityMetamodel( entityBinding, this, factory );
this.entityTuplizer = this.entityMetamodel.getTuplizer();
int batch = entityBinding.getBatchSize();
if ( batch == -1 ) {
@ -3816,10 +3817,11 @@ public abstract class AbstractEntityPersister
}
public void postInstantiate() throws MappingException {
generateEntityDefinition();
createLoaders();
createUniqueKeyLoaders();
createQueryLoader();
}
//needed by subclasses to override the createLoader strategy
@ -5070,4 +5072,110 @@ public abstract class AbstractEntityPersister
throw new HibernateException( "Illegal attempt to build cache entry for non-cached entity" );
}
}
// EntityDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private Iterable<AttributeDefinition> embeddedCompositeIdentifierAttributes;
private Iterable<AttributeDefinition> attributeDefinitions;
protected void generateEntityDefinition() {
collectEmbeddedCompositeIdentifierAttributeDefinitions();
collectAttributeDefinitions();
}
@Override
public EntityPersister getEntityPersister() {
return this;
}
@Override
public Iterable<AttributeDefinition> getEmbeddedCompositeIdentifierAttributes() {
return embeddedCompositeIdentifierAttributes;
}
@Override
public Iterable<AttributeDefinition> getAttributes() {
return attributeDefinitions;
}
private synchronized void collectEmbeddedCompositeIdentifierAttributeDefinitions() {
final Type idType = getIdentifierType();
if ( !idType.isComponentType() ) {
return;
}
final CompositeType cidType = (CompositeType) idType;
if ( !cidType.isEmbedded() ) {
return;
}
// we have an embedded composite identifier. Most likely we need to process the composite
// properties separately, although there is an edge case where the identifier is really
// a simple identifier (single value) wrapped in a JPA @IdClass or even in the case of a
// a simple identifier (single value) wrapped in a Hibernate composite type.
//
// We really do not have a built-in method to determine that. However, generally the
// persister would report that there is single, physical identifier property which is
// explicitly at odds with the notion of "embedded composite". So we use that for now
if ( getEntityMetamodel().getIdentifierProperty().isEmbedded() ) {
this.embeddedCompositeIdentifierAttributes = new Iterable<AttributeDefinition>() {
@Override
public Iterator<AttributeDefinition> iterator() {
return new Iterator<AttributeDefinition>() {
private final int numberOfAttributes = countSubclassProperties();
private int currentAttributeNumber = 0;
@Override
public boolean hasNext() {
return currentAttributeNumber < numberOfAttributes;
}
@Override
public AttributeDefinition next() {
// todo : implement
throw new NotYetImplementedException();
}
@Override
public void remove() {
throw new UnsupportedOperationException( "Remove operation not supported here" );
}
};
}
};
}
}
private void collectAttributeDefinitions() {
// todo : leverage the attribute definitions housed on EntityMetamodel
// for that to work, we'd have to be able to walk our super entity persister(s)
attributeDefinitions = new Iterable<AttributeDefinition>() {
@Override
public Iterator<AttributeDefinition> iterator() {
return new Iterator<AttributeDefinition>() {
// private final int numberOfAttributes = countSubclassProperties();
private final int numberOfAttributes = entityMetamodel.getPropertySpan();
private int currentAttributeNumber = 0;
@Override
public boolean hasNext() {
return currentAttributeNumber < numberOfAttributes;
}
@Override
public AttributeDefinition next() {
final int attributeNumber = currentAttributeNumber;
currentAttributeNumber++;
return entityMetamodel.getProperties()[ attributeNumber ];
}
@Override
public void remove() {
throw new UnsupportedOperationException( "Remove operation not supported here" );
}
};
}
};
}
}

View File

@ -44,22 +44,25 @@ import org.hibernate.engine.spi.ValueInclusion;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.internal.FilterAliasGenerator;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.type.Type;
import org.hibernate.type.VersionType;
/**
* Implementors define mapping and persistence logic for a particular
* strategy of entity mapping. An instance of entity persisters corresponds
* to a given mapped entity.
* Contract describing mapping information and persistence logic for a particular strategy of entity mapping. A given
* persister instance corresponds to a given mapped entity class.
* <p/>
* Implementors must be threadsafe (preferrably immutable) and must provide a constructor
* matching the signature of: {@link org.hibernate.mapping.PersistentClass}, {@link org.hibernate.engine.spi.SessionFactoryImplementor}
* Implementations must be thread-safe (preferably immutable).
*
* @author Gavin King
* @author Steve Ebersole
*
* @see org.hibernate.persister.spi.PersisterFactory
* @see org.hibernate.persister.spi.PersisterClassResolver
*/
public interface EntityPersister extends OptimisticCacheSource {
public interface EntityPersister extends OptimisticCacheSource, EntityDefinition {
/**
* The property name of the "special" identifier property in HQL

View File

@ -0,0 +1,160 @@
/*
* jDocBook, processing of DocBook sources
*
* 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 java.util.Iterator;
import org.hibernate.FetchMode;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.profile.Fetch;
import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.collection.AbstractCollectionPersister;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.AssociationType;
/**
* @author Steve Ebersole
*/
public class Helper {
/**
* Determine the fetch-style (if one) explicitly set for this association via fetch profiles.
* <p/>
* Note that currently fetch profiles only allow specifying join fetching, so this method currently
* returns either (a) FetchStyle.JOIN or (b) null
*
* @param loadQueryInfluencers
* @param persister
* @param path
* @param propertyNumber
*
* @return
*/
public static FetchStyle determineFetchStyleByProfile(
LoadQueryInfluencers loadQueryInfluencers,
EntityPersister persister,
PropertyPath path,
int propertyNumber) {
if ( !loadQueryInfluencers.hasEnabledFetchProfiles() ) {
// perf optimization
return null;
}
// ugh, this stuff has to be made easier...
final String fullPath = path.getFullPath();
final String rootPropertyName = ( (OuterJoinLoadable) persister ).getSubclassPropertyName( propertyNumber );
int pos = fullPath.lastIndexOf( rootPropertyName );
final String relativePropertyPath = pos >= 0
? fullPath.substring( pos )
: rootPropertyName;
final String fetchRole = persister.getEntityName() + "." + relativePropertyPath;
Iterator profiles = loadQueryInfluencers.getEnabledFetchProfileNames().iterator();
while ( profiles.hasNext() ) {
final String profileName = ( String ) profiles.next();
final FetchProfile profile = loadQueryInfluencers.getSessionFactory().getFetchProfile( profileName );
final Fetch fetch = profile.getFetchByRole( fetchRole );
if ( fetch != null && Fetch.Style.JOIN == fetch.getStyle() ) {
return FetchStyle.JOIN;
}
}
return null;
}
/**
*
* @param mappingFetchMode The mapping defined fetch mode
* @param type The association type
* @param sessionFactory The session factory
*
* @return
*/
public static FetchStyle determineFetchStyleByMetadata(
FetchMode mappingFetchMode,
AssociationType type,
SessionFactoryImplementor sessionFactory) {
if ( !type.isEntityType() && !type.isCollectionType() ) {
return FetchStyle.SELECT;
}
if ( mappingFetchMode == FetchMode.JOIN ) {
return FetchStyle.JOIN;
}
if ( type.isEntityType() ) {
EntityPersister persister = (EntityPersister) type.getAssociatedJoinable( sessionFactory );
if ( persister.isBatchLoadable() ) {
return FetchStyle.BATCH;
}
}
else {
CollectionPersister persister = (CollectionPersister) type.getAssociatedJoinable( sessionFactory );
if ( persister instanceof AbstractCollectionPersister
&& ( (AbstractCollectionPersister) persister ).isSubselectLoadable() ) {
return FetchStyle.SUBSELECT;
}
else if ( persister.getBatchSize() > 0 ) {
return FetchStyle.BATCH;
}
}
return FetchStyle.SELECT;
}
public static FetchTiming determineFetchTiming(
FetchStyle style,
AssociationType type,
SessionFactoryImplementor sessionFactory) {
switch ( style ) {
case JOIN: {
return FetchTiming.IMMEDIATE;
}
case BATCH:
case SUBSELECT: {
return FetchTiming.DELAYED;
}
default: {
// SELECT case, can be either
return isSubsequentSelectDelayed( type, sessionFactory )
? FetchTiming.DELAYED
: FetchTiming.IMMEDIATE;
}
}
}
private static boolean isSubsequentSelectDelayed(AssociationType type, SessionFactoryImplementor sessionFactory) {
if ( type.isEntityType() ) {
return ( (EntityPersister) type.getAssociatedJoinable( sessionFactory ) ).hasProxy();
}
else {
final CollectionPersister cp = ( (CollectionPersister) type.getAssociatedJoinable( sessionFactory ) );
return cp.isLazy() || cp.isExtraLazy();
}
}
}

View File

@ -0,0 +1,46 @@
/*
* 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;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.loader.PropertyPath;
/**
* @author Steve Ebersole
*/
public interface AssociationAttributeDefinition extends AttributeDefinition {
public AssociationKey getAssociationKey();
public boolean isCollection();
public EntityDefinition toEntityDefinition();
public CollectionDefinition toCollectionDefinition();
public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath);
public CascadeStyle determineCascadeStyle();
}

View File

@ -0,0 +1,53 @@
/*
* 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;
import java.util.Arrays;
/**
* Used to uniquely identify a foreign key, so that we don't join it more than once creating circularities.
* <p/>
* bit of a misnomer to call this an association attribute. But this follows the legacy use of AssociationKey
* from old JoinWalkers to denote circular join detection
*/
public class AssociationKey {
private final String table;
private final String[] columns;
public AssociationKey(String table, String[] columns) {
this.table = table;
this.columns = columns;
}
@Override
public boolean equals(Object other) {
AssociationKey that = (AssociationKey) other;
return that.table.equals(table) && Arrays.equals( columns, that.columns );
}
@Override
public int hashCode() {
return table.hashCode(); //TODO: inefficient
}
}

View File

@ -0,0 +1,51 @@
/*
* 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 Steve Ebersole
*/
public interface AssociationVisitationStrategy {
/**
* Notification we are preparing to start visitation.
*/
public void start();
/**
* Notification we are finished visitation.
*/
public void finish();
public void startingEntity(EntityDefinition entityDefinition);
public void finishingEntity(EntityDefinition entityDefinition);
public void startingCollection(CollectionDefinition collectionDefinition);
public void finishingCollection(CollectionDefinition collectionDefinition);
public void startingComposite(CompositeDefinition compositeDefinition);
public void finishingComposite(CompositeDefinition compositeDefinition);
public boolean startingAttribute(AttributeDefinition attributeDefinition);
public void finishingAttribute(AttributeDefinition attributeDefinition);
}

View File

@ -0,0 +1,35 @@
/*
* 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;
import org.hibernate.type.Type;
/**
* @author Steve Ebersole
*/
public interface AttributeDefinition {
public String getName();
public Type getType();
public AttributeSource getSource();
}

View File

@ -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 Steve Ebersole
*/
public interface AttributeSource {
public Iterable<AttributeDefinition> getAttributes();
}

View File

@ -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.persister.walking.spi;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.CollectionType;
/**
* @author Steve Ebersole
*/
public interface CollectionDefinition {
public CollectionPersister getCollectionPersister();
public CollectionType getCollectionType();
public CollectionIndexDefinition getIndexDefinition();
public CollectionElementDefinition getElementDefinition();
}

View File

@ -0,0 +1,39 @@
/*
* jDocBook, processing of DocBook sources
*
* 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;
import org.hibernate.type.Type;
/**
* @author Steve Ebersole
*/
public interface CollectionElementDefinition {
public CollectionDefinition getCollectionDefinition();
public Type getType();
public EntityDefinition toEntityDefinition();
public CompositeDefinition toCompositeDefinition();
}

View File

@ -0,0 +1,39 @@
/*
* jDocBook, processing of DocBook sources
*
* 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;
import org.hibernate.type.Type;
/**
* @author Steve Ebersole
*/
public interface CollectionIndexDefinition {
public CollectionDefinition getCollectionDefinition();
public Type getType();
public EntityDefinition toEntityDefinition();
public CompositeDefinition toCompositeDefinition();
}

View File

@ -0,0 +1,30 @@
/*
* 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 Steve Ebersole
*/
public interface CompositeDefinition extends AttributeDefinition, AttributeSource {
}

View File

@ -0,0 +1,36 @@
/*
* 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;
import org.hibernate.persister.entity.EntityPersister;
/**
* Defines the contract for walking the attributes defined by an entity
*
* @author Steve Ebersole
*/
public interface EntityDefinition extends AttributeSource {
public EntityPersister getEntityPersister();
public Iterable<AttributeDefinition> getEmbeddedCompositeIdentifierAttributes();
}

View File

@ -0,0 +1,208 @@
/*
* 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;
import java.util.HashSet;
import java.util.Set;
import org.jboss.logging.Logger;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.Type;
/**
* Provides model graph visitation based on the defined metadata (as opposed to based on the incoming graph
* as we see in cascade processing). In layman terms, we are walking the graph of the users model as defined by
* mapped associations.
* <p/>
* Re-implementation of the legacy {@link org.hibernate.loader.JoinWalker} contract to leverage load plans.
*
* @author Steve Ebersole
*/
public class MetadataDrivenModelGraphVisitor {
private static final Logger log = Logger.getLogger( MetadataDrivenModelGraphVisitor.class );
public static void visitEntity(AssociationVisitationStrategy strategy, EntityPersister persister) {
strategy.start();
try {
new MetadataDrivenModelGraphVisitor( strategy, persister.getFactory() )
.visitEntityDefinition( persister );
}
finally {
strategy.finish();
}
}
public static void visitCollection(AssociationVisitationStrategy strategy, CollectionPersister persister) {
strategy.start();
try {
new MetadataDrivenModelGraphVisitor( strategy, persister.getFactory() )
.visitCollectionDefinition( persister );
}
finally {
strategy.finish();
}
}
private final AssociationVisitationStrategy strategy;
private final SessionFactoryImplementor factory;
// todo : add a getDepth() method to PropertyPath
private PropertyPath currentPropertyPath = new PropertyPath();
public MetadataDrivenModelGraphVisitor(AssociationVisitationStrategy strategy, SessionFactoryImplementor factory) {
this.strategy = strategy;
this.factory = factory;
}
private void visitEntityDefinition(EntityDefinition entityDefinition) {
strategy.startingEntity( entityDefinition );
try {
visitAttributes( entityDefinition );
optionallyVisitEmbeddedCompositeIdentifier( entityDefinition );
}
finally {
strategy.finishingEntity( entityDefinition );
}
}
private void optionallyVisitEmbeddedCompositeIdentifier(EntityDefinition entityDefinition) {
// if the entity has a composite identifier, see if we need to handle its sub-properties separately
final Iterable<AttributeDefinition> embeddedCompositeIdentifierAttributes =
entityDefinition.getEmbeddedCompositeIdentifierAttributes();
if ( embeddedCompositeIdentifierAttributes == null ) {
return;
}
for ( AttributeDefinition attributeDefinition : embeddedCompositeIdentifierAttributes ) {
visitAttributeDefinition( attributeDefinition );
}
}
private void visitAttributes(AttributeSource attributeSource) {
for ( AttributeDefinition attributeDefinition : attributeSource.getAttributes() ) {
visitAttributeDefinition( attributeDefinition );
}
}
private void visitAttributeDefinition(AttributeDefinition attributeDefinition) {
final PropertyPath subPath = currentPropertyPath.append( attributeDefinition.getName() );
log.debug( "Visiting attribute path : " + subPath.getFullPath() );
final boolean continueWalk = strategy.startingAttribute( attributeDefinition );
if ( continueWalk ) {
final PropertyPath old = currentPropertyPath;
currentPropertyPath = subPath;
try {
if ( attributeDefinition.getType().isAssociationType() ) {
visitAssociation( (AssociationAttributeDefinition) attributeDefinition );
}
else if ( attributeDefinition.getType().isComponentType() ) {
visitCompositeDefinition( (CompositeDefinition) attributeDefinition );
}
}
finally {
currentPropertyPath = old;
}
}
strategy.finishingAttribute( attributeDefinition );
}
private void visitAssociation(AssociationAttributeDefinition attribute) {
// todo : do "too deep" checks; but see note about adding depth to PropertyPath
if ( isDuplicateAssociation( attribute.getAssociationKey() ) ) {
log.debug( "Property path deemed to be circular : " + currentPropertyPath.getFullPath() );
return;
}
if ( attribute.isCollection() ) {
visitCollectionDefinition( attribute.toCollectionDefinition() );
}
else {
visitEntityDefinition( attribute.toEntityDefinition() );
}
}
private void visitCompositeDefinition(CompositeDefinition compositeDefinition) {
strategy.startingComposite( compositeDefinition );
try {
visitAttributes( compositeDefinition );
}
finally {
strategy.finishingComposite( compositeDefinition );
}
}
private void visitCollectionDefinition(CollectionDefinition collectionDefinition) {
strategy.startingCollection( collectionDefinition );
try {
visitCollectionIndex( collectionDefinition.getIndexDefinition() );
final CollectionElementDefinition elementDefinition = collectionDefinition.getElementDefinition();
if ( elementDefinition.getType().isComponentType() ) {
visitCompositeDefinition( elementDefinition.toCompositeDefinition() );
}
else {
visitEntityDefinition( elementDefinition.toEntityDefinition() );
}
}
finally {
strategy.finishingCollection( collectionDefinition );
}
}
private void visitCollectionIndex(CollectionIndexDefinition collectionIndexDefinition) {
if ( collectionIndexDefinition == null ) {
return;
}
log.debug( "Visiting collection index : " + currentPropertyPath.getFullPath() );
currentPropertyPath = currentPropertyPath.append( "<key>" );
try {
final Type collectionIndexType = collectionIndexDefinition.getType();
if ( collectionIndexType.isComponentType() ) {
visitCompositeDefinition( collectionIndexDefinition.toCompositeDefinition() );
}
else if ( collectionIndexType.isAssociationType() ) {
visitEntityDefinition( collectionIndexDefinition.toEntityDefinition() );
}
}
finally {
currentPropertyPath = currentPropertyPath.getParent();
}
}
private final Set<AssociationKey> visitedAssociationKeys = new HashSet<AssociationKey>();
protected boolean isDuplicateAssociation(AssociationKey associationKey) {
return !visitedAssociationKeys.add( associationKey );
}
}

View File

@ -0,0 +1,6 @@
package org.hibernate.persister.walking.spi;
/**
* Package for "walking" associations through metadata definition. Ultimately want {@link org.hibernate.persister.walking.spi.AttributeDefinition} and
* {@link AttributeSource} etc to become part of the persister model.
*/

View File

@ -0,0 +1,55 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.tuple;
import org.hibernate.type.Type;
/**
* @author Steve Ebersole
*/
public abstract class AbstractAttribute implements Attribute, Property {
private final String attributeName;
private final Type attributeType;
protected AbstractAttribute(String attributeName, Type attributeType) {
this.attributeName = attributeName;
this.attributeType = attributeType;
}
@Override
@Deprecated
public String getNode() {
return null;
}
@Override
public String getName() {
return attributeName;
}
@Override
public Type getType() {
return attributeType;
}
}

View File

@ -0,0 +1,133 @@
/*
* 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.tuple;
import org.hibernate.FetchMode;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.walking.spi.AttributeSource;
import org.hibernate.type.Type;
/**
* @author Steve Ebersole
*/
public abstract class AbstractNonIdentifierAttribute extends AbstractAttribute implements NonIdentifierAttribute {
private final AttributeSource source;
private final SessionFactoryImplementor sessionFactory;
private final int attributeNumber;
private final BaselineAttributeInformation attributeInformation;
protected AbstractNonIdentifierAttribute(
AttributeSource source,
SessionFactoryImplementor sessionFactory,
int attributeNumber,
String attributeName,
Type attributeType,
BaselineAttributeInformation attributeInformation) {
super( attributeName, attributeType );
this.source = source;
this.sessionFactory = sessionFactory;
this.attributeNumber = attributeNumber;
this.attributeInformation = attributeInformation;
}
@Override
public AttributeSource getSource() {
return source();
}
protected AttributeSource source() {
return source;
}
protected SessionFactoryImplementor sessionFactory() {
return sessionFactory;
}
protected int attributeNumber() {
return attributeNumber;
}
@Override
public boolean isLazy() {
return attributeInformation.isLazy();
}
@Override
public boolean isInsertable() {
return attributeInformation.isInsertable();
}
@Override
public boolean isUpdateable() {
return attributeInformation.isUpdateable();
}
@Override
public boolean isInsertGenerated() {
return attributeInformation.isInsertGenerated();
}
@Override
public boolean isUpdateGenerated() {
return attributeInformation.isUpdateGenerated();
}
@Override
public boolean isNullable() {
return attributeInformation.isNullable();
}
@Override
public boolean isDirtyCheckable() {
return attributeInformation.isDirtyCheckable();
}
@Override
public boolean isDirtyCheckable(boolean hasUninitializedProperties) {
return isDirtyCheckable() && ( !hasUninitializedProperties || !isLazy() );
}
@Override
public boolean isVersionable() {
return attributeInformation.isVersionable();
}
@Override
public CascadeStyle getCascadeStyle() {
return attributeInformation.getCascadeStyle();
}
@Override
public FetchMode getFetchMode() {
return attributeInformation.getFetchMode();
}
@Override
public String toString() {
return "Attribute[non-identifier]( " + getName() + ")";
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.tuple;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.type.Type;
/**
* Contract for attributes
*
* @author Steve Ebersole
*/
public interface Attribute {
public String getName();
public Type getType();
}

View File

@ -0,0 +1,166 @@
package org.hibernate.tuple;
import org.hibernate.FetchMode;
import org.hibernate.engine.spi.CascadeStyle;
/**
* @author Steve Ebersole
*/
public class BaselineAttributeInformation {
private final boolean lazy;
private final boolean insertable;
private final boolean updateable;
private final boolean insertGenerated;
private final boolean updateGenerated;
private final boolean nullable;
private final boolean dirtyCheckable;
private final boolean versionable;
private final CascadeStyle cascadeStyle;
private final FetchMode fetchMode;
private boolean checkable;
public BaselineAttributeInformation(
boolean lazy,
boolean insertable,
boolean updateable,
boolean insertGenerated,
boolean updateGenerated,
boolean nullable,
boolean dirtyCheckable,
boolean versionable,
CascadeStyle cascadeStyle,
FetchMode fetchMode) {
this.lazy = lazy;
this.insertable = insertable;
this.updateable = updateable;
this.insertGenerated = insertGenerated;
this.updateGenerated = updateGenerated;
this.nullable = nullable;
this.dirtyCheckable = dirtyCheckable;
this.versionable = versionable;
this.cascadeStyle = cascadeStyle;
this.fetchMode = fetchMode;
}
public boolean isLazy() {
return lazy;
}
public boolean isInsertable() {
return insertable;
}
public boolean isUpdateable() {
return updateable;
}
public boolean isInsertGenerated() {
return insertGenerated;
}
public boolean isUpdateGenerated() {
return updateGenerated;
}
public boolean isNullable() {
return nullable;
}
public boolean isDirtyCheckable() {
return dirtyCheckable;
}
public boolean isVersionable() {
return versionable;
}
public CascadeStyle getCascadeStyle() {
return cascadeStyle;
}
public FetchMode getFetchMode() {
return fetchMode;
}
public boolean isCheckable() {
return checkable;
}
public static class Builder {
private boolean lazy;
private boolean insertable;
private boolean updateable;
private boolean insertGenerated;
private boolean updateGenerated;
private boolean nullable;
private boolean dirtyCheckable;
private boolean versionable;
private CascadeStyle cascadeStyle;
private FetchMode fetchMode;
public Builder setLazy(boolean lazy) {
this.lazy = lazy;
return this;
}
public Builder setInsertable(boolean insertable) {
this.insertable = insertable;
return this;
}
public Builder setUpdateable(boolean updateable) {
this.updateable = updateable;
return this;
}
public Builder setInsertGenerated(boolean insertGenerated) {
this.insertGenerated = insertGenerated;
return this;
}
public Builder setUpdateGenerated(boolean updateGenerated) {
this.updateGenerated = updateGenerated;
return this;
}
public Builder setNullable(boolean nullable) {
this.nullable = nullable;
return this;
}
public Builder setDirtyCheckable(boolean dirtyCheckable) {
this.dirtyCheckable = dirtyCheckable;
return this;
}
public Builder setVersionable(boolean versionable) {
this.versionable = versionable;
return this;
}
public Builder setCascadeStyle(CascadeStyle cascadeStyle) {
this.cascadeStyle = cascadeStyle;
return this;
}
public Builder setFetchMode(FetchMode fetchMode) {
this.fetchMode = fetchMode;
return this;
}
public BaselineAttributeInformation createInformation() {
return new BaselineAttributeInformation(
lazy,
insertable,
updateable,
insertGenerated,
updateGenerated,
nullable,
dirtyCheckable,
versionable,
cascadeStyle,
fetchMode
);
}
}
}

View File

@ -0,0 +1,21 @@
package org.hibernate.tuple;
import org.hibernate.engine.spi.IdentifierValue;
import org.hibernate.id.IdentifierGenerator;
/**
* @author Steve Ebersole
*/
public interface IdentifierAttribute extends Attribute, Property {
boolean isVirtual();
boolean isEmbedded();
IdentifierValue getUnsavedValue();
IdentifierGenerator getIdentifierGenerator();
boolean isIdentifierAssignedByInsert();
boolean hasIdentifierMapper();
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.tuple;
import org.hibernate.engine.spi.IdentifierValue;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PostInsertIdentifierGenerator;
@ -34,7 +34,7 @@ import org.hibernate.type.Type;
*
* @author Steve Ebersole
*/
public class IdentifierProperty extends Property {
public class IdentifierProperty extends AbstractAttribute implements IdentifierAttribute {
private boolean virtual;
private boolean embedded;
@ -63,7 +63,7 @@ public class IdentifierProperty extends Property {
boolean embedded,
IdentifierValue unsavedValue,
IdentifierGenerator identifierGenerator) {
super(name, node, type);
super( name, type );
this.virtual = false;
this.embedded = embedded;
this.hasIdentifierMapper = false;
@ -87,7 +87,7 @@ public class IdentifierProperty extends Property {
boolean hasIdentifierMapper,
IdentifierValue unsavedValue,
IdentifierGenerator identifierGenerator) {
super(null, null, type);
super( null, type );
this.virtual = true;
this.embedded = embedded;
this.hasIdentifierMapper = hasIdentifierMapper;
@ -96,27 +96,38 @@ public class IdentifierProperty extends Property {
this.identifierAssignedByInsert = identifierGenerator instanceof PostInsertIdentifierGenerator;
}
@Override
public boolean isVirtual() {
return virtual;
}
@Override
public boolean isEmbedded() {
return embedded;
}
@Override
public IdentifierValue getUnsavedValue() {
return unsavedValue;
}
@Override
public IdentifierGenerator getIdentifierGenerator() {
return identifierGenerator;
}
@Override
public boolean isIdentifierAssignedByInsert() {
return identifierAssignedByInsert;
}
@Override
public boolean hasIdentifierMapper() {
return hasIdentifierMapper;
}
@Override
public String toString() {
return "IdentifierAttribute(" + getName() + ")";
}
}

View File

@ -0,0 +1,55 @@
/*
* 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.tuple;
import org.hibernate.FetchMode;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.persister.walking.spi.AttributeDefinition;
/**
* @author Steve Ebersole
*/
public interface NonIdentifierAttribute extends Attribute, AttributeDefinition {
public boolean isLazy();
public boolean isInsertable();
public boolean isUpdateable();
public boolean isInsertGenerated();
public boolean isUpdateGenerated();
public boolean isNullable();
public boolean isDirtyCheckable(boolean hasUninitializedProperties);
public boolean isDirtyCheckable();
public boolean isVersionable();
public CascadeStyle getCascadeStyle();
public FetchMode getFetchMode();
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 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 Middleware LLC.
* 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
@ -20,52 +20,16 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.tuple;
import java.io.Serializable;
import org.hibernate.type.Type;
/**
* Defines the basic contract of a Property within the runtime metamodel.
*
* @author Steve Ebersole
*/
public abstract class Property implements Serializable {
private String name;
private String node;
private Type type;
/**
* Constructor for Property instances.
*
* @param name The name by which the property can be referenced within
* its owner.
* @param node The node name to use for XML-based representation of this
* property.
* @param type The Hibernate Type of this property.
*/
protected Property(String name, String node, Type type) {
this.name = name;
this.node = node;
this.type = type;
}
public String getName() {
return name;
}
public String getNode() {
return node;
}
public Type getType() {
return type;
}
public String toString() {
return "Property(" + name + ':' + type.getName() + ')';
}
@Deprecated
public interface Property extends Attribute {
@Deprecated
public String getNode();
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 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 Middleware LLC.
* 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
@ -20,17 +20,20 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.tuple;
import java.lang.reflect.Constructor;
import org.hibernate.EntityMode;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.internal.UnsavedValueFactory;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadeStyles;
import org.hibernate.engine.spi.IdentifierValue;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.VersionValue;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.internal.util.ReflectHelper;
@ -45,10 +48,16 @@ import org.hibernate.metamodel.binding.BasicAttributeBinding;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.SimpleValueBinding;
import org.hibernate.metamodel.binding.SingularAttributeBinding;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.property.Getter;
import org.hibernate.property.PropertyAccessor;
import org.hibernate.property.PropertyAccessorFactory;
import org.hibernate.tuple.entity.EntityBasedAssociationAttribute;
import org.hibernate.tuple.entity.EntityBasedBasicAttribute;
import org.hibernate.tuple.entity.EntityBasedCompositeAttribute;
import org.hibernate.tuple.entity.VersionProperty;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
import org.hibernate.type.VersionType;
@ -59,16 +68,16 @@ import org.hibernate.type.VersionType;
* @author Steve Ebersole
*/
public class PropertyFactory {
/**
* Generates an IdentifierProperty representation of the for a given entity mapping.
* Generates the attribute representation of the identifier for a given entity mapping.
*
* @param mappedEntity The mapping definition of the entity.
* @param generator The identifier value generator to use for this identifier.
* @return The appropriate IdentifierProperty definition.
*/
public static IdentifierProperty buildIdentifierProperty(PersistentClass mappedEntity, IdentifierGenerator generator) {
public static IdentifierProperty buildIdentifierAttribute(
PersistentClass mappedEntity,
IdentifierGenerator generator) {
String mappedUnsavedValue = mappedEntity.getIdentifier().getNullValue();
Type type = mappedEntity.getIdentifier().getType();
Property property = mappedEntity.getIdentifierProperty();
@ -109,7 +118,9 @@ public class PropertyFactory {
* @param generator The identifier value generator to use for this identifier.
* @return The appropriate IdentifierProperty definition.
*/
public static IdentifierProperty buildIdentifierProperty(EntityBinding mappedEntity, IdentifierGenerator generator) {
public static IdentifierProperty buildIdentifierProperty(
EntityBinding mappedEntity,
IdentifierGenerator generator) {
final BasicAttributeBinding property = mappedEntity.getHierarchyDetails().getEntityIdentifier().getValueBinding();
@ -157,7 +168,12 @@ public class PropertyFactory {
* @param lazyAvailable Is property lazy loading currently available.
* @return The appropriate VersionProperty definition.
*/
public static VersionProperty buildVersionProperty(Property property, boolean lazyAvailable) {
public static VersionProperty buildVersionProperty(
EntityPersister persister,
SessionFactoryImplementor sessionFactory,
int attributeNumber,
Property property,
boolean lazyAvailable) {
String mappedUnsavedValue = ( (KeyValue) property.getValue() ).getNullValue();
VersionValue unsavedValue = UnsavedValueFactory.getUnsavedVersionValue(
@ -165,23 +181,27 @@ public class PropertyFactory {
getGetter( property ),
(VersionType) property.getType(),
getConstructor( property.getPersistentClass() )
);
);
boolean lazy = lazyAvailable && property.isLazy();
return new VersionProperty(
persister,
sessionFactory,
attributeNumber,
property.getName(),
property.getNodeName(),
property.getValue().getType(),
lazy,
property.isInsertable(),
property.isUpdateable(),
property.getGeneration() == PropertyGeneration.INSERT || property.getGeneration() == PropertyGeneration.ALWAYS,
property.getGeneration() == PropertyGeneration.ALWAYS,
property.isOptional(),
property.isUpdateable() && !lazy,
property.isOptimisticLocked(),
property.getCascadeStyle(),
new BaselineAttributeInformation.Builder()
.setLazy( lazy )
.setInsertable( property.isInsertable() )
.setUpdateable( property.isUpdateable() )
.setInsertGenerated( property.getGeneration() == PropertyGeneration.INSERT || property.getGeneration() == PropertyGeneration.ALWAYS )
.setUpdateGenerated( property.getGeneration() == PropertyGeneration.ALWAYS )
.setNullable( property.isOptional() )
.setDirtyCheckable( property.isUpdateable() && !lazy )
.setVersionable( property.isOptimisticLocked() )
.setCascadeStyle( property.getCascadeStyle() )
.createInformation(),
unsavedValue
);
}
@ -194,52 +214,38 @@ public class PropertyFactory {
* @param lazyAvailable Is property lazy loading currently available.
* @return The appropriate VersionProperty definition.
*/
public static VersionProperty buildVersionProperty(BasicAttributeBinding property, boolean lazyAvailable) {
String mappedUnsavedValue = ( (KeyValue) property.getValue() ).getNullValue();
public static VersionProperty buildVersionProperty(
EntityPersister persister,
BasicAttributeBinding property,
boolean lazyAvailable) {
throw new NotYetImplementedException();
}
VersionValue unsavedValue = UnsavedValueFactory.getUnsavedVersionValue(
mappedUnsavedValue,
getGetter( property ),
(VersionType) property.getHibernateTypeDescriptor().getResolvedTypeMapping(),
getConstructor( (EntityBinding) property.getContainer() )
);
boolean lazy = lazyAvailable && property.isLazy();
final CascadeStyle cascadeStyle = property.isAssociation()
? ( (AssociationAttributeBinding) property ).getCascadeStyle()
: CascadeStyles.NONE;
return new VersionProperty(
property.getAttribute().getName(),
null,
property.getHibernateTypeDescriptor().getResolvedTypeMapping(),
lazy,
true, // insertable
true, // updatable
property.getGeneration() == PropertyGeneration.INSERT
|| property.getGeneration() == PropertyGeneration.ALWAYS,
property.getGeneration() == PropertyGeneration.ALWAYS,
property.isNullable(),
!lazy,
property.isIncludedInOptimisticLocking(),
cascadeStyle,
unsavedValue
);
public static enum NonIdentifierAttributeNature {
BASIC,
COMPOSITE,
ANY,
ENTITY,
COLLECTION
}
/**
* Generate a "standard" (i.e., non-identifier and non-version) based on the given
* mapped property.
* Generate a non-identifier (and non-version) attribute based on the given mapped property from the given entity
*
* @param property The mapped property.
* @param lazyAvailable Is property lazy loading currently available.
* @return The appropriate StandardProperty definition.
* @return The appropriate NonIdentifierProperty definition.
*/
public static StandardProperty buildStandardProperty(Property property, boolean lazyAvailable) {
public static NonIdentifierAttribute buildEntityBasedAttribute(
EntityPersister persister,
SessionFactoryImplementor sessionFactory,
int attributeNumber,
Property property,
boolean lazyAvailable) {
final Type type = property.getValue().getType();
final NonIdentifierAttributeNature nature = decode( type );
// we need to dirty check collections, since they can cause an owner
// version number increment
@ -250,30 +256,147 @@ public class PropertyFactory {
boolean alwaysDirtyCheck = type.isAssociationType() &&
( (AssociationType) type ).isAlwaysDirtyChecked();
switch ( nature ) {
case BASIC: {
return new EntityBasedBasicAttribute(
persister,
sessionFactory,
attributeNumber,
property.getName(),
type,
new BaselineAttributeInformation.Builder()
.setLazy( lazyAvailable && property.isLazy() )
.setInsertable( property.isInsertable() )
.setUpdateable( property.isUpdateable() )
.setInsertGenerated(
property.getGeneration() == PropertyGeneration.INSERT
|| property.getGeneration() == PropertyGeneration.ALWAYS
)
.setUpdateGenerated( property.getGeneration() == PropertyGeneration.ALWAYS )
.setNullable( property.isOptional() )
.setDirtyCheckable( alwaysDirtyCheck || property.isUpdateable() )
.setVersionable( property.isOptimisticLocked() )
.setCascadeStyle( property.getCascadeStyle() )
.setFetchMode( property.getValue().getFetchMode() )
.createInformation()
);
}
case COMPOSITE: {
return new EntityBasedCompositeAttribute(
persister,
sessionFactory,
attributeNumber,
property.getName(),
(CompositeType) type,
new BaselineAttributeInformation.Builder()
.setLazy( lazyAvailable && property.isLazy() )
.setInsertable( property.isInsertable() )
.setUpdateable( property.isUpdateable() )
.setInsertGenerated(
property.getGeneration() == PropertyGeneration.INSERT
|| property.getGeneration() == PropertyGeneration.ALWAYS
)
.setUpdateGenerated( property.getGeneration() == PropertyGeneration.ALWAYS )
.setNullable( property.isOptional() )
.setDirtyCheckable( alwaysDirtyCheck || property.isUpdateable() )
.setVersionable( property.isOptimisticLocked() )
.setCascadeStyle( property.getCascadeStyle() )
.setFetchMode( property.getValue().getFetchMode() )
.createInformation()
);
}
case ENTITY:
case ANY:
case COLLECTION: {
return new EntityBasedAssociationAttribute(
persister,
sessionFactory,
attributeNumber,
property.getName(),
(AssociationType) type,
new BaselineAttributeInformation.Builder()
.setLazy( lazyAvailable && property.isLazy() )
.setInsertable( property.isInsertable() )
.setUpdateable( property.isUpdateable() )
.setInsertGenerated(
property.getGeneration() == PropertyGeneration.INSERT
|| property.getGeneration() == PropertyGeneration.ALWAYS
)
.setUpdateGenerated( property.getGeneration() == PropertyGeneration.ALWAYS )
.setNullable( property.isOptional() )
.setDirtyCheckable( alwaysDirtyCheck || property.isUpdateable() )
.setVersionable( property.isOptimisticLocked() )
.setCascadeStyle( property.getCascadeStyle() )
.setFetchMode( property.getValue().getFetchMode() )
.createInformation()
);
}
default: {
throw new HibernateException( "Internal error" );
}
}
}
private static NonIdentifierAttributeNature decode(Type type) {
if ( type.isAssociationType() ) {
AssociationType associationType = (AssociationType) type;
if ( type.isComponentType() ) {
// an any type is both an association and a composite...
return NonIdentifierAttributeNature.ANY;
}
return type.isCollectionType()
? NonIdentifierAttributeNature.COLLECTION
: NonIdentifierAttributeNature.ENTITY;
}
else {
if ( type.isComponentType() ) {
return NonIdentifierAttributeNature.COMPOSITE;
}
return NonIdentifierAttributeNature.BASIC;
}
}
@Deprecated
public static StandardProperty buildStandardProperty(Property property, boolean lazyAvailable) {
final Type type = property.getValue().getType();
// we need to dirty check collections, since they can cause an owner
// version number increment
// we need to dirty check many-to-ones with not-found="ignore" in order
// to update the cache (not the database), since in this case a null
// entity reference can lose information
boolean alwaysDirtyCheck = type.isAssociationType() &&
( (AssociationType) type ).isAlwaysDirtyChecked();
return new StandardProperty(
property.getName(),
property.getNodeName(),
type,
lazyAvailable && property.isLazy(),
property.isInsertable(),
property.isUpdateable(),
property.getGeneration() == PropertyGeneration.INSERT || property.getGeneration() == PropertyGeneration.ALWAYS,
property.getGeneration() == PropertyGeneration.INSERT || property.getGeneration() == PropertyGeneration.ALWAYS,
property.getGeneration() == PropertyGeneration.ALWAYS,
property.isOptional(),
alwaysDirtyCheck || property.isUpdateable(),
property.isOptimisticLocked(),
property.getCascadeStyle(),
property.getValue().getFetchMode()
);
property.getValue().getFetchMode()
);
}
/**
* Generate a "standard" (i.e., non-identifier and non-version) based on the given
* mapped property.
*
* @param property The mapped property.
* @param lazyAvailable Is property lazy loading currently available.
* @return The appropriate StandardProperty definition.
* @return The appropriate NonIdentifierProperty definition.
*/
public static StandardProperty buildStandardProperty(AttributeBinding property, boolean lazyAvailable) {
@ -299,7 +422,6 @@ public class PropertyFactory {
return new StandardProperty(
singularAttributeBinding.getAttribute().getName(),
null,
type,
lazyAvailable && singularAttributeBinding.isLazy(),
true, // insertable
@ -325,7 +447,6 @@ public class PropertyFactory {
return new StandardProperty(
pluralAttributeBinding.getAttribute().getName(),
null,
type,
lazyAvailable && pluralAttributeBinding.isLazy(),
// TODO: fix this when HHH-6356 is fixed; for now assume AbstractPluralAttributeBinding is updatable and insertable

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 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 Middleware LLC.
* 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
@ -20,118 +20,69 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.tuple;
import org.hibernate.FetchMode;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.type.Type;
/**
* Represents a basic property within the Hibernate runtime-metamodel.
* Represents a non-identifier property within the Hibernate runtime-metamodel.
*
* @author Steve Ebersole
*/
public class StandardProperty extends Property {
@Deprecated
public class StandardProperty extends AbstractNonIdentifierAttribute implements NonIdentifierAttribute {
private final boolean lazy;
private final boolean insertable;
private final boolean updateable;
private final boolean insertGenerated;
private final boolean updateGenerated;
private final boolean nullable;
private final boolean dirtyCheckable;
private final boolean versionable;
private final CascadeStyle cascadeStyle;
private final FetchMode fetchMode;
/**
* Constructs StandardProperty instances.
*
* @param name The name by which the property can be referenced within
* its owner.
* @param node The node name to use for XML-based representation of this
* property.
* @param type The Hibernate Type of this property.
* @param lazy Should this property be handled lazily?
* @param insertable Is this property an insertable value?
* @param updateable Is this property an updateable value?
* @param insertGenerated Is this property generated in the database on insert?
* @param updateGenerated Is this property generated in the database on update?
* @param nullable Is this property a nullable value?
* @param checkable Is this property a checkable value?
* @param versionable Is this property a versionable value?
* @param cascadeStyle The cascade style for this property's value.
* @param fetchMode Any fetch mode defined for this property
*/
public StandardProperty(
String name,
String node,
Type type,
boolean lazy,
boolean insertable,
boolean updateable,
boolean insertGenerated,
boolean updateGenerated,
boolean nullable,
boolean checkable,
boolean versionable,
CascadeStyle cascadeStyle,
FetchMode fetchMode) {
super(name, node, type);
this.lazy = lazy;
this.insertable = insertable;
this.updateable = updateable;
this.insertGenerated = insertGenerated;
this.updateGenerated = updateGenerated;
this.nullable = nullable;
this.dirtyCheckable = checkable;
this.versionable = versionable;
this.cascadeStyle = cascadeStyle;
this.fetchMode = fetchMode;
}
public boolean isLazy() {
return lazy;
}
public boolean isInsertable() {
return insertable;
}
public boolean isUpdateable() {
return updateable;
}
public boolean isInsertGenerated() {
return insertGenerated;
}
public boolean isUpdateGenerated() {
return updateGenerated;
}
public boolean isNullable() {
return nullable;
}
public boolean isDirtyCheckable(boolean hasUninitializedProperties) {
return isDirtyCheckable() && ( !hasUninitializedProperties || !isLazy() );
}
public boolean isDirtyCheckable() {
return dirtyCheckable;
}
public boolean isVersionable() {
return versionable;
}
public CascadeStyle getCascadeStyle() {
return cascadeStyle;
}
public FetchMode getFetchMode() {
return fetchMode;
/**
* Constructs NonIdentifierProperty instances.
*
* @param name The name by which the property can be referenced within
* its owner.
* @param type The Hibernate Type of this property.
* @param lazy Should this property be handled lazily?
* @param insertable Is this property an insertable value?
* @param updateable Is this property an updateable value?
* @param insertGenerated Is this property generated in the database on insert?
* @param updateGenerated Is this property generated in the database on update?
* @param nullable Is this property a nullable value?
* @param checkable Is this property a checkable value?
* @param versionable Is this property a versionable value?
* @param cascadeStyle The cascade style for this property's value.
* @param fetchMode Any fetch mode defined for this property
*/
public StandardProperty(
String name,
Type type,
boolean lazy,
boolean insertable,
boolean updateable,
boolean insertGenerated,
boolean updateGenerated,
boolean nullable,
boolean checkable,
boolean versionable,
CascadeStyle cascadeStyle,
FetchMode fetchMode) {
super(
null,
null,
-1,
name,
type,
new BaselineAttributeInformation.Builder()
.setLazy( lazy )
.setInsertable( insertable )
.setUpdateable( updateable )
.setInsertGenerated( insertGenerated )
.setUpdateGenerated( updateGenerated )
.setNullable( nullable )
.setDirtyCheckable( checkable )
.setVersionable( versionable )
.setCascadeStyle( cascadeStyle )
.setFetchMode( fetchMode )
.createInformation()
);
}
}

View File

@ -1,81 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
*
* 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.tuple;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.VersionValue;
import org.hibernate.type.Type;
/**
* Represents a version property within the Hibernate runtime-metamodel.
*
* @author Steve Ebersole
*/
public class VersionProperty extends StandardProperty {
private final VersionValue unsavedValue;
/**
* Constructs VersionProperty instances.
*
* @param name The name by which the property can be referenced within
* its owner.
* @param node The node name to use for XML-based representation of this
* property.
* @param type The Hibernate Type of this property.
* @param lazy Should this property be handled lazily?
* @param insertable Is this property an insertable value?
* @param updateable Is this property an updateable value?
* @param insertGenerated Is this property generated in the database on insert?
* @param updateGenerated Is this property generated in the database on update?
* @param nullable Is this property a nullable value?
* @param checkable Is this property a checkable value?
* @param versionable Is this property a versionable value?
* @param cascadeStyle The cascade style for this property's value.
* @param unsavedValue The value which, if found as the value of
* this (i.e., the version) property, represents new (i.e., un-saved)
* instances of the owning entity.
*/
public VersionProperty(
String name,
String node,
Type type,
boolean lazy,
boolean insertable,
boolean updateable,
boolean insertGenerated,
boolean updateGenerated,
boolean nullable,
boolean checkable,
boolean versionable,
CascadeStyle cascadeStyle,
VersionValue unsavedValue) {
super( name, node, type, lazy, insertable, updateable, insertGenerated, updateGenerated, nullable, checkable, versionable, cascadeStyle, null );
this.unsavedValue = unsavedValue;
}
public VersionValue getUnsavedValue() {
return unsavedValue;
}
}

View File

@ -0,0 +1,61 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.tuple.component;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.tuple.AbstractNonIdentifierAttribute;
import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.tuple.NonIdentifierAttribute;
import org.hibernate.type.Type;
/**
* @author Steve Ebersole
*/
public abstract class AbstractCompositeBasedAttribute
extends AbstractNonIdentifierAttribute
implements NonIdentifierAttribute {
private final int ownerAttributeNumber;
public AbstractCompositeBasedAttribute(
AbstractCompositeDefinition source,
SessionFactoryImplementor sessionFactory,
int attributeNumber,
String attributeName,
Type attributeType,
BaselineAttributeInformation baselineInfo,
int ownerAttributeNumber) {
super( source, sessionFactory, attributeNumber, attributeName, attributeType, baselineInfo );
this.ownerAttributeNumber = ownerAttributeNumber;
}
protected int ownerAttributeNumber() {
return ownerAttributeNumber;
}
@Override
public AbstractCompositeDefinition getSource() {
return (AbstractCompositeDefinition) super.getSource();
}
}

View File

@ -0,0 +1,202 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.tuple.component;
import java.util.Iterator;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.OuterJoinLoadable;
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.CompositeDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.tuple.AbstractNonIdentifierAttribute;
import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.ForeignKeyDirection;
import org.hibernate.type.Type;
import static org.hibernate.engine.internal.JoinHelper.getLHSColumnNames;
import static org.hibernate.engine.internal.JoinHelper.getLHSTableName;
import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames;
/**
* @author Steve Ebersole
*/
public abstract class AbstractCompositeDefinition extends AbstractNonIdentifierAttribute implements CompositeDefinition {
protected AbstractCompositeDefinition(
AttributeSource source,
SessionFactoryImplementor sessionFactory,
int attributeNumber,
String attributeName,
CompositeType attributeType,
BaselineAttributeInformation baselineInfo) {
super( source, sessionFactory, attributeNumber, attributeName, attributeType, baselineInfo );
}
@Override
public CompositeType getType() {
return (CompositeType) super.getType();
}
@Override
public Iterable<AttributeDefinition> getAttributes() {
return new Iterable<AttributeDefinition>() {
@Override
public Iterator<AttributeDefinition> iterator() {
return new Iterator<AttributeDefinition>() {
private final int numberOfAttributes = getType().getSubtypes().length;
private int currentAttributeNumber = 0;
private int currentColumnPosition = 0;
@Override
public boolean hasNext() {
return currentAttributeNumber < numberOfAttributes;
}
@Override
public AttributeDefinition next() {
final int attributeNumber = currentAttributeNumber;
currentAttributeNumber++;
final String name = getType().getPropertyNames()[attributeNumber];
final Type type = getType().getSubtypes()[attributeNumber];
int columnPosition = currentColumnPosition;
currentColumnPosition += type.getColumnSpan( sessionFactory() );
if ( type.isAssociationType() ) {
// we build the association-key here because of the "goofiness" with 'currentColumnPosition'
final AssociationKey associationKey;
final AssociationType aType = (AssociationType) type;
final Joinable joinable = aType.getAssociatedJoinable( sessionFactory() );
if ( aType.getForeignKeyDirection() == ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT ) {
associationKey = new AssociationKey(
getLHSTableName(
aType,
attributeNumber(),
(OuterJoinLoadable) joinable
),
getLHSColumnNames(
aType,
attributeNumber(),
columnPosition,
(OuterJoinLoadable) joinable,
sessionFactory()
)
);
}
else {
associationKey = new AssociationKey(
joinable.getTableName(),
getRHSColumnNames( aType, sessionFactory() )
);
}
return new CompositeBasedAssociationAttribute(
AbstractCompositeDefinition.this,
sessionFactory(),
currentAttributeNumber,
name,
(AssociationType) type,
new BaselineAttributeInformation.Builder()
.setInsertable( AbstractCompositeDefinition.this.isInsertable() )
.setUpdateable( AbstractCompositeDefinition.this.isUpdateable() )
.setInsertGenerated( AbstractCompositeDefinition.this.isInsertGenerated() )
.setUpdateGenerated( AbstractCompositeDefinition.this.isUpdateGenerated() )
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
.setDirtyCheckable( true )
.setVersionable( AbstractCompositeDefinition.this.isVersionable() )
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
.createInformation(),
AbstractCompositeDefinition.this.attributeNumber(),
associationKey
);
}
else if ( type.isComponentType() ) {
return new CompositeBasedCompositeAttribute(
AbstractCompositeDefinition.this,
sessionFactory(),
currentAttributeNumber,
name,
(CompositeType) type,
new BaselineAttributeInformation.Builder()
.setInsertable( AbstractCompositeDefinition.this.isInsertable() )
.setUpdateable( AbstractCompositeDefinition.this.isUpdateable() )
.setInsertGenerated( AbstractCompositeDefinition.this.isInsertGenerated() )
.setUpdateGenerated( AbstractCompositeDefinition.this.isUpdateGenerated() )
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
.setDirtyCheckable( true )
.setVersionable( AbstractCompositeDefinition.this.isVersionable() )
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
.createInformation()
);
}
else {
return new CompositeBasedBasicAttribute(
AbstractCompositeDefinition.this,
sessionFactory(),
currentAttributeNumber,
name,
type,
new BaselineAttributeInformation.Builder()
.setInsertable( AbstractCompositeDefinition.this.isInsertable() )
.setUpdateable( AbstractCompositeDefinition.this.isUpdateable() )
.setInsertGenerated( AbstractCompositeDefinition.this.isInsertGenerated() )
.setUpdateGenerated( AbstractCompositeDefinition.this.isUpdateGenerated() )
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
.setDirtyCheckable( true )
.setVersionable( AbstractCompositeDefinition.this.isVersionable() )
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
.createInformation()
);
}
}
@Override
public void remove() {
throw new UnsupportedOperationException( "Remove operation not supported here" );
}
};
}
};
}
public EntityPersister locateOwningPersister() {
if ( EntityDefinition.class.isInstance( getSource() ) ) {
return ( (EntityDefinition) getSource() ).getEntityPersister();
}
else {
return ( (AbstractCompositeDefinition) getSource() ).locateOwningPersister();
}
}
}

View File

@ -32,8 +32,8 @@ import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.Property;
import org.hibernate.tuple.PropertyFactory;
import org.hibernate.tuple.StandardProperty;
import org.hibernate.tuple.PropertyFactory;
/**
* Centralizes metamodel information about a component.

View File

@ -0,0 +1,157 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.tuple.component;
import org.hibernate.FetchMode;
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.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.walking.internal.Helper;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.AssociationKey;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CompositeType;
/**
* @author Steve Ebersole
*/
public class CompositeBasedAssociationAttribute
extends AbstractCompositeBasedAttribute
implements AssociationAttributeDefinition {
private final AssociationKey associationKey;
private Joinable joinable;
public CompositeBasedAssociationAttribute(
AbstractCompositeDefinition source,
SessionFactoryImplementor factory,
int attributeNumber,
String attributeName,
AssociationType attributeType,
BaselineAttributeInformation baselineInfo,
int ownerAttributeNumber,
AssociationKey associationKey) {
super( source, factory, attributeNumber, attributeName, attributeType, baselineInfo, ownerAttributeNumber );
this.associationKey = associationKey;
}
@Override
public AssociationType getType() {
return (AssociationType) super.getType();
}
protected Joinable getJoinable() {
if ( joinable == null ) {
joinable = getType().getAssociatedJoinable( sessionFactory() );
}
return joinable;
}
@Override
public AssociationKey getAssociationKey() {
return associationKey;
}
@Override
public boolean isCollection() {
return getJoinable().isCollection();
}
@Override
public EntityDefinition toEntityDefinition() {
if ( isCollection() ) {
throw new IllegalStateException( "Cannot treat collection attribute as entity type" );
}
return (EntityPersister) getJoinable();
}
@Override
public CollectionDefinition toCollectionDefinition() {
if ( isCollection() ) {
throw new IllegalStateException( "Cannot treat entity attribute as collection type" );
}
return (CollectionPersister) getJoinable();
}
@Override
public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) {
final EntityPersister owningPersister = locateOwningPersister();
FetchStyle style = determineFetchStyleByProfile(
loadQueryInfluencers,
owningPersister,
propertyPath,
ownerAttributeNumber()
);
if ( style == null ) {
style = determineFetchStyleByMetadata(
getSource().getType().getFetchMode( attributeNumber() ),
getType()
);
}
return new FetchStrategy( determineFetchTiming( style ), style );
}
protected FetchStyle determineFetchStyleByProfile(
LoadQueryInfluencers loadQueryInfluencers,
EntityPersister owningPersister,
PropertyPath propertyPath,
int ownerAttributeNumber) {
return Helper.determineFetchStyleByProfile(
loadQueryInfluencers,
owningPersister,
propertyPath,
ownerAttributeNumber
);
}
protected FetchStyle determineFetchStyleByMetadata(FetchMode fetchMode, AssociationType type) {
return Helper.determineFetchStyleByMetadata( fetchMode, type, sessionFactory() );
}
private FetchTiming determineFetchTiming(FetchStyle style) {
return Helper.determineFetchTiming( style, getType(), sessionFactory() );
}
private EntityPersister locateOwningPersister() {
return getSource().locateOwningPersister();
}
@Override
public CascadeStyle determineCascadeStyle() {
final CompositeType compositeType = (CompositeType) locateOwningPersister().getPropertyType( getName() );
return compositeType.getCascadeStyle( attributeNumber() );
}
}

View File

@ -0,0 +1,45 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.tuple.component;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.walking.spi.AttributeSource;
import org.hibernate.tuple.AbstractNonIdentifierAttribute;
import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.Type;
/**
* @author Steve Ebersole
*/
public class CompositeBasedBasicAttribute extends AbstractNonIdentifierAttribute {
protected CompositeBasedBasicAttribute(
AttributeSource source,
SessionFactoryImplementor sessionFactory,
int attributeNumber,
String attributeName,
Type attributeType,
BaselineAttributeInformation baselineInfo) {
super( source, sessionFactory, attributeNumber, attributeName, attributeType, baselineInfo );
}
}

View File

@ -0,0 +1,46 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.tuple.component;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.walking.spi.CompositeDefinition;
import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.CompositeType;
/**
* @author Steve Ebersole
*/
public class CompositeBasedCompositeAttribute
extends AbstractCompositeDefinition
implements CompositeDefinition {
public CompositeBasedCompositeAttribute(
CompositeDefinition source,
SessionFactoryImplementor sessionFactory,
int attributeNumber,
String attributeName,
CompositeType attributeType,
BaselineAttributeInformation baselineInfo) {
super( source, sessionFactory, attributeNumber, attributeName, attributeType, baselineInfo );
}
}

View File

@ -0,0 +1,50 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.tuple.entity;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.tuple.AbstractNonIdentifierAttribute;
import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.Type;
/**
* @author Steve Ebersole
*/
public abstract class AbstractEntityBasedAttribute extends AbstractNonIdentifierAttribute {
protected AbstractEntityBasedAttribute(
EntityPersister source,
SessionFactoryImplementor sessionFactory,
int attributeNumber,
String attributeName,
Type attributeType,
BaselineAttributeInformation attributeInformation) {
super( source, sessionFactory, attributeNumber, attributeName, attributeType, attributeInformation );
}
@Override
public EntityPersister getSource() {
return (EntityPersister) super.getSource();
}
}

View File

@ -56,8 +56,9 @@ import org.hibernate.property.Setter;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.ProxyFactory;
import org.hibernate.tuple.Instantiator;
import org.hibernate.tuple.NonIdentifierAttribute;
import org.hibernate.tuple.StandardProperty;
import org.hibernate.tuple.VersionProperty;
import org.hibernate.tuple.entity.VersionProperty;
import org.hibernate.type.ComponentType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
@ -604,7 +605,7 @@ public abstract class AbstractEntityTuplizer implements EntityTuplizer {
final Object[] result = new Object[span];
for ( int j = 0; j < span; j++ ) {
StandardProperty property = entityMetamodel.getProperties()[j];
NonIdentifierAttribute property = entityMetamodel.getProperties()[j];
if ( getAll || !property.isLazy() ) {
result[j] = getters[j].get( entity );
}

View File

@ -0,0 +1,132 @@
package org.hibernate.tuple.entity;
import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.PropertyPath;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.persister.walking.internal.Helper;
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
import org.hibernate.persister.walking.spi.AssociationKey;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.AssociationType;
import org.hibernate.type.ForeignKeyDirection;
import static org.hibernate.engine.internal.JoinHelper.getLHSColumnNames;
import static org.hibernate.engine.internal.JoinHelper.getLHSTableName;
import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames;
/**
* @author Steve Ebersole
*/
public class EntityBasedAssociationAttribute
extends AbstractEntityBasedAttribute
implements AssociationAttributeDefinition {
private Joinable joinable;
public EntityBasedAssociationAttribute(
EntityPersister source,
SessionFactoryImplementor sessionFactory,
int attributeNumber,
String attributeName,
AssociationType attributeType,
BaselineAttributeInformation baselineInfo) {
super( source, sessionFactory, attributeNumber, attributeName, attributeType, baselineInfo );
}
@Override
public AssociationType getType() {
return (AssociationType) super.getType();
}
protected Joinable getJoinable() {
if ( joinable == null ) {
joinable = getType().getAssociatedJoinable( sessionFactory() );
}
return joinable;
}
@Override
public AssociationKey getAssociationKey() {
final AssociationType type = getType();
final Joinable joinable = type.getAssociatedJoinable( sessionFactory() );
if ( type.getForeignKeyDirection() == ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT ) {
final String lhsTableName;
final String[] lhsColumnNames;
if ( joinable.isCollection() ) {
final QueryableCollection collectionPersister = (QueryableCollection) joinable;
lhsTableName = collectionPersister.getTableName();
lhsColumnNames = collectionPersister.getElementColumnNames();
}
else {
final OuterJoinLoadable entityPersister = (OuterJoinLoadable) joinable;
lhsTableName = getLHSTableName( type, attributeNumber(), entityPersister );
lhsColumnNames = getLHSColumnNames( type, attributeNumber(), entityPersister, sessionFactory() );
}
return new AssociationKey( lhsTableName, lhsColumnNames );
}
else {
return new AssociationKey( joinable.getTableName(), getRHSColumnNames( type, sessionFactory() ) );
}
}
@Override
public boolean isCollection() {
return getJoinable().isCollection();
}
@Override
public EntityDefinition toEntityDefinition() {
if ( isCollection() ) {
throw new IllegalStateException( "Cannot treat collection-valued attribute as entity type" );
}
return (EntityPersister) getJoinable();
}
@Override
public CollectionDefinition toCollectionDefinition() {
if ( ! isCollection() ) {
throw new IllegalStateException( "Cannot treat entity-valued attribute as collection type" );
}
return (QueryableCollection) getJoinable();
}
@Override
public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) {
final EntityPersister owningPersister = getSource().getEntityPersister();
FetchStyle style = Helper.determineFetchStyleByProfile(
loadQueryInfluencers,
owningPersister,
propertyPath,
attributeNumber()
);
if ( style == null ) {
style = Helper.determineFetchStyleByMetadata(
((OuterJoinLoadable) getSource().getEntityPersister()).getFetchMode( attributeNumber() ),
getType(),
sessionFactory()
);
}
return new FetchStrategy(
Helper.determineFetchTiming( style, getType(), sessionFactory() ),
style
);
}
@Override
public CascadeStyle determineCascadeStyle() {
return getSource().getEntityPersister().getPropertyCascadeStyles()[attributeNumber()];
}
}

View File

@ -0,0 +1,44 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.tuple.entity;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.Type;
/**
* @author Steve Ebersole
*/
public class EntityBasedBasicAttribute extends AbstractEntityBasedAttribute {
public EntityBasedBasicAttribute(
EntityPersister source,
SessionFactoryImplementor factory,
int attributeNumber,
String attributeName,
Type attributeType,
BaselineAttributeInformation baselineInfo) {
super( source, factory, attributeNumber, attributeName, attributeType, baselineInfo );
}
}

View File

@ -0,0 +1,49 @@
/*
* jDocBook, processing of DocBook sources
*
* 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.tuple.entity;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.tuple.component.AbstractCompositeDefinition;
import org.hibernate.persister.walking.spi.CompositeDefinition;
import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.CompositeType;
/**
* @author Steve Ebersole
*/
public class EntityBasedCompositeAttribute
extends AbstractCompositeDefinition
implements CompositeDefinition {
public EntityBasedCompositeAttribute(
EntityPersister source,
SessionFactoryImplementor factory,
int attributeNumber,
String attributeName,
CompositeType attributeType,
BaselineAttributeInformation baselineInfo) {
super( source, factory, attributeNumber, attributeName, attributeType, baselineInfo );
}
}

View File

@ -57,10 +57,12 @@ import org.hibernate.metamodel.binding.BasicAttributeBinding;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.domain.Attribute;
import org.hibernate.metamodel.domain.SingularAttribute;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.tuple.IdentifierProperty;
import org.hibernate.tuple.NonIdentifierAttribute;
import org.hibernate.tuple.PropertyFactory;
import org.hibernate.tuple.StandardProperty;
import org.hibernate.tuple.VersionProperty;
import org.hibernate.tuple.entity.VersionProperty;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
@ -78,17 +80,18 @@ public class EntityMetamodel implements Serializable {
private static final int NO_VERSION_INDX = -66;
private final SessionFactoryImplementor sessionFactory;
private final AbstractEntityPersister persister;
private final String name;
private final String rootName;
private final EntityType entityType;
private final IdentifierProperty identifierProperty;
private final IdentifierProperty identifierAttribute;
private final boolean versioned;
private final int propertySpan;
private final int versionPropertyIndex;
private final StandardProperty[] properties;
private final NonIdentifierAttribute[] properties;
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private final String[] propertyNames;
private final Type[] propertyTypes;
@ -136,17 +139,21 @@ public class EntityMetamodel implements Serializable {
private final EntityTuplizer entityTuplizer;
private final EntityInstrumentationMetadata instrumentationMetadata;
public EntityMetamodel(PersistentClass persistentClass, SessionFactoryImplementor sessionFactory) {
public EntityMetamodel(
PersistentClass persistentClass,
AbstractEntityPersister persister,
SessionFactoryImplementor sessionFactory) {
this.sessionFactory = sessionFactory;
this.persister = persister;
name = persistentClass.getEntityName();
rootName = persistentClass.getRootClass().getEntityName();
entityType = sessionFactory.getTypeResolver().getTypeFactory().manyToOne( name );
identifierProperty = PropertyFactory.buildIdentifierProperty(
persistentClass,
sessionFactory.getIdentifierGenerator( rootName )
);
identifierAttribute = PropertyFactory.buildIdentifierAttribute(
persistentClass,
sessionFactory.getIdentifierGenerator( rootName )
);
versioned = persistentClass.isVersioned();
@ -157,7 +164,7 @@ public class EntityMetamodel implements Serializable {
boolean hasLazy = false;
propertySpan = persistentClass.getPropertyClosureSpan();
properties = new StandardProperty[propertySpan];
properties = new NonIdentifierAttribute[propertySpan];
List<Integer> naturalIdNumbers = new ArrayList<Integer>();
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
propertyNames = new String[propertySpan];
@ -191,10 +198,22 @@ public class EntityMetamodel implements Serializable {
if ( prop == persistentClass.getVersion() ) {
tempVersionProperty = i;
properties[i] = PropertyFactory.buildVersionProperty( prop, instrumentationMetadata.isInstrumented() );
properties[i] = PropertyFactory.buildVersionProperty(
persister,
sessionFactory,
i,
prop,
instrumentationMetadata.isInstrumented()
);
}
else {
properties[i] = PropertyFactory.buildStandardProperty( prop, instrumentationMetadata.isInstrumented() );
properties[i] = PropertyFactory.buildEntityBasedAttribute(
persister,
sessionFactory,
i,
prop,
instrumentationMetadata.isInstrumented()
);
}
if ( prop.isNaturalIdentifier() ) {
@ -363,15 +382,19 @@ public class EntityMetamodel implements Serializable {
}
}
public EntityMetamodel(EntityBinding entityBinding, SessionFactoryImplementor sessionFactory) {
public EntityMetamodel(
EntityBinding entityBinding,
AbstractEntityPersister persister,
SessionFactoryImplementor sessionFactory) {
this.sessionFactory = sessionFactory;
this.persister = persister;
name = entityBinding.getEntity().getName();
rootName = entityBinding.getHierarchyDetails().getRootEntityBinding().getEntity().getName();
entityType = sessionFactory.getTypeResolver().getTypeFactory().manyToOne( name );
identifierProperty = PropertyFactory.buildIdentifierProperty(
identifierAttribute = PropertyFactory.buildIdentifierProperty(
entityBinding,
sessionFactory.getIdentifierGenerator( rootName )
);
@ -398,7 +421,7 @@ public class EntityMetamodel implements Serializable {
entityBinding.getAttributeBindingClosureSpan() :
entityBinding.getAttributeBindingClosureSpan() - 1;
properties = new StandardProperty[propertySpan];
properties = new NonIdentifierAttribute[propertySpan];
List naturalIdNumbers = new ArrayList();
// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
propertyNames = new String[propertySpan];
@ -435,6 +458,7 @@ public class EntityMetamodel implements Serializable {
if ( attributeBinding == entityBinding.getHierarchyDetails().getVersioningAttributeBinding() ) {
tempVersionProperty = i;
properties[i] = PropertyFactory.buildVersionProperty(
persister,
entityBinding.getHierarchyDetails().getVersioningAttributeBinding(),
instrumentationMetadata.isInstrumented()
);
@ -595,7 +619,7 @@ public class EntityMetamodel implements Serializable {
}
}
private ValueInclusion determineInsertValueGenerationType(Property mappingProperty, StandardProperty runtimeProperty) {
private ValueInclusion determineInsertValueGenerationType(Property mappingProperty, NonIdentifierAttribute runtimeProperty) {
if ( runtimeProperty.isInsertGenerated() ) {
return ValueInclusion.FULL;
}
@ -607,7 +631,7 @@ public class EntityMetamodel implements Serializable {
return ValueInclusion.NONE;
}
private ValueInclusion determineInsertValueGenerationType(AttributeBinding mappingProperty, StandardProperty runtimeProperty) {
private ValueInclusion determineInsertValueGenerationType(AttributeBinding mappingProperty, NonIdentifierAttribute runtimeProperty) {
if ( runtimeProperty.isInsertGenerated() ) {
return ValueInclusion.FULL;
}
@ -636,7 +660,7 @@ public class EntityMetamodel implements Serializable {
return false;
}
private ValueInclusion determineUpdateValueGenerationType(Property mappingProperty, StandardProperty runtimeProperty) {
private ValueInclusion determineUpdateValueGenerationType(Property mappingProperty, NonIdentifierAttribute runtimeProperty) {
if ( runtimeProperty.isUpdateGenerated() ) {
return ValueInclusion.FULL;
}
@ -648,7 +672,7 @@ public class EntityMetamodel implements Serializable {
return ValueInclusion.NONE;
}
private ValueInclusion determineUpdateValueGenerationType(AttributeBinding mappingProperty, StandardProperty runtimeProperty) {
private ValueInclusion determineUpdateValueGenerationType(AttributeBinding mappingProperty, NonIdentifierAttribute runtimeProperty) {
if ( runtimeProperty.isUpdateGenerated() ) {
return ValueInclusion.FULL;
}
@ -762,7 +786,7 @@ public class EntityMetamodel implements Serializable {
}
public IdentifierProperty getIdentifierProperty() {
return identifierProperty;
return identifierAttribute;
}
public int getPropertySpan() {
@ -782,7 +806,7 @@ public class EntityMetamodel implements Serializable {
}
}
public StandardProperty[] getProperties() {
public NonIdentifierAttribute[] getProperties() {
return properties;
}

View File

@ -0,0 +1,70 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, 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.tuple.entity;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.VersionValue;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.tuple.AbstractNonIdentifierAttribute;
import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.Type;
/**
* Represents a version property within the Hibernate runtime-metamodel.
*
* @author Steve Ebersole
*/
public class VersionProperty extends AbstractNonIdentifierAttribute {
private final VersionValue unsavedValue;
/**
* Constructs VersionProperty instances.
*
* @param source Reference back to the source of this attribute (the persister)
* @param sessionFactory The session factory this is part of.
* @param attributeNumber The attribute number within thje
* @param attributeName The name by which the property can be referenced within
* its owner.
* @param attributeType The Hibernate Type of this property.
* @param attributeInformation The basic attribute information.
* @param unsavedValue The value which, if found as the value of
* this (i.e., the version) property, represents new (i.e., un-saved)
* instances of the owning entity.
*/
public VersionProperty(
EntityPersister source,
SessionFactoryImplementor sessionFactory,
int attributeNumber,
String attributeName,
Type attributeType,
BaselineAttributeInformation attributeInformation, VersionValue unsavedValue) {
super( source, sessionFactory, attributeNumber, attributeName, attributeType, attributeInformation );
this.unsavedValue = unsavedValue;
}
public VersionValue getUnsavedValue() {
return unsavedValue;
}
}

View File

@ -28,7 +28,7 @@ import java.util.Map;
import org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.property.BackrefPropertyAccessor;
import org.hibernate.tuple.StandardProperty;
import org.hibernate.tuple.NonIdentifierAttribute;
/**
* Collection of convenience methods relating to operations across arrays of types...
@ -280,7 +280,7 @@ public class TypeHelper {
* @return Array containing indices of the dirty properties, or null if no properties considered dirty.
*/
public static int[] findDirty(
final StandardProperty[] properties,
final NonIdentifierAttribute[] properties,
final Object[] currentState,
final Object[] previousState,
final boolean[][] includeColumns,
@ -328,7 +328,7 @@ public class TypeHelper {
* @return Array containing indices of the modified properties, or null if no properties considered modified.
*/
public static int[] findModified(
final StandardProperty[] properties,
final NonIdentifierAttribute[] properties,
final Object[] currentState,
final Object[] previousState,
final boolean[][] includeColumns,

View File

@ -0,0 +1,149 @@
/*
* jDocBook, processing of DocBook sources
*
* 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 javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import java.util.List;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.loader.plan.internal.CascadeLoadPlanBuilderStrategy;
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.junit.Test;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.junit4.ExtraAssertions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
/**
* @author Steve Ebersole
*/
public class LoadPlanBuilderTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Message.class, Poster.class };
}
@Test
public void testSimpleBuild() {
EntityPersister ep = (EntityPersister) sessionFactory().getClassMetadata(Message.class);
SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
sessionFactory(),
LoadQueryInfluencers.NONE,
"abc",
0
);
LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, ep );
assertFalse( plan.hasAnyScalarReturns() );
assertEquals( 1, plan.getReturns().size() );
Return rtn = plan.getReturns().get( 0 );
EntityReturn entityReturn = ExtraAssertions.assertTyping( EntityReturn.class, rtn );
assertEquals( "abc", entityReturn.getAlias() );
assertNotNull( entityReturn.getFetches() );
assertEquals( 1, entityReturn.getFetches().length );
Fetch fetch = entityReturn.getFetches()[0];
EntityFetch entityFetch = ExtraAssertions.assertTyping( EntityFetch.class, fetch );
assertNotNull( entityFetch.getFetches() );
assertEquals( 0, entityFetch.getFetches().length );
}
@Test
public void testCascadeBasedBuild() {
EntityPersister ep = (EntityPersister) sessionFactory().getClassMetadata(Message.class);
CascadeLoadPlanBuilderStrategy strategy = new CascadeLoadPlanBuilderStrategy(
CascadingActions.MERGE,
sessionFactory(),
LoadQueryInfluencers.NONE,
"abc",
0
);
LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, ep );
assertFalse( plan.hasAnyScalarReturns() );
assertEquals( 1, plan.getReturns().size() );
Return rtn = plan.getReturns().get( 0 );
EntityReturn entityReturn = ExtraAssertions.assertTyping( EntityReturn.class, rtn );
assertEquals( "abc", entityReturn.getAlias() );
assertNotNull( entityReturn.getFetches() );
assertEquals( 1, entityReturn.getFetches().length );
Fetch fetch = entityReturn.getFetches()[0];
EntityFetch entityFetch = ExtraAssertions.assertTyping( EntityFetch.class, fetch );
assertNotNull( entityFetch.getFetches() );
assertEquals( 0, entityFetch.getFetches().length );
}
@Test
public void testCollectionInitializerCase() {
CollectionPersister cp = sessionFactory().getCollectionPersister( Poster.class.getName() + ".messages" );
SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
sessionFactory(),
LoadQueryInfluencers.NONE,
"abc",
0
);
LoadPlan plan = LoadPlanBuilder.buildRootCollectionLoadPlan( strategy, cp );
assertFalse( plan.hasAnyScalarReturns() );
assertEquals( 1, plan.getReturns().size() );
Return rtn = plan.getReturns().get( 0 );
CollectionReturn collectionReturn = ExtraAssertions.assertTyping( CollectionReturn.class, rtn );
assertEquals( "abc", collectionReturn.getAlias() );
assertNotNull( collectionReturn.getFetches() );
assertEquals( 1, collectionReturn.getFetches().length ); // the collection elements are fetched
Fetch fetch = collectionReturn.getFetches()[0];
EntityFetch entityFetch = ExtraAssertions.assertTyping( EntityFetch.class, fetch );
assertNotNull( entityFetch.getFetches() );
assertEquals( 0, entityFetch.getFetches().length );
}
@Entity( name = "Message" )
public static class Message {
@Id
private Integer id;
private String name;
@ManyToOne( cascade = CascadeType.MERGE )
@JoinColumn
private Poster poster;
}
@Entity( name = "Poster" )
public static class Poster {
@Id
private Integer id;
private String name;
@OneToMany(mappedBy = "poster")
private List<Message> messages;
}
}

View File

@ -0,0 +1,177 @@
/*
* jDocBook, processing of DocBook sources
*
* 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;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import java.util.List;
import org.hibernate.annotations.common.util.StringHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.walking.spi.AssociationVisitationStrategy;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CollectionDefinition;
import org.hibernate.persister.walking.spi.CompositeDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.persister.walking.spi.MetadataDrivenModelGraphVisitor;
import org.junit.Test;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
/**
* @author Steve Ebersole
*/
public class BasicWalkingTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Message.class, Poster.class };
}
@Test
public void testIt() {
EntityPersister ep = (EntityPersister) sessionFactory().getClassMetadata(Message.class);
MetadataDrivenModelGraphVisitor.visitEntity(
new AssociationVisitationStrategy() {
private int depth = 0;
@Override
public void start() {
System.out.println( ">> Start" );
}
@Override
public void finish() {
System.out.println( "<< Finish" );
}
@Override
public void startingEntity(EntityDefinition entityDefinition) {
System.out.println(
String.format(
"%s Starting entity (%s)",
StringHelper.repeat( ">>", ++depth ),
entityDefinition.toString()
)
);
}
@Override
public void finishingEntity(EntityDefinition entityDefinition) {
System.out.println(
String.format(
"%s Finishing entity (%s)",
StringHelper.repeat( "<<", depth-- ),
entityDefinition.toString()
)
);
}
@Override
public void startingCollection(CollectionDefinition collectionDefinition) {
System.out.println(
String.format(
"%s Starting collection (%s)",
StringHelper.repeat( ">>", ++depth ),
collectionDefinition.toString()
)
);
}
@Override
public void finishingCollection(CollectionDefinition collectionDefinition) {
System.out.println(
String.format(
"%s Finishing collection (%s)",
StringHelper.repeat( ">>", depth-- ),
collectionDefinition.toString()
)
);
}
@Override
public void startingComposite(CompositeDefinition compositeDefinition) {
System.out.println(
String.format(
"%s Starting composite (%s)",
StringHelper.repeat( ">>", ++depth ),
compositeDefinition.toString()
)
);
}
@Override
public void finishingComposite(CompositeDefinition compositeDefinition) {
System.out.println(
String.format(
"%s Finishing composite (%s)",
StringHelper.repeat( ">>", depth-- ),
compositeDefinition.toString()
)
);
}
@Override
public boolean startingAttribute(AttributeDefinition attributeDefinition) {
System.out.println(
String.format(
"%s Handling attribute (%s)",
StringHelper.repeat( ">>", depth + 1 ),
attributeDefinition.toString()
)
);
return true;
}
@Override
public void finishingAttribute(AttributeDefinition attributeDefinition) {
// nothing to do
}
},
ep
);
}
@Entity( name = "Message" )
public static class Message {
@Id
private Integer id;
private String name;
@ManyToOne
@JoinColumn
private Poster poster;
}
@Entity( name = "Poster" )
public static class Poster {
@Id
private Integer id;
private String name;
@OneToMany(mappedBy = "poster")
private List<Message> messages;
}
}

View File

@ -37,6 +37,7 @@ import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy;
import org.hibernate.cache.spi.entry.CacheEntry;
import org.hibernate.cache.spi.entry.CacheEntryStructure;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.Mapping;
@ -54,6 +55,9 @@ import org.hibernate.metamodel.binding.PluralAttributeBinding;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.spi.PersisterClassResolver;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.tuple.entity.NonPojoInstrumentationMetadata;
@ -579,6 +583,21 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
// TODO Auto-generated method stub
return null;
}
@Override
public EntityPersister getEntityPersister() {
return this;
}
@Override
public Iterable<AttributeDefinition> getEmbeddedCompositeIdentifierAttributes() {
throw new NotYetImplementedException();
}
@Override
public Iterable<AttributeDefinition> getAttributes() {
throw new NotYetImplementedException();
}
}
public static class NoopCollectionPersister implements CollectionPersister {
@ -606,8 +625,23 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public CollectionPersister getCollectionPersister() {
return this;
}
public CollectionType getCollectionType() {
return null; //To change body of implemented methods use File | Settings | File Templates.
throw new NotYetImplementedException();
}
@Override
public CollectionIndexDefinition getIndexDefinition() {
throw new NotYetImplementedException();
}
@Override
public CollectionElementDefinition getElementDefinition() {
throw new NotYetImplementedException();
}
public Type getKeyType() {

View File

@ -17,6 +17,7 @@ import org.hibernate.cache.spi.entry.CacheEntry;
import org.hibernate.cache.spi.entry.CacheEntryStructure;
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.internal.TwoPhaseLoad;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.Mapping;
@ -34,6 +35,7 @@ import org.hibernate.internal.util.compare.EqualsHelper;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.tuple.entity.NonPojoInstrumentationMetadata;
@ -671,4 +673,19 @@ public class CustomPersister implements EntityPersister {
public FilterAliasGenerator getFilterAliasGenerator(String rootAlias) {
return new StaticFilterAliasGenerator(rootAlias);
}
@Override
public EntityPersister getEntityPersister() {
return this;
}
@Override
public Iterable<AttributeDefinition> getEmbeddedCompositeIdentifierAttributes() {
throw new NotYetImplementedException();
}
@Override
public Iterable<AttributeDefinition> getAttributes() {
throw new NotYetImplementedException();
}
}