use of com.blazebit.persistence.spi.JoinTable in project blaze-persistence by Blazebit.
the class DataNucleus51JpaProvider method getJoinTable.
@Override
public JoinTable getJoinTable(EntityType<?> ownerType, String attributeName) {
AttributeImpl<?, ?> attribute = getAttribute(ownerType, attributeName);
AbstractMemberMetaData metaData = attribute.getMetadata();
if (metaData.getJoinMetaData() != null) {
Map<String, String> keyMapping = null;
Map<String, String> keyColumnTypes = null;
KeyMetaData keyMetaData = metaData.getKeyMetaData();
if (keyMetaData != null && keyMetaData.getColumnMetaData() != null) {
keyMapping = new LinkedHashMap<>();
ColumnMetaData[] keyColumnMetaData = keyMetaData.getColumnMetaData();
ColumnMetaData[] keyTargetPrimaryKeyColumnMetaData = keyMetaData.getForeignKeyMetaData() == null ? null : keyMetaData.getForeignKeyMetaData().getColumnMetaData();
if (keyTargetPrimaryKeyColumnMetaData == null) {
keyMapping.put(keyMetaData.getColumnName(), keyMetaData.getColumnName());
} else {
for (int i = 0; i < keyTargetPrimaryKeyColumnMetaData.length; i++) {
keyMapping.put(keyColumnMetaData[i].getName(), keyTargetPrimaryKeyColumnMetaData[i].getName());
}
}
} else if (metaData.getOrderMetaData() != null) {
String columnName = metaData.getOrderMetaData().getColumnName();
if (columnName != null) {
keyMapping = Collections.singletonMap(columnName, columnName);
}
}
String tableName;
Map<String, String> idColumnMapping;
Map<String, String> targetIdColumnMapping;
if (metaData.getJoinMetaData().getTable() == null) {
tableName = metaData.getTable();
ColumnMetaData[] joinMetaData;
ColumnMetaData[] elementMetaData;
if (metaData.getJoinMetaData() == null || (joinMetaData = metaData.getJoinMetaData().getColumnMetaData()) == null) {
idColumnMapping = Collections.emptyMap();
} else {
idColumnMapping = new LinkedHashMap<>(joinMetaData.length);
for (int i = 0; i < joinMetaData.length; i++) {
idColumnMapping.put(joinMetaData[i].getName(), joinMetaData[i].getTarget());
}
}
if (metaData.getElementMetaData() == null || (elementMetaData = metaData.getElementMetaData().getColumnMetaData()) == null) {
targetIdColumnMapping = Collections.emptyMap();
} else {
targetIdColumnMapping = new LinkedHashMap<>(elementMetaData.length);
for (int i = 0; i < elementMetaData.length; i++) {
targetIdColumnMapping.put(elementMetaData[i].getName(), elementMetaData[i].getTarget());
}
}
} else {
tableName = metaData.getJoinMetaData().getTable();
ColumnMetaData[] primaryKeyColumnMetaData = metaData.getJoinMetaData().getPrimaryKeyMetaData().getColumnMetaData();
ColumnMetaData[] foreignKeyColumnMetaData = metaData.getJoinMetaData().getForeignKeyMetaData().getColumnMetaData();
idColumnMapping = new LinkedHashMap<>(primaryKeyColumnMetaData.length);
for (int i = 0; i < foreignKeyColumnMetaData.length; i++) {
idColumnMapping.put(foreignKeyColumnMetaData[i].getName(), primaryKeyColumnMetaData[i].getName());
}
ColumnMetaData[] targetColumnMetaData = metaData.getJoinMetaData().getColumnMetaData();
ColumnMetaData[] targetPrimaryKeyColumnMetaData = metaData.getElementMetaData().getForeignKeyMetaData().getColumnMetaData();
targetIdColumnMapping = new LinkedHashMap<>(targetPrimaryKeyColumnMetaData.length);
for (int i = 0; i < targetColumnMetaData.length; i++) {
targetIdColumnMapping.put(targetColumnMetaData[i].getName(), targetPrimaryKeyColumnMetaData[i].getName());
}
}
return new JoinTable(tableName, null, idColumnMapping, keyMapping, keyColumnTypes, null, targetIdColumnMapping);
}
return null;
}
use of com.blazebit.persistence.spi.JoinTable in project blaze-persistence by Blazebit.
the class AbstractDeleteCollectionCriteriaBuilder 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;
// Prepare a Map<EntityAlias.idColumnName, CollectionAlias.idColumnName>
// This is used to replace references to id columns properly in the final sql query
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();
if (joinTable == null) {
throw new IllegalStateException("Deleting inverse collections is not supported!");
}
int joinTableIndex = SqlUtils.indexOfTableName(sql, joinTable.getTableName());
String collectionAlias = SqlUtils.extractAlias(sql, joinTableIndex + joinTable.getTableName().length());
String tableToDelete = joinTable.getTableName();
String tablePrefix = mainQuery.dbmsDialect.getDeleteJoinStyle() == DeleteJoinStyle.FROM ? collectionAlias : tableToDelete;
Map<String, String> columnExpressionRemappings = new HashMap<>(joinTable.getIdColumnMappings().size());
List<String> joinTableIdColumns = new ArrayList<>();
if (joinTable.getKeyColumnMappings() != null) {
for (Map.Entry<String, String> entry : joinTable.getKeyColumnMappings().entrySet()) {
joinTableIdColumns.add(entry.getKey());
columnExpressionRemappings.put(CollectionDmlSupportFunction.FUNCTION_NAME + "(" + collectionAlias + "." + entry.getValue() + ")", tablePrefix + "." + entry.getKey());
}
}
String[] discriminatorColumnCheck = mainQuery.jpaProvider.getDiscriminatorColumnCheck(entityType);
if (discriminatorColumnCheck != null) {
columnExpressionRemappings.put(ownerAlias + "." + discriminatorColumnCheck[0] + "=" + discriminatorColumnCheck[1], "1=1");
}
for (Map.Entry<String, String> entry : joinTable.getIdColumnMappings().entrySet()) {
joinTableIdColumns.add(entry.getKey());
columnExpressionRemappings.put(CollectionDmlSupportFunction.FUNCTION_NAME + "(" + ownerAlias + "." + entry.getValue() + ")", tablePrefix + "." + entry.getKey());
}
for (Map.Entry<String, String> entry : joinTable.getTargetColumnMappings().entrySet()) {
columnExpressionRemappings.put(CollectionDmlSupportFunction.FUNCTION_NAME + "(" + targetAlias + "." + entry.getValue() + ")", 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(", ");
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());
}
return new CollectionDeleteModificationQuerySpecification(this, baseQuery, exampleQuery, parameterManager.getParameterImpls(), parameterListNames, mainQuery.cteManager.isRecursive(), ctes, shouldRenderCteNodes, isEmbedded, returningColumns, objectBuilder, includedModificationStates, returningAttributeBindingMap, mainQuery.getQueryConfiguration().isQueryPlanCacheEnabled(), tableToDelete, collectionAlias, joinTableIdColumns.toArray(new String[0]), false, getDeleteExampleQuery(), columnExpressionRemappings);
}
use of com.blazebit.persistence.spi.JoinTable in project blaze-persistence by Blazebit.
the class AbstractInsertCollectionCriteriaBuilder 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);
Set<JoinNode> keyRestrictedLeftJoins = getKeyRestrictedLeftJoins();
List<String> keyRestrictedLeftJoinAliases = getKeyRestrictedLeftJoinAliases(baseQuery, keyRestrictedLeftJoins, Collections.EMPTY_SET);
List<EntityFunctionNode> entityFunctionNodes = getEntityFunctionNodes(baseQuery);
boolean isEmbedded = this instanceof ReturningBuilder;
boolean shouldRenderCteNodes = renderCteNodes(isEmbedded);
List<CTENode> ctes = shouldRenderCteNodes ? getCteNodes(isEmbedded) : Collections.EMPTY_LIST;
ExtendedQuerySupport extendedQuerySupport = getService(ExtendedQuerySupport.class);
Query insertExampleQuery = getInsertExampleQuery();
String insertExampleSql = extendedQuerySupport.getSql(em, insertExampleQuery);
String ownerAlias = extendedQuerySupport.getSqlAlias(em, insertExampleQuery, entityAlias);
String targetAlias = extendedQuerySupport.getSqlAlias(em, insertExampleQuery, JoinManager.COLLECTION_DML_BASE_QUERY_ALIAS);
JoinTable joinTable = mainQuery.jpaProvider.getJoinTable(entityType, collectionName);
int joinTableIndex = SqlUtils.indexOfTableName(insertExampleSql, joinTable.getTableName());
String collectionAlias = SqlUtils.extractAlias(insertExampleSql, joinTableIndex + joinTable.getTableName().length());
String[] selectItemExpressions = SqlUtils.getSelectItemExpressions(insertExampleSql, SqlUtils.indexOfSelect(insertExampleSql));
// 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<>(selectItemExpressions.length);
String[] discriminatorColumnCheck = mainQuery.jpaProvider.getDiscriminatorColumnCheck(entityType);
if (discriminatorColumnCheck != null) {
columnExpressionRemappings.put(ownerAlias + "." + discriminatorColumnCheck[0] + "=" + discriminatorColumnCheck[1], "1=1");
}
if (joinTable.getKeyColumnMappings() != null) {
for (Map.Entry<String, String> entry : joinTable.getKeyColumnMappings().entrySet()) {
columnExpressionRemappings.put(collectionAlias + "." + entry.getValue(), entry.getKey());
}
}
for (Map.Entry<String, String> entry : joinTable.getIdColumnMappings().entrySet()) {
columnExpressionRemappings.put(ownerAlias + "." + entry.getValue(), entry.getKey());
}
for (Map.Entry<String, String> entry : joinTable.getTargetColumnMappings().entrySet()) {
columnExpressionRemappings.put(targetAlias + "." + entry.getValue(), entry.getKey());
}
int cutoffColumns = 0;
StringBuilder insertSqlSb = new StringBuilder();
insertSqlSb.append("insert into ").append(joinTable.getTableName()).append("(");
for (String selectItemExpression : selectItemExpressions) {
String columnExpression = columnExpressionRemappings.get(selectItemExpression.trim());
// It should never be null, but the workaround for https://hibernate.atlassian.net/browse/HHH-13045 requires us to filter out the entity fetch columns
if (columnExpression == null) {
cutoffColumns++;
} else {
insertSqlSb.append(columnExpression).append(',');
}
}
insertSqlSb.setCharAt(insertSqlSb.length() - 1, ')');
return new CollectionInsertModificationQuerySpecification(this, baseQuery, exampleQuery, parameterManager.getParameterImpls(), parameterListNames, keyRestrictedLeftJoinAliases, entityFunctionNodes, mainQuery.cteManager.isRecursive(), ctes, shouldRenderCteNodes, isEmbedded, returningColumns, objectBuilder, includedModificationStates, returningAttributeBindingMap, getInsertExecutorQuery(), insertSqlSb.toString(), cutoffColumns, getForeignKeyParticipatingQueries(), mainQuery.getQueryConfiguration().isQueryPlanCacheEnabled());
}
use of com.blazebit.persistence.spi.JoinTable in project blaze-persistence by Blazebit.
the class HibernateJpaProvider method getJoinMappingPropertyNames.
@Override
public Map<String, String> getJoinMappingPropertyNames(EntityType<?> owner, String elementCollectionPath, String attributeName) {
QueryableCollection persister;
Type propertyType;
AbstractEntityPersister entityPersister = getEntityPersister(owner);
SessionFactoryImplementor factory = entityPersister.getFactory();
if (elementCollectionPath != null && (persister = getCollectionPersister(owner, elementCollectionPath)) != null) {
ComponentType componentType = (ComponentType) persister.getElementType();
String subAttribute = attributeName.substring(elementCollectionPath.length() + 1);
// Component types only store direct properties, so we have to go deeper
String[] propertyParts = subAttribute.split("\\.");
for (int i = 0; i < propertyParts.length - 1; i++) {
int index = componentType.getPropertyIndex(propertyParts[i]);
propertyType = componentType.getSubtypes()[index];
if (propertyType instanceof ComponentType) {
componentType = (ComponentType) propertyType;
} else {
// A path expression shouldn't navigate over an association..
throw new IllegalStateException("Can't get the id properties for: " + attributeName);
}
}
propertyType = componentType.getSubtypes()[componentType.getPropertyIndex(propertyParts[propertyParts.length - 1])];
} else {
propertyType = getPropertyType(entityPersister, attributeName);
}
List<String> identifierOrUniqueKeyPropertyNames = new ArrayList<>();
List<String> sourceIdentifierOrUniqueKeyPropertyNames = new ArrayList<>();
if (propertyType instanceof CollectionType) {
Type elementType = ((CollectionType) propertyType).getElementType(factory);
if (elementType instanceof org.hibernate.type.EntityType) {
JoinTable joinTable = getJoinTable(owner, attributeName);
Collection<String> targetAttributeNames = joinTable == null ? null : joinTable.getTargetAttributeNames();
if (targetAttributeNames == null) {
collectPropertyNames(identifierOrUniqueKeyPropertyNames, null, elementType, factory);
String mappedBy = getMappedBy(getCollectionPersister(owner, attributeName));
if (mappedBy == null || mappedBy.isEmpty()) {
// but also no mapped by attribute, I don't know if that is even a valid/possible mapping
if (((CollectionType) propertyType).useLHSPrimaryKey()) {
// TODO: this doesn't work for entities using an id class
sourceIdentifierOrUniqueKeyPropertyNames.add(entityPersister.getIdentifierPropertyName());
} else {
throw new IllegalArgumentException("One-to-many using natural key is unsupported!");
}
} else {
AbstractEntityPersister elementPersister = (AbstractEntityPersister) entityPersisters.get(((org.hibernate.type.EntityType) elementType).getAssociatedEntityName());
collectPropertyNames(sourceIdentifierOrUniqueKeyPropertyNames, null, getPropertyType(elementPersister, mappedBy), factory);
// if (sourceIdentifierOrUniqueKeyPropertyNames.size() != identifierOrUniqueKeyPropertyNames.size()) {
// // We have a inverse map or inverse indexed list here
// // Maybe at some point we can determine the index property name mapping as well
// persister = getCollectionPersister(owner, attributeName);
// Set<String> indexAttributeNames = getColumnMatchingAttributeNames(elementPersister, Arrays.asList(persister.getIndexColumnNames()));
// persister.getIndexType()
// }
}
} else {
AbstractEntityPersister elementPersister = (AbstractEntityPersister) entityPersisters.get(((org.hibernate.type.EntityType) elementType).getAssociatedEntityName());
for (String targetAttributeName : targetAttributeNames) {
collectPropertyNames(identifierOrUniqueKeyPropertyNames, targetAttributeName, getPropertyType(elementPersister, targetAttributeName), factory);
}
for (String idAttributeName : joinTable.getIdAttributeNames()) {
collectPropertyNames(sourceIdentifierOrUniqueKeyPropertyNames, idAttributeName, getPropertyType(entityPersister, idAttributeName), factory);
}
}
}
} else {
collectPropertyNames(identifierOrUniqueKeyPropertyNames, null, propertyType, factory);
if (propertyType instanceof org.hibernate.type.EntityType) {
AbstractEntityPersister elementPersister = (AbstractEntityPersister) entityPersisters.get(((org.hibernate.type.EntityType) propertyType).getAssociatedEntityName());
if (((org.hibernate.type.EntityType) propertyType).isReferenceToPrimaryKey()) {
if (elementPersister.getIdentifierType().isComponentType()) {
String targetPropertyPrefix = elementPersister.getIdentifierPropertyName() == null ? attributeName + "." : "";
for (int i = 0; i < identifierOrUniqueKeyPropertyNames.size(); i++) {
sourceIdentifierOrUniqueKeyPropertyNames.add(targetPropertyPrefix + identifierOrUniqueKeyPropertyNames.get(i));
}
} else {
sourceIdentifierOrUniqueKeyPropertyNames.add(elementPersister.getIdentifierPropertyName());
}
} else if (propertyType instanceof OneToOneType) {
String mappedBy = ((OneToOneType) propertyType).getRHSUniqueKeyPropertyName();
if (mappedBy == null || mappedBy.isEmpty()) {
throw new IllegalArgumentException("One-to-one using natural key is unsupported!");
} else {
collectPropertyNames(sourceIdentifierOrUniqueKeyPropertyNames, null, getPropertyType(elementPersister, mappedBy), factory);
}
}
}
}
Map<String, String> joinMapping = new LinkedHashMap<>(identifierOrUniqueKeyPropertyNames.size());
for (int i = 0; i < identifierOrUniqueKeyPropertyNames.size(); i++) {
if (sourceIdentifierOrUniqueKeyPropertyNames.size() > i) {
joinMapping.put(identifierOrUniqueKeyPropertyNames.get(i), sourceIdentifierOrUniqueKeyPropertyNames.get(i));
} else {
joinMapping.put(identifierOrUniqueKeyPropertyNames.get(i), null);
}
}
return joinMapping;
}
use of com.blazebit.persistence.spi.JoinTable in project blaze-persistence by Blazebit.
the class DataNucleusJpaProvider method getJoinTable.
@Override
public JoinTable getJoinTable(EntityType<?> ownerType, String attributeName) {
AttributeImpl<?, ?> attribute = getAttribute(ownerType, attributeName);
AbstractMemberMetaData metaData = attribute.getMetadata();
if (metaData.getJoinMetaData() != null) {
Map<String, String> keyMapping = null;
Map<String, String> keyColumnTypes = null;
KeyMetaData keyMetaData = metaData.getKeyMetaData();
if (keyMetaData != null && keyMetaData.getColumnMetaData() != null) {
keyMapping = new LinkedHashMap<>();
ColumnMetaData[] keyColumnMetaData = keyMetaData.getColumnMetaData();
ColumnMetaData[] keyTargetPrimaryKeyColumnMetaData = keyMetaData.getForeignKeyMetaData() == null ? null : keyMetaData.getForeignKeyMetaData().getColumnMetaData();
if (keyTargetPrimaryKeyColumnMetaData == null) {
keyMapping.put(keyMetaData.getColumnName(), keyMetaData.getColumnName());
} else {
for (int i = 0; i < keyTargetPrimaryKeyColumnMetaData.length; i++) {
keyMapping.put(keyColumnMetaData[i].getName(), keyTargetPrimaryKeyColumnMetaData[i].getName());
}
}
} else if (metaData.getOrderMetaData() != null) {
String columnName = metaData.getOrderMetaData().getColumnName();
if (columnName != null) {
keyMapping = Collections.singletonMap(columnName, columnName);
}
}
String tableName;
Map<String, String> idColumnMapping;
Map<String, String> targetIdColumnMapping;
if (metaData.getJoinMetaData().getTable() == null) {
tableName = metaData.getTable();
ColumnMetaData[] joinMetaData;
ColumnMetaData[] elementMetaData;
if (metaData.getJoinMetaData() == null || (joinMetaData = metaData.getJoinMetaData().getColumnMetaData()) == null) {
idColumnMapping = Collections.emptyMap();
} else {
idColumnMapping = new LinkedHashMap<>(joinMetaData.length);
for (int i = 0; i < joinMetaData.length; i++) {
idColumnMapping.put(joinMetaData[i].getName(), joinMetaData[i].getTarget());
}
}
if (metaData.getElementMetaData() == null || (elementMetaData = metaData.getElementMetaData().getColumnMetaData()) == null) {
targetIdColumnMapping = Collections.emptyMap();
} else {
targetIdColumnMapping = new LinkedHashMap<>(elementMetaData.length);
for (int i = 0; i < elementMetaData.length; i++) {
targetIdColumnMapping.put(elementMetaData[i].getName(), elementMetaData[i].getTarget());
}
}
} else {
tableName = metaData.getJoinMetaData().getTable();
ColumnMetaData[] primaryKeyColumnMetaData = metaData.getJoinMetaData().getPrimaryKeyMetaData().getColumnMetaData();
ColumnMetaData[] foreignKeyColumnMetaData = metaData.getJoinMetaData().getForeignKeyMetaData().getColumnMetaData();
idColumnMapping = new LinkedHashMap<>(primaryKeyColumnMetaData.length);
for (int i = 0; i < foreignKeyColumnMetaData.length; i++) {
idColumnMapping.put(foreignKeyColumnMetaData[i].getName(), primaryKeyColumnMetaData[i].getName());
}
ColumnMetaData[] targetColumnMetaData = metaData.getJoinMetaData().getColumnMetaData();
ColumnMetaData[] targetPrimaryKeyColumnMetaData = metaData.getElementMetaData().getForeignKeyMetaData().getColumnMetaData();
targetIdColumnMapping = new LinkedHashMap<>(targetPrimaryKeyColumnMetaData.length);
for (int i = 0; i < targetColumnMetaData.length; i++) {
targetIdColumnMapping.put(targetColumnMetaData[i].getName(), targetPrimaryKeyColumnMetaData[i].getName());
}
}
return new JoinTable(tableName, null, idColumnMapping, keyMapping, keyColumnTypes, null, targetIdColumnMapping);
}
return null;
}
Aggregations