org.hibernate.mapping.Collection.java Source code

Java tutorial

Introduction

Here is the source code for org.hibernate.mapping.Collection.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.mapping;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.Objects;

import org.hibernate.FetchMode;
import org.hibernate.MappingException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.internal.FilterConfiguration;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.CollectionType;
import org.hibernate.type.Type;

/**
 * Mapping for a collection. Subclasses specialize to particular collection styles.
 *
 * @author Gavin King
 */
public abstract class Collection implements Fetchable, Value, Filterable {

    public static final String DEFAULT_ELEMENT_COLUMN_NAME = "elt";
    public static final String DEFAULT_KEY_COLUMN_NAME = "id";

    private final MetadataImplementor metadata;
    private PersistentClass owner;

    private KeyValue key;
    private Value element;
    private Table collectionTable;
    private String role;
    private boolean lazy;
    private boolean extraLazy;
    private boolean inverse;
    private boolean mutable = true;
    private boolean subselectLoadable;
    private String cacheConcurrencyStrategy;
    private String cacheRegionName;
    private String orderBy;
    private String where;
    private String manyToManyWhere;
    private String manyToManyOrderBy;
    private String referencedPropertyName;
    private String mappedByProperty;
    private boolean sorted;
    private Comparator comparator;
    private String comparatorClassName;
    private boolean orphanDelete;
    private int batchSize = -1;
    private FetchMode fetchMode;
    private boolean embedded = true;
    private boolean optimisticLocked = true;
    private Class collectionPersisterClass;
    private String typeName;
    private Properties typeParameters;
    private final java.util.List filters = new ArrayList();
    private final java.util.List manyToManyFilters = new ArrayList();
    private final java.util.Set<String> synchronizedTables = new HashSet<String>();

    private String customSQLInsert;
    private boolean customInsertCallable;
    private ExecuteUpdateResultCheckStyle insertCheckStyle;
    private String customSQLUpdate;
    private boolean customUpdateCallable;
    private ExecuteUpdateResultCheckStyle updateCheckStyle;
    private String customSQLDelete;
    private boolean customDeleteCallable;
    private ExecuteUpdateResultCheckStyle deleteCheckStyle;
    private String customSQLDeleteAll;
    private boolean customDeleteAllCallable;
    private ExecuteUpdateResultCheckStyle deleteAllCheckStyle;

    private String loaderName;

    protected Collection(MetadataBuildingContext buildingContext, PersistentClass owner) {
        this(buildingContext.getMetadataCollector(), owner);
    }

    /**
     * @deprecated Use {@link Collection#Collection(MetadataBuildingContext, PersistentClass)} instead.
     */
    @Deprecated
    protected Collection(MetadataImplementor metadata, PersistentClass owner) {
        this.metadata = metadata;
        this.owner = owner;
    }

    public MetadataImplementor getMetadata() {
        return metadata;
    }

    @Override
    public ServiceRegistry getServiceRegistry() {
        return getMetadata().getMetadataBuildingOptions().getServiceRegistry();
    }

    public boolean isSet() {
        return false;
    }

    public KeyValue getKey() {
        return key;
    }

    public Value getElement() {
        return element;
    }

    public boolean isIndexed() {
        return false;
    }

    public Table getCollectionTable() {
        return collectionTable;
    }

    public void setCollectionTable(Table table) {
        this.collectionTable = table;
    }

    public boolean isSorted() {
        return sorted;
    }

    public Comparator getComparator() {
        if (comparator == null && comparatorClassName != null) {
            try {
                final ClassLoaderService classLoaderService = getMetadata().getMetadataBuildingOptions()
                        .getServiceRegistry().getService(ClassLoaderService.class);
                setComparator((Comparator) classLoaderService.classForName(comparatorClassName).newInstance());
            } catch (Exception e) {
                throw new MappingException("Could not instantiate comparator class [" + comparatorClassName
                        + "] for collection " + getRole());
            }
        }
        return comparator;
    }

    public boolean isLazy() {
        return lazy;
    }

    public void setLazy(boolean lazy) {
        this.lazy = lazy;
    }

    public String getRole() {
        return role;
    }

    public abstract CollectionType getDefaultCollectionType() throws MappingException;

    public boolean isPrimitiveArray() {
        return false;
    }

    public boolean isArray() {
        return false;
    }

    public boolean hasFormula() {
        return false;
    }

    public boolean isOneToMany() {
        return element instanceof OneToMany;
    }

    public boolean isInverse() {
        return inverse;
    }

    public String getOwnerEntityName() {
        return owner.getEntityName();
    }

    public String getOrderBy() {
        return orderBy;
    }

    public void setComparator(Comparator comparator) {
        this.comparator = comparator;
    }

    public void setElement(Value element) {
        this.element = element;
    }

    public void setKey(KeyValue key) {
        this.key = key;
    }

    public void setOrderBy(String orderBy) {
        this.orderBy = orderBy;
    }

    public void setRole(String role) {
        this.role = role;
    }

    public void setSorted(boolean sorted) {
        this.sorted = sorted;
    }

    public void setInverse(boolean inverse) {
        this.inverse = inverse;
    }

    public PersistentClass getOwner() {
        return owner;
    }

    /**
     * @param owner The owner
     *
     * @deprecated Inject the owner into constructor.
     */
    @Deprecated
    public void setOwner(PersistentClass owner) {
        this.owner = owner;
    }

    public String getWhere() {
        return where;
    }

    public void setWhere(String where) {
        this.where = where;
    }

    public String getManyToManyWhere() {
        return manyToManyWhere;
    }

    public void setManyToManyWhere(String manyToManyWhere) {
        this.manyToManyWhere = manyToManyWhere;
    }

    public String getManyToManyOrdering() {
        return manyToManyOrderBy;
    }

    public void setManyToManyOrdering(String orderFragment) {
        this.manyToManyOrderBy = orderFragment;
    }

    public boolean isIdentified() {
        return false;
    }

    public boolean hasOrphanDelete() {
        return orphanDelete;
    }

    public void setOrphanDelete(boolean orphanDelete) {
        this.orphanDelete = orphanDelete;
    }

    public int getBatchSize() {
        return batchSize;
    }

    public void setBatchSize(int i) {
        batchSize = i;
    }

    public FetchMode getFetchMode() {
        return fetchMode;
    }

    public void setFetchMode(FetchMode fetchMode) {
        this.fetchMode = fetchMode;
    }

    public void setCollectionPersisterClass(Class persister) {
        this.collectionPersisterClass = persister;
    }

    public Class getCollectionPersisterClass() {
        return collectionPersisterClass;
    }

    public void validate(Mapping mapping) throws MappingException {
        assert getKey() != null : "Collection key not bound : " + getRole();
        assert getElement() != null : "Collection element not bound : " + getRole();

        if (!getKey().isValid(mapping)) {
            throw new MappingException("collection foreign key mapping has wrong number of columns: " + getRole()
                    + " type: " + getKey().getType().getName());
        }
        if (!getElement().isValid(mapping)) {
            throw new MappingException("collection element mapping has wrong number of columns: " + getRole()
                    + " type: " + getElement().getType().getName());
        }

        checkColumnDuplication();
    }

    private void checkColumnDuplication(java.util.Set distinctColumns, Value value) throws MappingException {
        final boolean[] insertability = value.getColumnInsertability();
        final boolean[] updatability = value.getColumnUpdateability();
        final Iterator<Selectable> iterator = value.getColumnIterator();
        int i = 0;
        while (iterator.hasNext()) {
            Selectable s = iterator.next();
            // exclude formulas and coluns that are not insertable or updatable
            // since these values can be be repeated (HHH-5393)
            if (!s.isFormula() && (insertability[i] || updatability[i])) {
                Column col = (Column) s;
                if (!distinctColumns.add(col.getName())) {
                    throw new MappingException("Repeated column in mapping for collection: " + getRole()
                            + " column: " + col.getName());
                }
            }
            i++;
        }
    }

    private void checkColumnDuplication() throws MappingException {
        HashSet cols = new HashSet();
        checkColumnDuplication(cols, getKey());
        if (isIndexed()) {
            checkColumnDuplication(cols, ((IndexedCollection) this).getIndex());
        }
        if (isIdentified()) {
            checkColumnDuplication(cols, ((IdentifierCollection) this).getIdentifier());
        }
        if (!isOneToMany()) {
            checkColumnDuplication(cols, getElement());
        }
    }

    public Iterator<Selectable> getColumnIterator() {
        return Collections.<Selectable>emptyList().iterator();
    }

    public int getColumnSpan() {
        return 0;
    }

    public Type getType() throws MappingException {
        return getCollectionType();
    }

    public CollectionType getCollectionType() {
        if (typeName == null) {
            return getDefaultCollectionType();
        } else {
            return getMetadata().getTypeConfiguration().getTypeResolver().getTypeFactory()
                    .customCollection(typeName, typeParameters, role, referencedPropertyName);
        }
    }

    public boolean isNullable() {
        return true;
    }

    public boolean isAlternateUniqueKey() {
        return false;
    }

    public Table getTable() {
        return owner.getTable();
    }

    public void createForeignKey() {
    }

    public boolean isSimpleValue() {
        return false;
    }

    public boolean isValid(Mapping mapping) throws MappingException {
        return true;
    }

    @Override
    public boolean isSame(Value other) {
        return this == other || other instanceof Collection && isSame((Collection) other);
    }

    protected static boolean isSame(Value v1, Value v2) {
        return v1 == v2 || v1 != null && v2 != null && v1.isSame(v2);
    }

    public boolean isSame(Collection other) {
        return this == other || isSame(key, other.key) && isSame(element, other.element)
                && Objects.equals(collectionTable, other.collectionTable) && Objects.equals(where, other.where)
                && Objects.equals(manyToManyWhere, other.manyToManyWhere)
                && Objects.equals(referencedPropertyName, other.referencedPropertyName)
                && Objects.equals(mappedByProperty, other.mappedByProperty)
                && Objects.equals(typeName, other.typeName) && Objects.equals(typeParameters, other.typeParameters);
    }

    private void createForeignKeys() throws MappingException {
        // if ( !isInverse() ) { // for inverse collections, let the "other end" handle it
        if (referencedPropertyName == null) {
            getElement().createForeignKey();
            key.createForeignKeyOfEntity(getOwner().getEntityName());
        }
        // }
    }

    abstract void createPrimaryKey();

    public void createAllKeys() throws MappingException {
        createForeignKeys();
        if (!isInverse()) {
            createPrimaryKey();
        }
    }

    public String getCacheConcurrencyStrategy() {
        return cacheConcurrencyStrategy;
    }

    public void setCacheConcurrencyStrategy(String cacheConcurrencyStrategy) {
        this.cacheConcurrencyStrategy = cacheConcurrencyStrategy;
    }

    public void setTypeUsingReflection(String className, String propertyName) {
    }

    public String getCacheRegionName() {
        return cacheRegionName == null ? role : cacheRegionName;
    }

    public void setCacheRegionName(String cacheRegionName) {
        this.cacheRegionName = StringHelper.nullIfEmpty(cacheRegionName);
    }

    public void setCustomSQLInsert(String customSQLInsert, boolean callable,
            ExecuteUpdateResultCheckStyle checkStyle) {
        this.customSQLInsert = customSQLInsert;
        this.customInsertCallable = callable;
        this.insertCheckStyle = checkStyle;
    }

    public String getCustomSQLInsert() {
        return customSQLInsert;
    }

    public boolean isCustomInsertCallable() {
        return customInsertCallable;
    }

    public ExecuteUpdateResultCheckStyle getCustomSQLInsertCheckStyle() {
        return insertCheckStyle;
    }

    public void setCustomSQLUpdate(String customSQLUpdate, boolean callable,
            ExecuteUpdateResultCheckStyle checkStyle) {
        this.customSQLUpdate = customSQLUpdate;
        this.customUpdateCallable = callable;
        this.updateCheckStyle = checkStyle;
    }

    public String getCustomSQLUpdate() {
        return customSQLUpdate;
    }

    public boolean isCustomUpdateCallable() {
        return customUpdateCallable;
    }

    public ExecuteUpdateResultCheckStyle getCustomSQLUpdateCheckStyle() {
        return updateCheckStyle;
    }

    public void setCustomSQLDelete(String customSQLDelete, boolean callable,
            ExecuteUpdateResultCheckStyle checkStyle) {
        this.customSQLDelete = customSQLDelete;
        this.customDeleteCallable = callable;
        this.deleteCheckStyle = checkStyle;
    }

    public String getCustomSQLDelete() {
        return customSQLDelete;
    }

    public boolean isCustomDeleteCallable() {
        return customDeleteCallable;
    }

    public ExecuteUpdateResultCheckStyle getCustomSQLDeleteCheckStyle() {
        return deleteCheckStyle;
    }

    public void setCustomSQLDeleteAll(String customSQLDeleteAll, boolean callable,
            ExecuteUpdateResultCheckStyle checkStyle) {
        this.customSQLDeleteAll = customSQLDeleteAll;
        this.customDeleteAllCallable = callable;
        this.deleteAllCheckStyle = checkStyle;
    }

    public String getCustomSQLDeleteAll() {
        return customSQLDeleteAll;
    }

    public boolean isCustomDeleteAllCallable() {
        return customDeleteAllCallable;
    }

    public ExecuteUpdateResultCheckStyle getCustomSQLDeleteAllCheckStyle() {
        return deleteAllCheckStyle;
    }

    public void addFilter(String name, String condition, boolean autoAliasInjection,
            java.util.Map<String, String> aliasTableMap, java.util.Map<String, String> aliasEntityMap) {
        filters.add(
                new FilterConfiguration(name, condition, autoAliasInjection, aliasTableMap, aliasEntityMap, null));
    }

    public java.util.List getFilters() {
        return filters;
    }

    public void addManyToManyFilter(String name, String condition, boolean autoAliasInjection,
            java.util.Map<String, String> aliasTableMap, java.util.Map<String, String> aliasEntityMap) {
        manyToManyFilters.add(
                new FilterConfiguration(name, condition, autoAliasInjection, aliasTableMap, aliasEntityMap, null));
    }

    public java.util.List getManyToManyFilters() {
        return manyToManyFilters;
    }

    @Override
    public String toString() {
        return getClass().getName() + '(' + getRole() + ')';
    }

    public java.util.Set<String> getSynchronizedTables() {
        return synchronizedTables;
    }

    public String getLoaderName() {
        return loaderName;
    }

    public void setLoaderName(String name) {
        this.loaderName = name;
    }

    public String getReferencedPropertyName() {
        return referencedPropertyName;
    }

    public void setReferencedPropertyName(String propertyRef) {
        this.referencedPropertyName = propertyRef;
    }

    public boolean isOptimisticLocked() {
        return optimisticLocked;
    }

    public void setOptimisticLocked(boolean optimisticLocked) {
        this.optimisticLocked = optimisticLocked;
    }

    public boolean isMap() {
        return false;
    }

    public String getTypeName() {
        return typeName;
    }

    public void setTypeName(String typeName) {
        this.typeName = typeName;
    }

    public Properties getTypeParameters() {
        return typeParameters;
    }

    public void setTypeParameters(Properties parameterMap) {
        this.typeParameters = parameterMap;
    }

    public void setTypeParameters(java.util.Map parameterMap) {
        if (parameterMap instanceof Properties) {
            this.typeParameters = (Properties) parameterMap;
        } else {
            this.typeParameters = new Properties();
            typeParameters.putAll(parameterMap);
        }
    }

    public boolean[] getColumnInsertability() {
        return ArrayHelper.EMPTY_BOOLEAN_ARRAY;
    }

    public boolean[] getColumnUpdateability() {
        return ArrayHelper.EMPTY_BOOLEAN_ARRAY;
    }

    public boolean isSubselectLoadable() {
        return subselectLoadable;
    }

    public void setSubselectLoadable(boolean subqueryLoadable) {
        this.subselectLoadable = subqueryLoadable;
    }

    public boolean isMutable() {
        return mutable;
    }

    public void setMutable(boolean mutable) {
        this.mutable = mutable;
    }

    public boolean isExtraLazy() {
        return extraLazy;
    }

    public void setExtraLazy(boolean extraLazy) {
        this.extraLazy = extraLazy;
    }

    public boolean hasOrder() {
        return orderBy != null || manyToManyOrderBy != null;
    }

    public void setComparatorClassName(String comparatorClassName) {
        this.comparatorClassName = comparatorClassName;
    }

    public String getComparatorClassName() {
        return comparatorClassName;
    }

    public String getMappedByProperty() {
        return mappedByProperty;
    }

    public void setMappedByProperty(String mappedByProperty) {
        this.mappedByProperty = mappedByProperty;
    }
}