Search in sources :

Example 6 with JoinTable

use of com.blazebit.persistence.spi.JoinTable in project blaze-persistence by Blazebit.

the class HibernateJpaProvider method createJoinTable.

private JoinTable createJoinTable(EntityType<?> ownerType, QueryableCollection queryableCollection, Map<String, String> targetColumnMapping, Set<String> targetIdAttributeNames, String attributeName) {
    String[] indexColumnNames = queryableCollection.getIndexColumnNames();
    Map<String, String> keyColumnMapping = null;
    Map<String, String> keyColumnTypes = null;
    if (indexColumnNames != null) {
        keyColumnMapping = new LinkedHashMap<>(indexColumnNames.length);
        keyColumnTypes = new LinkedHashMap<>(indexColumnNames.length);
        if (queryableCollection.getKeyType().isEntityType()) {
            throw new IllegalArgumentException("Determining the join table key foreign key mappings is not yet supported!");
        } else {
            keyColumnMapping.put(indexColumnNames[0], indexColumnNames[0]);
            keyColumnTypes.put(indexColumnNames[0], getColumnTypeForPropertyType(ownerType, attributeName, queryableCollection.getFactory(), queryableCollection.getIndexType())[0]);
        }
    }
    AbstractEntityPersister ownerEntityPersister = (AbstractEntityPersister) queryableCollection.getOwnerEntityPersister();
    String[] primaryKeyColumnMetaData;
    if (queryableCollection.getKeyType() instanceof EmbeddedComponentType) {
        String[] propertyNames = ((EmbeddedComponentType) queryableCollection.getKeyType()).getPropertyNames();
        List<String> columnNames = new ArrayList<>(propertyNames.length);
        for (String propertyName : propertyNames) {
            for (String propertyColumnName : getColumnNames(ownerEntityPersister, propertyName)) {
                columnNames.add(propertyColumnName);
            }
        }
        primaryKeyColumnMetaData = columnNames.toArray(new String[columnNames.size()]);
    } else {
        primaryKeyColumnMetaData = ownerEntityPersister.getKeyColumnNames();
    }
    String[] foreignKeyColumnMetaData = queryableCollection.getKeyColumnNames();
    Map<String, String> idColumnMapping = new LinkedHashMap<>(primaryKeyColumnMetaData.length);
    for (int i = 0; i < foreignKeyColumnMetaData.length; i++) {
        idColumnMapping.put(foreignKeyColumnMetaData[i], primaryKeyColumnMetaData[i]);
    }
    Set<String> idAttributeNames = getColumnMatchingAttributeNames(ownerEntityPersister, Arrays.asList(primaryKeyColumnMetaData));
    if (targetIdAttributeNames == null) {
        Type elementType = queryableCollection.getElementType();
        if (elementType instanceof ComponentType) {
            targetIdAttributeNames = new LinkedHashSet<>();
            collectPropertyNames(targetIdAttributeNames, null, elementType, queryableCollection.getFactory());
        }
    }
    return new JoinTable(queryableCollection.getTableName(), idAttributeNames, idColumnMapping, keyColumnMapping, keyColumnTypes, targetIdAttributeNames, targetColumnMapping);
}
Also used : EmbeddedComponentType(org.hibernate.type.EmbeddedComponentType) ComponentType(org.hibernate.type.ComponentType) EmbeddedComponentType(org.hibernate.type.EmbeddedComponentType) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) ManyToOneType(org.hibernate.type.ManyToOneType) OneToOneType(org.hibernate.type.OneToOneType) IdentifiableType(javax.persistence.metamodel.IdentifiableType) JoinType(com.blazebit.persistence.JoinType) ManagedType(javax.persistence.metamodel.ManagedType) EnhancedUserType(org.hibernate.usertype.EnhancedUserType) CustomType(org.hibernate.type.CustomType) CollectionType(org.hibernate.type.CollectionType) EmbeddedComponentType(org.hibernate.type.EmbeddedComponentType) EntityType(javax.persistence.metamodel.EntityType) ComponentType(org.hibernate.type.ComponentType) CompositeType(org.hibernate.type.CompositeType) AssociationType(org.hibernate.type.AssociationType) Type(org.hibernate.type.Type) AbstractEntityPersister(org.hibernate.persister.entity.AbstractEntityPersister) JoinTable(com.blazebit.persistence.spi.JoinTable)

Example 7 with JoinTable

use of com.blazebit.persistence.spi.JoinTable in project blaze-persistence by Blazebit.

the class AbstractPersistenceTest method getRelationalModelAccessor.

@Override
protected RelationalModelAccessor getRelationalModelAccessor() {
    return new RelationalModelAccessor() {

        @Override
        public String tableFromEntity(Class<?> entityClass) {
            SessionImplementor session = em.unwrap(SessionImplementor.class);
            AbstractEntityPersister persister = (AbstractEntityPersister) session.getFactory().getEntityPersister(entityClass.getName());
            return persister.getTableName().substring(persister.getTableName().lastIndexOf('.') + 1);
        }

        @Override
        public String tableFromEntityRelation(Class<?> entityClass, String relationName) {
            JoinTable joinTable = jpaProvider.getJoinTable(em.getMetamodel().entity(entityClass), relationName);
            if (joinTable != null) {
                return joinTable.getTableName().substring(joinTable.getTableName().lastIndexOf('.') + 1);
            }
            return null;
        }
    };
}
Also used : RelationalModelAccessor(com.blazebit.persistence.testsuite.base.jpa.RelationalModelAccessor) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) AbstractEntityPersister(org.hibernate.persister.entity.AbstractEntityPersister) JoinTable(com.blazebit.persistence.spi.JoinTable)

Example 8 with JoinTable

use of com.blazebit.persistence.spi.JoinTable in project blaze-persistence by Blazebit.

the class AbstractJpaPersistenceTest method clearCollections.

protected void clearCollections(EntityManager em, Class<?>... entityClasses) {
    for (Class<?> c : entityClasses) {
        List<String> deletes = PLURAL_DELETES.get(c);
        if (deletes == null) {
            Metamodel entityMetamodel = cbf.getService(Metamodel.class);
            EntityType<?> t = entityMetamodel.entity(c);
            deletes = new ArrayList<>();
            for (PluralAttribute<?, ?, ?> pluralAttribute : t.getPluralAttributes()) {
                JoinTable joinTable = jpaProvider.getJoinTable(t, pluralAttribute.getName());
                if (joinTable != null) {
                    deletes.add("delete from " + joinTable.getTableName());
                }
            }
            PLURAL_DELETES.put(c, deletes);
        }
        for (String delete : deletes) {
            em.createNativeQuery(delete).executeUpdate();
        }
    }
}
Also used : Metamodel(javax.persistence.metamodel.Metamodel) JoinTable(com.blazebit.persistence.spi.JoinTable)

Example 9 with JoinTable

use of com.blazebit.persistence.spi.JoinTable in project blaze-persistence by Blazebit.

the class AbstractModificationCriteriaBuilder method getReturningColumns.

private String[] getReturningColumns(List<List<Attribute<?, ?>>> attributes) {
    List<String> columns = new ArrayList<String>(attributes.size());
    StringBuilder sb = new StringBuilder();
    for (List<Attribute<?, ?>> returningAttribute : attributes) {
        JoinTable joinTable = null;
        // To support this, we need to retrieve the columns from the join table
        for (int i = 0; i < returningAttribute.size(); i++) {
            sb.append(returningAttribute.get(i).getName()).append('.');
            if (returningAttribute.get(i).isCollection()) {
                sb.setLength(sb.length() - 1);
                joinTable = mainQuery.metamodel.getManagedType(ExtendedManagedType.class, entityType).getAttribute(sb.toString()).getJoinTable();
                sb.setLength(0);
            }
        }
        sb.setLength(sb.length() - 1);
        if (joinTable == null) {
            for (String column : mainQuery.metamodel.getManagedType(ExtendedManagedType.class, entityType).getAttribute(sb.toString()).getColumnNames()) {
                columns.add(column);
            }
        } else {
            // The id columns are the only allowed objects that can be returned
            for (String column : joinTable.getTargetColumnMappings().keySet()) {
                columns.add(column);
            }
        }
        sb.setLength(0);
    }
    return columns.toArray(new String[columns.size()]);
}
Also used : SingularAttribute(javax.persistence.metamodel.SingularAttribute) Attribute(javax.persistence.metamodel.Attribute) ExtendedAttribute(com.blazebit.persistence.spi.ExtendedAttribute) ArrayList(java.util.ArrayList) JoinTable(com.blazebit.persistence.spi.JoinTable) ExtendedManagedType(com.blazebit.persistence.spi.ExtendedManagedType)

Example 10 with JoinTable

use of com.blazebit.persistence.spi.JoinTable in project blaze-persistence by Blazebit.

the class AbstractUpdateCollectionCriteriaBuilder method getQuerySpecification.

private <R> QuerySpecification getQuerySpecification(Query baseQuery, Query exampleQuery, String[] returningColumns, ReturningObjectBuilder<R> objectBuilder, Map<DbmsModificationState, String> includedModificationStates) {
    Set<String> parameterListNames = parameterManager.getParameterListNames(baseQuery);
    boolean isEmbedded = this instanceof ReturningBuilder;
    boolean shouldRenderCteNodes = renderCteNodes(isEmbedded);
    List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(isEmbedded) : Collections.EMPTY_LIST;
    ExtendedQuerySupport extendedQuerySupport = getService(ExtendedQuerySupport.class);
    String sql = extendedQuerySupport.getSql(em, baseQuery);
    String ownerAlias = extendedQuerySupport.getSqlAlias(em, baseQuery, entityAlias);
    String targetAlias = extendedQuerySupport.getSqlAlias(em, baseQuery, JoinManager.COLLECTION_DML_BASE_QUERY_ALIAS);
    JoinTable joinTable = collectionAttribute.getJoinTable();
    int joinTableIndex = SqlUtils.indexOfTableName(sql, joinTable.getTableName());
    String collectionAlias = SqlUtils.extractAlias(sql, joinTableIndex + joinTable.getTableName().length());
    String tableToUpdate = joinTable.getTableName();
    String tablePrefix;
    if (mainQuery.dbmsDialect.getUpdateJoinStyle() == UpdateJoinStyle.FROM_ALIAS) {
        tablePrefix = collectionAlias;
    } else if (mainQuery.dbmsDialect.getUpdateJoinStyle() == UpdateJoinStyle.FROM) {
        tablePrefix = null;
    } else {
        tablePrefix = tableToUpdate;
    }
    List<String> setColumns = getSetColumns();
    // Prepare a Map<EntityAlias.idColumnName, CollectionAlias.idColumnName>
    // This is used to replace references to id columns properly in the final sql query
    Map<String, String> columnExpressionRemappings = new HashMap<>();
    List<String> joinTableIdColumns = new ArrayList<>();
    String[] discriminatorColumnCheck = mainQuery.jpaProvider.getDiscriminatorColumnCheck(entityType);
    String discriminatorPredicate = "";
    if (discriminatorColumnCheck != null) {
        discriminatorPredicate = ownerAlias + "." + discriminatorColumnCheck[0] + "=" + discriminatorColumnCheck[1] + " and";
        columnExpressionRemappings.put(ownerAlias + "." + discriminatorColumnCheck[0] + "=" + discriminatorColumnCheck[1], "1=1");
    }
    if (joinTable.getKeyColumnMappings() != null) {
        for (Map.Entry<String, String> entry : joinTable.getKeyColumnMappings().entrySet()) {
            joinTableIdColumns.add(entry.getKey());
            String sourceExpression = CollectionDmlSupportFunction.FUNCTION_NAME + "(" + collectionAlias + "." + entry.getValue() + ")";
            if (tablePrefix == null) {
                columnExpressionRemappings.put(sourceExpression, collectionAlias + "." + entry.getValue());
            } else {
                columnExpressionRemappings.put(sourceExpression, tablePrefix + "." + entry.getKey());
            }
        }
    }
    for (Map.Entry<String, String> entry : joinTable.getIdColumnMappings().entrySet()) {
        joinTableIdColumns.add(entry.getKey());
        String sourceExpression = CollectionDmlSupportFunction.FUNCTION_NAME + "(" + ownerAlias + "." + entry.getValue() + ")";
        if (tablePrefix == null) {
            columnExpressionRemappings.put(sourceExpression, ownerAlias + "." + entry.getValue());
        } else {
            columnExpressionRemappings.put(sourceExpression, tablePrefix + "." + entry.getKey());
        }
    }
    for (Map.Entry<String, String> entry : joinTable.getTargetColumnMappings().entrySet()) {
        String sourceExpression = CollectionDmlSupportFunction.FUNCTION_NAME + "(" + targetAlias + "." + entry.getValue() + ")";
        if (tablePrefix == null) {
            columnExpressionRemappings.put(sourceExpression, targetAlias + "." + entry.getValue());
        } else {
            columnExpressionRemappings.put(sourceExpression, tablePrefix + "." + entry.getKey());
        }
    }
    // If the id attribute is an embedded type, there is the possibility that row value expressions are used which we need to handle as well
    Set<SingularAttribute<?, ?>> idAttributes = JpaMetamodelUtils.getIdAttributes(entityType);
    if (idAttributes.size() == 1 && idAttributes.iterator().next().getType() instanceof ManagedType<?>) {
        StringBuilder leftSb = new StringBuilder();
        StringBuilder rightSb = new StringBuilder();
        leftSb.append(CollectionDmlSupportFunction.FUNCTION_NAME).append("((");
        rightSb.append("(");
        for (Map.Entry<String, String> entry : joinTable.getIdColumnMappings().entrySet()) {
            leftSb.append(ownerAlias).append('.').append(entry.getValue()).append(", ");
            if (tablePrefix == null) {
                rightSb.append(ownerAlias).append('.').append(entry.getValue()).append(',');
            } else {
                rightSb.append(tablePrefix).append('.').append(entry.getKey()).append(',');
            }
        }
        leftSb.setLength(leftSb.length() - 2);
        leftSb.append("))");
        rightSb.setCharAt(rightSb.length() - 1, ')');
        columnExpressionRemappings.put(leftSb.toString(), rightSb.toString());
    }
    Map<String, String> aliasMapping = new TreeMap<>();
    if (mainQuery.dbmsDialect.getPhysicalRowId() != null) {
        joinTableIdColumns.clear();
        joinTableIdColumns.add(mainQuery.dbmsDialect.getPhysicalRowId());
    }
    for (String idColumn : joinTableIdColumns) {
        aliasMapping.put(collectionAlias + "." + idColumn, "tmp.c" + aliasMapping.size());
    }
    SqlUtils.buildAliasMappingForTopLevelSelects(extendedQuerySupport.getSql(em, baseQuery), "tmp", aliasMapping);
    return new CollectionUpdateModificationQuerySpecification(this, baseQuery, exampleQuery, parameterManager.getParameterImpls(), parameterListNames, mainQuery.cteManager.isRecursive(), ctes, shouldRenderCteNodes, isEmbedded, returningColumns, objectBuilder, includedModificationStates, returningAttributeBindingMap, mainQuery.getQueryConfiguration().isQueryPlanCacheEnabled(), tableToUpdate, collectionAlias, joinTableIdColumns.toArray(new String[0]), setColumns, getForeignKeyParticipatingQueries(), aliasMapping, getUpdateExampleQuery(), columnExpressionRemappings);
}
Also used : ReturningBuilder(com.blazebit.persistence.ReturningBuilder) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) TreeMap(java.util.TreeMap) CollectionUpdateModificationQuerySpecification(com.blazebit.persistence.impl.query.CollectionUpdateModificationQuerySpecification) SingularAttribute(javax.persistence.metamodel.SingularAttribute) ExtendedQuerySupport(com.blazebit.persistence.spi.ExtendedQuerySupport) CTENode(com.blazebit.persistence.impl.query.CTENode) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) JoinTable(com.blazebit.persistence.spi.JoinTable)

Aggregations

JoinTable (com.blazebit.persistence.spi.JoinTable)12 ArrayList (java.util.ArrayList)5 LinkedHashMap (java.util.LinkedHashMap)5 Map (java.util.Map)5 HashMap (java.util.HashMap)4 ReturningBuilder (com.blazebit.persistence.ReturningBuilder)3 CTENode (com.blazebit.persistence.impl.query.CTENode)3 ExtendedQuerySupport (com.blazebit.persistence.spi.ExtendedQuerySupport)3 ManagedType (javax.persistence.metamodel.ManagedType)3 SingularAttribute (javax.persistence.metamodel.SingularAttribute)3 AbstractEntityPersister (org.hibernate.persister.entity.AbstractEntityPersister)3 JoinType (com.blazebit.persistence.JoinType)2 ExtendedAttribute (com.blazebit.persistence.spi.ExtendedAttribute)2 ExtendedManagedType (com.blazebit.persistence.spi.ExtendedManagedType)2 EntityType (javax.persistence.metamodel.EntityType)2 IdentifiableType (javax.persistence.metamodel.IdentifiableType)2 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)2 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)2 KeyMetaData (org.datanucleus.metadata.KeyMetaData)2 AssociationType (org.hibernate.type.AssociationType)2