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