Search in sources :

Example 11 with QueryableCollection

use of org.hibernate.persister.collection.QueryableCollection in project hibernate-orm by hibernate.

the class LoadQueryJoinAndFetchProcessor method processCollectionFetch.

private void processCollectionFetch(SelectStatementBuilder selectStatementBuilder, FetchSource fetchSource, CollectionAttributeFetch fetch, ReaderCollector readerCollector, FetchStatsImpl fetchStats) {
    fetchStats.processingFetch(fetch);
    if (!FetchStrategyHelper.isJoinFetched(fetch.getFetchStrategy())) {
        // not join fetched, so nothing else to do
        return;
    }
    final CollectionReferenceAliases aliases = aliasResolutionContext.resolveCollectionReferenceAliases(fetch.getQuerySpaceUid());
    final QueryableCollection queryableCollection = (QueryableCollection) fetch.getCollectionPersister();
    final Joinable joinableCollection = (Joinable) fetch.getCollectionPersister();
    if (fetch.getCollectionPersister().isManyToMany()) {
        // todo : better way to access `ownerTableAlias` here.
        // 		when processing the Join part of this we are able to look up the "lhs table alias" because we know
        // 		the 'lhs' QuerySpace.
        //
        // Good idea to be able resolve a Join by lookup on the rhs and lhs uid?  If so, Fetch
        // for many-to-many we have 3 table aliases.  By way of example, consider a normal m-n: User<->Role
        // where User is the FetchOwner and Role (User.roles) is the Fetch.  We'd have:
        //		1) the owner's table : user
        final String ownerTableAlias = aliasResolutionContext.resolveSqlTableAliasFromQuerySpaceUid(fetchSource.getQuerySpaceUid());
        //		2) the m-n table : user_role
        final String collectionTableAlias = aliases.getCollectionTableAlias();
        //		3) the element table : role
        final String elementTableAlias = aliases.getElementTableAlias();
        // add select fragments from the collection table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        selectStatementBuilder.appendSelectClauseFragment(joinableCollection.selectFragment((Joinable) queryableCollection.getElementPersister(), elementTableAlias, collectionTableAlias, aliases.getEntityElementAliases().getColumnAliases().getSuffix(), aliases.getCollectionColumnAliases().getSuffix(), true));
        // add select fragments from the element entity table ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        final OuterJoinLoadable elementPersister = (OuterJoinLoadable) queryableCollection.getElementPersister();
        selectStatementBuilder.appendSelectClauseFragment(elementPersister.selectFragment(elementTableAlias, aliases.getEntityElementAliases().getColumnAliases().getSuffix()));
        // add SQL ORDER-BY fragments
        final String manyToManyOrdering = queryableCollection.getManyToManyOrderByString(elementTableAlias);
        if (StringHelper.isNotEmpty(manyToManyOrdering)) {
            selectStatementBuilder.appendOrderByFragment(manyToManyOrdering);
        }
        final String ordering = queryableCollection.getSQLOrderByString(collectionTableAlias);
        if (StringHelper.isNotEmpty(ordering)) {
            selectStatementBuilder.appendOrderByFragment(ordering);
        }
        readerCollector.add(new EntityReferenceInitializerImpl((EntityReference) fetch.getElementGraph(), aliasResolutionContext.resolveEntityReferenceAliases(fetch.getElementGraph().getQuerySpaceUid())));
    } else {
        // select the "collection columns"
        selectStatementBuilder.appendSelectClauseFragment(queryableCollection.selectFragment(aliases.getElementTableAlias(), aliases.getCollectionColumnAliases().getSuffix()));
        if (fetch.getCollectionPersister().isOneToMany()) {
            // if the collection elements are entities, select the entity columns as well
            final OuterJoinLoadable elementPersister = (OuterJoinLoadable) queryableCollection.getElementPersister();
            selectStatementBuilder.appendSelectClauseFragment(elementPersister.selectFragment(aliases.getElementTableAlias(), aliases.getEntityElementAliases().getColumnAliases().getSuffix()));
            readerCollector.add(new EntityReferenceInitializerImpl((EntityReference) fetch.getElementGraph(), aliasResolutionContext.resolveEntityReferenceAliases(fetch.getElementGraph().getQuerySpaceUid())));
        }
        final String ordering = queryableCollection.getSQLOrderByString(aliases.getElementTableAlias());
        if (StringHelper.isNotEmpty(ordering)) {
            selectStatementBuilder.appendOrderByFragment(ordering);
        }
    }
    if (fetch.getElementGraph() != null) {
        processFetches(fetch.getElementGraph(), selectStatementBuilder, readerCollector);
    }
    readerCollector.add(new CollectionReferenceInitializerImpl(fetch, aliases));
}
Also used : OuterJoinLoadable(org.hibernate.persister.entity.OuterJoinLoadable) Joinable(org.hibernate.persister.entity.Joinable) EntityReferenceInitializerImpl(org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl) EntityReference(org.hibernate.loader.plan.spi.EntityReference) CollectionReferenceAliases(org.hibernate.loader.plan.exec.spi.CollectionReferenceAliases) QueryableCollection(org.hibernate.persister.collection.QueryableCollection) CollectionReferenceInitializerImpl(org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl)

Example 12 with QueryableCollection

use of org.hibernate.persister.collection.QueryableCollection in project hibernate-orm by hibernate.

the class OrderByTest method testInverseIndex.

@Test
@TestForIssue(jiraKey = "HHH-5732")
public void testInverseIndex() {
    final CollectionPersister transactionsPersister = sessionFactory().getCollectionPersister(BankAccount.class.getName() + ".transactions");
    assertTrue(transactionsPersister.isInverse());
    Session s = openSession();
    s.getTransaction().begin();
    BankAccount account = new BankAccount();
    account.addTransaction("zzzzz");
    account.addTransaction("aaaaa");
    account.addTransaction("mmmmm");
    s.save(account);
    s.getTransaction().commit();
    s.close();
    s = openSession();
    s.getTransaction().begin();
    try {
        final QueryableCollection queryableCollection = (QueryableCollection) transactionsPersister;
        SimpleSelect select = new SimpleSelect(getDialect()).setTableName(queryableCollection.getTableName()).addColumn("code").addColumn("transactions_index");
        PreparedStatement preparedStatement = ((SessionImplementor) s).getJdbcCoordinator().getStatementPreparer().prepareStatement(select.toStatementString());
        ResultSet resultSet = ((SessionImplementor) s).getJdbcCoordinator().getResultSetReturn().extract(preparedStatement);
        Map<Integer, String> valueMap = new HashMap<Integer, String>();
        while (resultSet.next()) {
            final String code = resultSet.getString(1);
            assertFalse("code column was null", resultSet.wasNull());
            final int indx = resultSet.getInt(2);
            assertFalse("List index column was null", resultSet.wasNull());
            valueMap.put(indx, code);
        }
        assertEquals(3, valueMap.size());
        assertEquals("zzzzz", valueMap.get(0));
        assertEquals("aaaaa", valueMap.get(1));
        assertEquals("mmmmm", valueMap.get(2));
    } catch (SQLException e) {
        fail(e.getMessage());
    } finally {
        s.getTransaction().rollback();
        s.close();
    }
}
Also used : HashMap(java.util.HashMap) SQLException(java.sql.SQLException) QueryableCollection(org.hibernate.persister.collection.QueryableCollection) PreparedStatement(java.sql.PreparedStatement) CollectionPersister(org.hibernate.persister.collection.CollectionPersister) ResultSet(java.sql.ResultSet) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) SimpleSelect(org.hibernate.sql.SimpleSelect) Session(org.hibernate.Session) Test(org.junit.Test) TestForIssue(org.hibernate.testing.TestForIssue)

Example 13 with QueryableCollection

use of org.hibernate.persister.collection.QueryableCollection in project hibernate-orm by hibernate.

the class PersistentListTest method testInverseListIndex.

@Test
@TestForIssue(jiraKey = "HHH-5732")
public void testInverseListIndex() {
    // make sure no one changes the mapping
    final CollectionPersister collectionPersister = sessionFactory().getCollectionPersister(ListOwner.class.getName() + ".children");
    assertTrue(collectionPersister.isInverse());
    // do some creations...
    Session session = openSession();
    session.beginTransaction();
    ListOwner root = new ListOwner("root");
    ListOwner child1 = new ListOwner("c1");
    root.getChildren().add(child1);
    child1.setParent(root);
    ListOwner child2 = new ListOwner("c2");
    root.getChildren().add(child2);
    child2.setParent(root);
    session.save(root);
    session.getTransaction().commit();
    session.close();
    // now, make sure the list-index column gotten written...
    final Session session2 = openSession();
    session2.beginTransaction();
    session2.doWork(new Work() {

        @Override
        public void execute(Connection connection) throws SQLException {
            final QueryableCollection queryableCollection = (QueryableCollection) collectionPersister;
            SimpleSelect select = new SimpleSelect(getDialect()).setTableName(queryableCollection.getTableName()).addColumn("NAME").addColumn("LIST_INDEX").addCondition("NAME", "<>", "?");
            PreparedStatement preparedStatement = ((SessionImplementor) session2).getJdbcCoordinator().getStatementPreparer().prepareStatement(select.toStatementString());
            preparedStatement.setString(1, "root");
            ResultSet resultSet = ((SessionImplementor) session2).getJdbcCoordinator().getResultSetReturn().extract(preparedStatement);
            Map<String, Integer> valueMap = new HashMap<String, Integer>();
            while (resultSet.next()) {
                final String name = resultSet.getString(1);
                assertFalse("NAME column was null", resultSet.wasNull());
                final int position = resultSet.getInt(2);
                assertFalse("LIST_INDEX column was null", resultSet.wasNull());
                valueMap.put(name, position);
            }
            assertEquals(2, valueMap.size());
            // c1 should be list index 0
            assertEquals(Integer.valueOf(0), valueMap.get("c1"));
            // c2 should be list index 1
            assertEquals(Integer.valueOf(1), valueMap.get("c2"));
        }
    });
    session2.delete(root);
    session2.getTransaction().commit();
    session2.close();
}
Also used : SQLException(java.sql.SQLException) Connection(java.sql.Connection) QueryableCollection(org.hibernate.persister.collection.QueryableCollection) PreparedStatement(java.sql.PreparedStatement) CollectionPersister(org.hibernate.persister.collection.CollectionPersister) Work(org.hibernate.jdbc.Work) ResultSet(java.sql.ResultSet) SimpleSelect(org.hibernate.sql.SimpleSelect) HashMap(java.util.HashMap) Map(java.util.Map) Session(org.hibernate.Session) Test(org.junit.Test) TestForIssue(org.hibernate.testing.TestForIssue)

Example 14 with QueryableCollection

use of org.hibernate.persister.collection.QueryableCollection in project hibernate-orm by hibernate.

the class EntityGraphQueryHint method getFromElements.

private List<FromElement> getFromElements(List attributeNodes, FromElement origin, FromClause fromClause, HqlSqlWalker walker, Map<String, FromElement> explicitFetches) {
    final List<FromElement> fromElements = new ArrayList<FromElement>();
    for (Object obj : attributeNodes) {
        final AttributeNode<?> attributeNode = (AttributeNode<?>) obj;
        final String attributeName = attributeNode.getAttributeName();
        final String className = origin.getClassName();
        // TODO: This is ignored by collection types and probably wrong for entity types.  Presumably it screws
        // with inheritance.
        final String role = className + "." + attributeName;
        final String classAlias = origin.getClassAlias();
        final String originTableAlias = origin.getTableAlias();
        final Type propertyType = origin.getPropertyType(attributeName, attributeName);
        try {
            FromElement fromElement = explicitFetches.get(role);
            boolean explicitFromElement = false;
            if (fromElement == null) {
                if (propertyType.isEntityType()) {
                    final EntityType entityType = (EntityType) propertyType;
                    final String[] columns = origin.toColumns(originTableAlias, attributeName, false);
                    final String tableAlias = walker.getAliasGenerator().createName(entityType.getAssociatedEntityName());
                    final FromElementFactory fromElementFactory = new FromElementFactory(fromClause, origin, attributeName, classAlias, columns, false);
                    final JoinSequence joinSequence = walker.getSessionFactoryHelper().createJoinSequence(false, entityType, tableAlias, JoinType.LEFT_OUTER_JOIN, columns);
                    fromElement = fromElementFactory.createEntityJoin(entityType.getAssociatedEntityName(), tableAlias, joinSequence, true, walker.isInFrom(), entityType, role, null);
                } else if (propertyType.isCollectionType()) {
                    CollectionType collectionType = (CollectionType) propertyType;
                    final String[] columns = origin.toColumns(originTableAlias, attributeName, false);
                    final FromElementFactory fromElementFactory = new FromElementFactory(fromClause, origin, attributeName, classAlias, columns, false);
                    final QueryableCollection queryableCollection = walker.getSessionFactoryHelper().requireQueryableCollection(collectionType.getRole());
                    fromElement = fromElementFactory.createCollection(queryableCollection, collectionType.getRole(), JoinType.LEFT_OUTER_JOIN, true, false);
                }
            } else {
                explicitFromElement = true;
                fromElement.setInProjectionList(true);
                fromElement.setFetch(true);
            }
            if (fromElement != null) {
                if (!explicitFromElement) {
                    fromElements.add(fromElement);
                }
                // recurse into subgraphs
                for (Subgraph<?> subgraph : attributeNode.getSubgraphs().values()) {
                    fromElements.addAll(getFromElements(subgraph.getAttributeNodes(), fromElement, fromClause, walker, explicitFetches));
                }
            }
        } catch (Exception e) {
            throw new QueryException("Could not apply the EntityGraph to the Query!", e);
        }
    }
    return fromElements;
}
Also used : AttributeNode(javax.persistence.AttributeNode) ArrayList(java.util.ArrayList) QueryableCollection(org.hibernate.persister.collection.QueryableCollection) QueryException(org.hibernate.QueryException) EntityType(org.hibernate.type.EntityType) JoinType(org.hibernate.sql.JoinType) CollectionType(org.hibernate.type.CollectionType) EntityType(org.hibernate.type.EntityType) Type(org.hibernate.type.Type) QueryException(org.hibernate.QueryException) ImpliedFromElement(org.hibernate.hql.internal.ast.tree.ImpliedFromElement) FromElement(org.hibernate.hql.internal.ast.tree.FromElement) CollectionType(org.hibernate.type.CollectionType) FromElementFactory(org.hibernate.hql.internal.ast.tree.FromElementFactory) JoinSequence(org.hibernate.engine.internal.JoinSequence)

Example 15 with QueryableCollection

use of org.hibernate.persister.collection.QueryableCollection in project hibernate-orm by hibernate.

the class AttributeNodeImpl method internalMakeSubgraph.

@SuppressWarnings("unchecked")
private <X> SubgraphImpl<X> internalMakeSubgraph(Class<X> type) {
    if (attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.BASIC || attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED) {
        throw new IllegalArgumentException(String.format("Attribute [%s] is not of managed type", getAttributeName()));
    }
    if (attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.ELEMENT_COLLECTION) {
        throw new IllegalArgumentException(String.format("Collection elements [%s] is not of managed type", getAttributeName()));
    }
    if (subgraphMap == null) {
        subgraphMap = new HashMap<>();
    }
    final Helper.AttributeSource attributeSource = Helper.resolveAttributeSource(sessionFactory(), managedType);
    final AssociationType attributeType = (AssociationType) attributeSource.findType(attribute.getName());
    final Joinable joinable = attributeType.getAssociatedJoinable(sessionFactory());
    if (joinable.isCollection()) {
        final EntityPersister elementEntityPersister = ((QueryableCollection) joinable).getElementPersister();
        if (type == null) {
            type = elementEntityPersister.getMappedClass();
        } else {
            if (!isTreatableAs(elementEntityPersister, type)) {
                throw new IllegalArgumentException(String.format("Collection elements [%s] cannot be treated as requested type [%s] : %s", getAttributeName(), type.getName(), elementEntityPersister.getMappedClass().getName()));
            }
        }
    } else {
        final EntityPersister entityPersister = (EntityPersister) joinable;
        if (type == null) {
            type = entityPersister.getMappedClass();
        } else {
            if (!isTreatableAs(entityPersister, type)) {
                throw new IllegalArgumentException(String.format("Attribute [%s] cannot be treated as requested type [%s] : %s", getAttributeName(), type.getName(), entityPersister.getMappedClass().getName()));
            }
        }
    }
    ManagedType managedType = null;
    try {
        managedType = sessionFactory.getMetamodel().entity(type.getName());
    } catch (IllegalArgumentException e) {
    // do nothing
    }
    if (managedType == null) {
        managedType = attribute.getDeclaringType();
    }
    final SubgraphImpl<X> subgraph = new SubgraphImpl<>(this.sessionFactory, managedType, type);
    subgraphMap.put(type, subgraph);
    return subgraph;
}
Also used : CollectionHelper(org.hibernate.internal.util.collections.CollectionHelper) Helper(org.hibernate.metamodel.internal.Helper) EntityPersister(org.hibernate.persister.entity.EntityPersister) ManagedType(javax.persistence.metamodel.ManagedType) AssociationType(org.hibernate.type.AssociationType) Joinable(org.hibernate.persister.entity.Joinable) QueryableCollection(org.hibernate.persister.collection.QueryableCollection)

Aggregations

QueryableCollection (org.hibernate.persister.collection.QueryableCollection)33 Type (org.hibernate.type.Type)10 QueryException (org.hibernate.QueryException)9 AssociationType (org.hibernate.type.AssociationType)7 JoinSequence (org.hibernate.engine.internal.JoinSequence)6 Joinable (org.hibernate.persister.entity.Joinable)6 JoinType (org.hibernate.sql.JoinType)6 CollectionType (org.hibernate.type.CollectionType)6 EntityPersister (org.hibernate.persister.entity.EntityPersister)5 HashMap (java.util.HashMap)4 CollectionPersister (org.hibernate.persister.collection.CollectionPersister)4 OuterJoinLoadable (org.hibernate.persister.entity.OuterJoinLoadable)4 EntityType (org.hibernate.type.EntityType)4 SemanticException (antlr.SemanticException)3 PreparedStatement (java.sql.PreparedStatement)3 ResultSet (java.sql.ResultSet)3 SQLException (java.sql.SQLException)3 Map (java.util.Map)3 Session (org.hibernate.Session)3 SessionFactoryImplementor (org.hibernate.engine.spi.SessionFactoryImplementor)3