org.hibernate.tuple.entity.EntityBasedAssociationAttribute.java Source code

Java tutorial

Introduction

Here is the source code for org.hibernate.tuple.entity.EntityBasedAssociationAttribute.java

Source

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
 */
package org.hibernate.tuple.entity;

import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.internal.JoinHelper;
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.spi.HydratedCompoundValueHandler;
import org.hibernate.persister.walking.internal.FetchStrategyHelper;
import org.hibernate.persister.walking.internal.StandardAnyTypeDefinition;
import org.hibernate.persister.walking.spi.AnyMappingDefinition;
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.persister.walking.spi.WalkingException;
import org.hibernate.tuple.BaselineAttributeInformation;
import org.hibernate.type.AnyType;
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 {

    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();
    }

    @Override
    public AssociationKey getAssociationKey() {
        final AssociationType type = getType();

        if (type.isAnyType()) {
            return new AssociationKey(
                    JoinHelper.getLHSTableName(type, attributeNumber(), (OuterJoinLoadable) getSource()),
                    JoinHelper.getLHSColumnNames(type, attributeNumber(), 0, (OuterJoinLoadable) getSource(),
                            sessionFactory()));
        }

        final Joinable joinable = type.getAssociatedJoinable(sessionFactory());

        if (type.getForeignKeyDirection() == ForeignKeyDirection.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) source();
                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 AssociationNature getAssociationNature() {
        if (getType().isAnyType()) {
            return AssociationNature.ANY;
        } else {
            if (getType().isCollectionType()) {
                return AssociationNature.COLLECTION;
            } else {
                return AssociationNature.ENTITY;
            }
        }
    }

    @Override
    public AnyMappingDefinition toAnyDefinition() {
        return new StandardAnyTypeDefinition((AnyType) getType(),
                getSource().getEntityMetamodel().getProperties()[attributeNumber()].isLazy());
    }

    private Joinable joinable;

    protected Joinable getJoinable() {
        if (getAssociationNature() == AssociationNature.ANY) {
            throw new WalkingException("Cannot resolve AnyType to a Joinable");
        }

        if (joinable == null) {
            joinable = getType().getAssociatedJoinable(sessionFactory());
        }
        return joinable;
    }

    @Override
    public EntityDefinition toEntityDefinition() {
        if (getAssociationNature() == AssociationNature.ANY) {
            throw new WalkingException("Cannot treat any-type attribute as an entity type");
        }
        if (getAssociationNature() == AssociationNature.COLLECTION) {
            throw new IllegalStateException("Cannot treat collection-valued attribute as entity type");
        }
        return (EntityPersister) getJoinable();
    }

    @Override
    public CollectionDefinition toCollectionDefinition() {
        if (getAssociationNature() == AssociationNature.ANY) {
            throw new WalkingException("Cannot treat any-type attribute as a collection type");
        }
        if (getAssociationNature() == AssociationNature.ENTITY) {
            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 = FetchStrategyHelper.determineFetchStyleByProfile(loadQueryInfluencers, owningPersister,
                propertyPath, attributeNumber());
        if (style == null) {
            style = FetchStrategyHelper.determineFetchStyleByMetadata(
                    ((OuterJoinLoadable) getSource().getEntityPersister()).getFetchMode(attributeNumber()),
                    getType(), sessionFactory());
        }

        return new FetchStrategy(FetchStrategyHelper.determineFetchTiming(style, getType(), sessionFactory()),
                style);
    }

    @Override
    public CascadeStyle determineCascadeStyle() {
        return getSource().getEntityPersister().getPropertyCascadeStyles()[attributeNumber()];
    }

    private HydratedCompoundValueHandler hydratedCompoundValueHandler;

    @Override
    public HydratedCompoundValueHandler getHydratedCompoundValueExtractor() {
        if (hydratedCompoundValueHandler == null) {
            hydratedCompoundValueHandler = new HydratedCompoundValueHandler() {
                @Override
                public Object extract(Object hydratedState) {
                    return ((Object[]) hydratedState)[attributeNumber()];
                }

                @Override
                public void inject(Object hydratedState, Object value) {
                    ((Object[]) hydratedState)[attributeNumber()] = value;
                }
            };
        }
        return hydratedCompoundValueHandler;
    }

    @Override
    protected String loggableMetadata() {
        return super.loggableMetadata() + ",association";
    }
}