use of io.micronaut.data.model.naming.NamingStrategy in project micronaut-data by micronaut-projects.
the class MongoQueryBuilder method addLookups.
private void addLookups(Collection<JoinPath> joins, QueryState queryState) {
if (joins.isEmpty()) {
return;
}
List<String> joined = joins.stream().map(JoinPath::getPath).sorted((o1, o2) -> Comparator.comparingInt(String::length).thenComparing(String::compareTo).compare(o1, o2)).collect(Collectors.toList());
for (String join : joined) {
StringJoiner rootPath = new StringJoiner(".");
StringJoiner currentEntityPath = new StringJoiner(".");
LookupsStage currentLookup = queryState.rootLookups;
for (String path : StringUtils.splitOmitEmptyStrings(join, '.')) {
rootPath.add(path);
currentEntityPath.add(path);
String thisPath = currentEntityPath.toString();
if (currentLookup.subLookups.containsKey(thisPath)) {
currentLookup = currentLookup.subLookups.get(path);
currentEntityPath = new StringJoiner(".");
continue;
}
PersistentPropertyPath propertyPath = currentLookup.persistentEntity.getPropertyPath(thisPath);
PersistentProperty property = propertyPath.getProperty();
if (!(property instanceof Association)) {
continue;
}
Association association = (Association) property;
if (association.getKind() == Relation.Kind.EMBEDDED) {
continue;
}
LookupsStage lookupStage = new LookupsStage(association.getAssociatedEntity());
List<Map<String, Object>> pipeline = currentLookup.pipeline;
Optional<Association> inverseSide = association.getInverseSide().map(Function.identity());
PersistentEntity persistentEntity = association.getOwner();
String joinedCollectionName = association.getAssociatedEntity().getPersistedName();
String ownerCollectionName = persistentEntity.getPersistedName();
if (association.getKind() == Relation.Kind.MANY_TO_MANY || association.isForeignKey() && !inverseSide.isPresent()) {
PersistentEntity associatedEntity = association.getAssociatedEntity();
PersistentEntity associationOwner = association.getOwner();
// JOIN TABLE
PersistentProperty identity = associatedEntity.getIdentity();
if (identity == null) {
throw new IllegalArgumentException("Associated entity [" + associatedEntity.getName() + "] defines no ID. Cannot join.");
}
final PersistentProperty associatedId = associationOwner.getIdentity();
if (associatedId == null) {
throw new MappingException("Cannot join on entity [" + associationOwner.getName() + "] that has no declared ID");
}
Association owningAssociation = inverseSide.orElse(association);
boolean isAssociationOwner = !association.getInverseSide().isPresent();
NamingStrategy namingStrategy = associationOwner.getNamingStrategy();
AnnotationMetadata annotationMetadata = owningAssociation.getAnnotationMetadata();
List<String> ownerJoinFields = resolveJoinTableAssociatedFields(annotationMetadata, isAssociationOwner, associationOwner, namingStrategy);
List<String> ownerJoinCollectionFields = resolveJoinTableJoinFields(annotationMetadata, isAssociationOwner, associationOwner, namingStrategy);
List<String> associationJoinFields = resolveJoinTableAssociatedFields(annotationMetadata, !isAssociationOwner, associatedEntity, namingStrategy);
List<String> associationJoinCollectionFields = resolveJoinTableJoinFields(annotationMetadata, !isAssociationOwner, associatedEntity, namingStrategy);
String joinCollectionName = namingStrategy.mappedName(owningAssociation);
// String joinTableName = annotationMetadata
// .stringValue(ANN_JOIN_TABLE, "name")
// .orElseGet(() -> namingStrategy.mappedName(association));
List<Map<String, Object>> joinCollectionLookupPipeline = new ArrayList<>();
pipeline.add(lookup(joinCollectionName, "_id", ownerCollectionName, joinCollectionLookupPipeline, thisPath));
joinCollectionLookupPipeline.add(lookup(joinedCollectionName, joinedCollectionName, "_id", lookupStage.pipeline, joinedCollectionName));
joinCollectionLookupPipeline.add(unwind("$" + joinedCollectionName, true));
joinCollectionLookupPipeline.add(singletonMap("$replaceRoot", singletonMap("newRoot", "$" + joinedCollectionName)));
} else {
String currentPath = asPath(propertyPath.getAssociations(), propertyPath.getProperty());
if (association.isForeignKey()) {
String mappedBy = association.getAnnotationMetadata().stringValue(Relation.class, "mappedBy").orElseThrow(IllegalStateException::new);
PersistentPropertyPath mappedByPath = association.getAssociatedEntity().getPropertyPath(mappedBy);
if (mappedByPath == null) {
throw new IllegalStateException("Cannot find mapped path: " + mappedBy);
}
if (!(mappedByPath.getProperty() instanceof Association)) {
throw new IllegalStateException("Expected association as a mapped path: " + mappedBy);
}
List<String> localMatchFields = new ArrayList<>();
List<String> foreignMatchFields = new ArrayList<>();
traversePersistentProperties(currentLookup.persistentEntity.getIdentity(), (associations, p) -> {
String fieldPath = asPath(associations, p);
localMatchFields.add(fieldPath);
});
List<Association> mappedAssociations = new ArrayList<>(mappedByPath.getAssociations());
mappedAssociations.add((Association) mappedByPath.getProperty());
traversePersistentProperties(mappedAssociations, currentLookup.persistentEntity.getIdentity(), (associations, p) -> {
String fieldPath = asPath(associations, p);
foreignMatchFields.add(fieldPath);
});
pipeline.add(lookup(joinedCollectionName, localMatchFields, foreignMatchFields, lookupStage.pipeline, currentPath));
} else {
List<Association> mappedAssociations = new ArrayList<>(propertyPath.getAssociations());
mappedAssociations.add((Association) propertyPath.getProperty());
List<String> localMatchFields = new ArrayList<>();
List<String> foreignMatchFields = new ArrayList<>();
PersistentProperty identity = lookupStage.persistentEntity.getIdentity();
if (identity == null) {
throw new IllegalStateException("Null identity of persistent entity: " + lookupStage.persistentEntity);
}
traversePersistentProperties(mappedAssociations, identity, (associations, p) -> {
String fieldPath = asPath(associations, p);
localMatchFields.add(fieldPath);
});
traversePersistentProperties(identity, (associations, p) -> {
String fieldPath = asPath(associations, p);
foreignMatchFields.add(fieldPath);
});
pipeline.add(lookup(joinedCollectionName, localMatchFields, foreignMatchFields, lookupStage.pipeline, currentPath));
}
if (association.getKind().isSingleEnded()) {
pipeline.add(unwind("$" + currentPath, true));
}
}
currentLookup.subLookups.put(currentEntityPath.toString(), lookupStage);
}
queryState.joinPaths.add(join);
}
}
use of io.micronaut.data.model.naming.NamingStrategy in project micronaut-data by micronaut-projects.
the class SqlQueryBuilder method buildInsert.
@NonNull
@Override
public QueryResult buildInsert(AnnotationMetadata repositoryMetadata, PersistentEntity entity) {
boolean escape = shouldEscape(entity);
final String unescapedTableName = getUnescapedTableName(entity);
NamingStrategy namingStrategy = entity.getNamingStrategy();
Collection<? extends PersistentProperty> persistentProperties = entity.getPersistentProperties();
List<QueryParameterBinding> parameterBindings = new ArrayList<>();
List<String> columns = new ArrayList<>();
List<String> values = new ArrayList<>();
for (PersistentProperty prop : persistentProperties) {
if (!prop.isGenerated()) {
traversePersistentProperties(prop, (associations, property) -> {
addWriteExpression(values, prop);
String key = String.valueOf(values.size());
String[] path = asStringPath(associations, property);
parameterBindings.add(new QueryParameterBinding() {
@Override
public String getKey() {
return key;
}
@Override
public DataType getDataType() {
return property.getDataType();
}
@Override
public String[] getPropertyPath() {
return path;
}
});
String columnName = namingStrategy.mappedName(associations, property);
if (escape) {
columnName = quote(columnName);
}
columns.add(columnName);
});
}
}
PersistentProperty version = entity.getVersion();
if (version != null) {
addWriteExpression(values, version);
String key = String.valueOf(values.size());
parameterBindings.add(new QueryParameterBinding() {
@Override
public String getKey() {
return key;
}
@Override
public DataType getDataType() {
return version.getDataType();
}
@Override
public String[] getPropertyPath() {
return new String[] { version.getName() };
}
});
String columnName = namingStrategy.mappedName(Collections.emptyList(), version);
if (escape) {
columnName = quote(columnName);
}
columns.add(columnName);
}
PersistentProperty identity = entity.getIdentity();
if (identity != null) {
traversePersistentProperties(identity, (associations, property) -> {
boolean isSequence = false;
if (isNotForeign(associations)) {
Optional<AnnotationValue<GeneratedValue>> generated = property.findAnnotation(GeneratedValue.class);
if (generated.isPresent()) {
GeneratedValue.Type idGeneratorType = generated.flatMap(av -> av.enumValue(GeneratedValue.Type.class)).orElseGet(() -> selectAutoStrategy(property));
if (idGeneratorType == GeneratedValue.Type.SEQUENCE) {
isSequence = true;
} else if (dialect != Dialect.MYSQL || property.getDataType() != DataType.UUID) {
// Property skipped
return;
}
}
}
if (isSequence) {
values.add(getSequenceStatement(unescapedTableName, property));
} else {
addWriteExpression(values, property);
String key = String.valueOf(values.size());
String[] path = asStringPath(associations, property);
parameterBindings.add(new QueryParameterBinding() {
@Override
public String getKey() {
return key;
}
@Override
public DataType getDataType() {
return property.getDataType();
}
@Override
public String[] getPropertyPath() {
return path;
}
});
}
String columnName = namingStrategy.mappedName(associations, property);
if (escape) {
columnName = quote(columnName);
}
columns.add(columnName);
});
}
String builder = INSERT_INTO + getTableName(entity) + " (" + String.join(",", columns) + CLOSE_BRACKET + " " + "VALUES (" + String.join(String.valueOf(COMMA), values) + CLOSE_BRACKET;
return QueryResult.of(builder, Collections.emptyList(), parameterBindings, Collections.emptyMap());
}
use of io.micronaut.data.model.naming.NamingStrategy in project micronaut-data by micronaut-projects.
the class SqlQueryBuilder method selectAllColumns.
/**
* Selects all columns for the given entity and alias.
*
* @param entity The entity
* @param alias The alias
* @param sb The builder to add the columns
*/
@Override
public void selectAllColumns(PersistentEntity entity, String alias, StringBuilder sb) {
if (canUseWildcardForSelect(entity)) {
if (alias != null) {
sb.append(alias).append(DOT);
}
sb.append("*");
return;
}
boolean escape = shouldEscape(entity);
NamingStrategy namingStrategy = entity.getNamingStrategy();
int length = sb.length();
traversePersistentProperties(entity, (associations, property) -> {
String transformed = getDataTransformerReadValue(alias, property).orElse(null);
if (transformed != null) {
sb.append(transformed).append(AS_CLAUSE).append(property.getPersistedName());
} else {
String column = namingStrategy.mappedName(associations, property);
if (escape) {
column = quote(column);
}
sb.append(alias).append(DOT).append(column);
}
sb.append(COMMA);
});
int newLength = sb.length();
if (newLength == length) {
if (alias != null) {
sb.append(alias).append(DOT);
}
sb.append("*");
} else {
sb.setLength(newLength - 1);
}
}
use of io.micronaut.data.model.naming.NamingStrategy in project micronaut-data by micronaut-projects.
the class SqlQueryBuilder method buildJoin.
private void buildJoin(String joinType, StringBuilder sb, QueryState queryState, List<Association> joinAssociationsPath, String joinAlias, Association association, PersistentEntity associatedEntity, PersistentEntity associationOwner, String currentJoinAlias) {
final boolean escape = shouldEscape(associationOwner);
String mappedBy = association.getAnnotationMetadata().stringValue(Relation.class, "mappedBy").orElse(null);
if (association.getKind() == Relation.Kind.MANY_TO_MANY || association.isForeignKey() && StringUtils.isEmpty(mappedBy)) {
PersistentProperty identity = associatedEntity.getIdentity();
if (identity == null) {
throw new IllegalArgumentException("Associated entity [" + associatedEntity.getName() + "] defines no ID. Cannot join.");
}
final PersistentProperty associatedId = associationOwner.getIdentity();
if (associatedId == null) {
throw new MappingException("Cannot join on entity [" + associationOwner.getName() + "] that has no declared ID");
}
Optional<Association> inverseSide = association.getInverseSide().map(Function.identity());
Association owningAssociation = inverseSide.orElse(association);
boolean isAssociationOwner = !association.getInverseSide().isPresent();
NamingStrategy namingStrategy = associationOwner.getNamingStrategy();
AnnotationMetadata annotationMetadata = owningAssociation.getAnnotationMetadata();
List<String> ownerJoinColumns = resolveJoinTableAssociatedColumns(annotationMetadata, isAssociationOwner, associationOwner, namingStrategy);
List<String> ownerJoinTableColumns = resolveJoinTableJoinColumns(annotationMetadata, isAssociationOwner, associationOwner, namingStrategy);
List<String> associationJoinColumns = resolveJoinTableAssociatedColumns(annotationMetadata, !isAssociationOwner, associatedEntity, namingStrategy);
List<String> associationJoinTableColumns = resolveJoinTableJoinColumns(annotationMetadata, !isAssociationOwner, associatedEntity, namingStrategy);
if (escape) {
ownerJoinColumns = ownerJoinColumns.stream().map(this::quote).collect(Collectors.toList());
ownerJoinTableColumns = ownerJoinTableColumns.stream().map(this::quote).collect(Collectors.toList());
associationJoinColumns = associationJoinColumns.stream().map(this::quote).collect(Collectors.toList());
associationJoinTableColumns = associationJoinTableColumns.stream().map(this::quote).collect(Collectors.toList());
}
String joinTableName = annotationMetadata.stringValue(ANN_JOIN_TABLE, "name").orElseGet(() -> namingStrategy.mappedName(association));
String joinTableAlias = annotationMetadata.stringValue(ANN_JOIN_TABLE, "alias").orElseGet(() -> currentJoinAlias + joinTableName + "_");
join(sb, queryState.getQueryModel(), joinType, escape ? quote(joinTableName) : joinTableName, joinTableAlias, joinAlias, ownerJoinColumns, ownerJoinTableColumns);
sb.append(SPACE);
join(sb, queryState.getQueryModel(), joinType, getTableName(associatedEntity), currentJoinAlias, joinTableAlias, associationJoinTableColumns, associationJoinColumns);
} else {
if (StringUtils.isNotEmpty(mappedBy)) {
PersistentProperty ownerIdentity = associationOwner.getIdentity();
if (ownerIdentity == null) {
throw new IllegalArgumentException("Associated entity [" + associationOwner + "] defines no ID. Cannot join.");
}
PersistentPropertyPath mappedByPropertyPath = associatedEntity.getPropertyPath(mappedBy);
if (mappedByPropertyPath == null) {
throw new MappingException("Foreign key association with mappedBy references a property that doesn't exist [" + mappedBy + "] of entity: " + associatedEntity.getName());
}
join(sb, joinType, queryState, associatedEntity, associationOwner, joinAlias, currentJoinAlias, joinAssociationsPath, ownerIdentity, mappedByPropertyPath.getAssociations(), mappedByPropertyPath.getProperty());
} else {
PersistentProperty associatedProperty = association.getAssociatedEntity().getIdentity();
if (associatedProperty == null) {
throw new IllegalArgumentException("Associated entity [" + association.getAssociatedEntity().getName() + "] defines no ID. Cannot join.");
}
join(sb, joinType, queryState, associatedEntity, associationOwner, joinAlias, currentJoinAlias, joinAssociationsPath, association, Collections.emptyList(), associatedProperty);
}
}
}
use of io.micronaut.data.model.naming.NamingStrategy in project micronaut-data by micronaut-projects.
the class AbstractMongoCollectionsCreator method initialize.
/**
* Initialize the collections.
*
* @param runtimeEntityRegistry The entity registry
* @param mongoConfigurations The configuration
* @param databaseOperationsProvider The database provider
*/
protected void initialize(RuntimeEntityRegistry runtimeEntityRegistry, List<AbstractMongoConfiguration> mongoConfigurations, DatabaseOperationsProvider<Dtbs> databaseOperationsProvider) {
for (AbstractMongoConfiguration mongoConfiguration : mongoConfigurations) {
// TODO: different initializer per conf
Collection<BeanIntrospection<Object>> introspections = BeanIntrospector.SHARED.findIntrospections(MappedEntity.class);
PersistentEntity[] entities = introspections.stream().filter(i -> !i.getBeanType().getName().contains("$")).filter(i -> !java.lang.reflect.Modifier.isAbstract(i.getBeanType().getModifiers())).map(e -> runtimeEntityRegistry.getEntity(e.getBeanType())).toArray(PersistentEntity[]::new);
DatabaseOperations<Dtbs> databaseOperations = databaseOperationsProvider.get(mongoConfiguration);
for (PersistentEntity entity : entities) {
Dtbs database = databaseOperations.find(entity);
Set<String> collections = databaseOperations.listCollectionNames(database);
String persistedName = entity.getPersistedName();
if (collections.add(persistedName)) {
if (LOG.isInfoEnabled()) {
LOG.info("Creating collection: {} in database: {}", persistedName, databaseOperations.getDatabaseName(database));
}
databaseOperations.createCollection(database, persistedName);
}
for (PersistentProperty persistentProperty : entity.getPersistentProperties()) {
if (persistentProperty instanceof Association) {
Association association = (Association) persistentProperty;
Optional<Association> inverseSide = association.getInverseSide().map(Function.identity());
if (association.getKind() == Relation.Kind.MANY_TO_MANY || association.isForeignKey() && !inverseSide.isPresent()) {
Association owningAssociation = inverseSide.orElse(association);
NamingStrategy namingStrategy = association.getOwner().getNamingStrategy();
String joinCollectionName = namingStrategy.mappedName(owningAssociation);
if (collections.add(joinCollectionName)) {
if (LOG.isInfoEnabled()) {
LOG.info("Creating collection: {} in database: {}", persistedName, databaseOperations.getDatabaseName(database));
}
databaseOperations.createCollection(database, joinCollectionName);
}
}
}
}
}
}
}
Aggregations