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