Search in sources :

Example 1 with PersistentEntity

use of io.micronaut.data.model.PersistentEntity in project micronaut-data by micronaut-projects.

the class QueryModelSelectionVisitor method visit.

@Override
public void visit(IdExpression<?, ?> idExpression) {
    PersistentEntityRoot<?> root = idExpression.getRoot();
    PersistentEntity persistentEntity = root.getPersistentEntity();
    if (persistentEntity.hasCompositeIdentity()) {
        for (PersistentProperty persistentProperty : persistentEntity.getCompositeIdentity()) {
            if (distinct) {
                addProjection(Projections.distinct(persistentProperty.getName()));
            } else {
                addProjection(Projections.property(persistentProperty.getName()));
            }
        }
    } else {
        PersistentProperty identity = persistentEntity.getIdentity();
        if (distinct) {
            addProjection(Projections.distinct(identity.getName()));
        } else {
            addProjection(Projections.property(identity.getName()));
        }
    }
}
Also used : PersistentEntity(io.micronaut.data.model.PersistentEntity) PersistentProperty(io.micronaut.data.model.PersistentProperty)

Example 2 with PersistentEntity

use of io.micronaut.data.model.PersistentEntity in project micronaut-data by micronaut-projects.

the class AbstractSqlRepositoryOperations method idPropertiesWithValues.

private Stream<Map.Entry<PersistentProperty, Object>> idPropertiesWithValues(PersistentProperty property, Object value) {
    Object propertyValue = ((RuntimePersistentProperty) property).getProperty().get(value);
    if (property instanceof Embedded) {
        Embedded embedded = (Embedded) property;
        PersistentEntity embeddedEntity = embedded.getAssociatedEntity();
        return embeddedEntity.getPersistentProperties().stream().flatMap(prop -> idPropertiesWithValues(prop, propertyValue));
    } else if (property instanceof Association) {
        Association association = (Association) property;
        if (association.isForeignKey()) {
            return Stream.empty();
        }
        PersistentEntity associatedEntity = association.getAssociatedEntity();
        PersistentProperty identity = associatedEntity.getIdentity();
        if (identity == null) {
            throw new IllegalStateException("Identity cannot be missing for: " + associatedEntity);
        }
        return idPropertiesWithValues(identity, propertyValue);
    }
    return Stream.of(new AbstractMap.SimpleEntry<>(property, propertyValue));
}
Also used : AbstractMap(java.util.AbstractMap) RuntimeAssociation(io.micronaut.data.model.runtime.RuntimeAssociation) Association(io.micronaut.data.model.Association) PersistentEntity(io.micronaut.data.model.PersistentEntity) RuntimePersistentEntity(io.micronaut.data.model.runtime.RuntimePersistentEntity) Embedded(io.micronaut.data.model.Embedded) PersistentProperty(io.micronaut.data.model.PersistentProperty) RuntimePersistentProperty(io.micronaut.data.model.runtime.RuntimePersistentProperty)

Example 3 with PersistentEntity

use of io.micronaut.data.model.PersistentEntity 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);
    }
}
Also used : Arrays(java.util.Arrays) TypeRole(io.micronaut.data.annotation.TypeRole) Internal(io.micronaut.core.annotation.Internal) Collections.singletonList(java.util.Collections.singletonList) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Locale(java.util.Locale) Arrays.asList(java.util.Arrays.asList) Map(java.util.Map) QueryResult(io.micronaut.data.model.query.builder.QueryResult) ArgumentUtils(io.micronaut.core.util.ArgumentUtils) PersistentPropertyPath(io.micronaut.data.model.PersistentPropertyPath) PersistentProperty(io.micronaut.data.model.PersistentProperty) MappingException(io.micronaut.data.exceptions.MappingException) Sort(io.micronaut.data.model.Sort) Collection(java.util.Collection) Set(java.util.Set) NotNull(javax.validation.constraints.NotNull) Collectors(java.util.stream.Collectors) StringUtils(io.micronaut.core.util.StringUtils) List(java.util.List) Optional(java.util.Optional) Pattern(java.util.regex.Pattern) Relation(io.micronaut.data.annotation.Relation) QueryParameterBinding(io.micronaut.data.model.query.builder.QueryParameterBinding) MongoAnnotations(io.micronaut.data.document.mongo.MongoAnnotations) QueryModel(io.micronaut.data.model.query.QueryModel) HashMap(java.util.HashMap) Function(java.util.function.Function) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Embedded(io.micronaut.data.model.Embedded) SerdeConfig(io.micronaut.serde.config.annotation.SerdeConfig) Nullable(io.micronaut.core.annotation.Nullable) Pageable(io.micronaut.data.model.Pageable) BiConsumer(java.util.function.BiConsumer) Collections.singletonMap(java.util.Collections.singletonMap) NamingStrategy(io.micronaut.data.model.naming.NamingStrategy) Iterator(java.util.Iterator) NonNull(io.micronaut.core.annotation.NonNull) JoinPath(io.micronaut.data.model.query.JoinPath) BindingParameter(io.micronaut.data.model.query.BindingParameter) Association(io.micronaut.data.model.Association) PersistentEntity(io.micronaut.data.model.PersistentEntity) CollectionUtils(io.micronaut.core.util.CollectionUtils) StringJoiner(java.util.StringJoiner) QueryBuilder(io.micronaut.data.model.query.builder.QueryBuilder) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Comparator(java.util.Comparator) Collections(java.util.Collections) JoinPath(io.micronaut.data.model.query.JoinPath) PersistentEntity(io.micronaut.data.model.PersistentEntity) ArrayList(java.util.ArrayList) PersistentPropertyPath(io.micronaut.data.model.PersistentPropertyPath) PersistentProperty(io.micronaut.data.model.PersistentProperty) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) MappingException(io.micronaut.data.exceptions.MappingException) NamingStrategy(io.micronaut.data.model.naming.NamingStrategy) Relation(io.micronaut.data.annotation.Relation) Association(io.micronaut.data.model.Association) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Collections.singletonMap(java.util.Collections.singletonMap) StringJoiner(java.util.StringJoiner)

Example 4 with PersistentEntity

use of io.micronaut.data.model.PersistentEntity in project micronaut-data by micronaut-projects.

the class MongoReactiveCollectionsCreator method initialize.

@PostConstruct
void initialize(BeanLocator beanLocator, RuntimeEntityRegistry runtimeEntityRegistry, List<AbstractMongoConfiguration> mongoConfigurations) {
    super.initialize(runtimeEntityRegistry, mongoConfigurations, mongoConfiguration -> {
        ReactiveMongoDatabaseFactory mongoDatabaseFactory = getMongoFactory(ReactiveMongoDatabaseFactory.class, beanLocator, mongoConfiguration);
        Map<String, Set<String>> databaseCollections = new HashMap<>();
        return new DatabaseOperations<MongoDatabase>() {

            @Override
            public String getDatabaseName(MongoDatabase database) {
                return database.getName();
            }

            @Override
            public MongoDatabase find(PersistentEntity persistentEntity) {
                return mongoDatabaseFactory.getDatabase(persistentEntity);
            }

            @Override
            public Set<String> listCollectionNames(MongoDatabase database) {
                return databaseCollections.computeIfAbsent(database.getName(), s -> Flux.from(database.listCollectionNames()).collect(Collectors.toSet()).block());
            }

            @Override
            public void createCollection(MongoDatabase database, String collection) {
                Mono.from(database.createCollection(collection)).block();
            }
        };
    });
}
Also used : Set(java.util.Set) HashMap(java.util.HashMap) PersistentEntity(io.micronaut.data.model.PersistentEntity) ReactiveMongoDatabaseFactory(io.micronaut.data.mongodb.database.ReactiveMongoDatabaseFactory) MongoDatabase(com.mongodb.reactivestreams.client.MongoDatabase) PostConstruct(javax.annotation.PostConstruct)

Example 5 with PersistentEntity

use of io.micronaut.data.model.PersistentEntity in project micronaut-data by micronaut-projects.

the class SqlQueryBuilder method findOwner.

private Optional<PersistentEntity> findOwner(List<Association> associations, PersistentProperty property) {
    PersistentEntity owner = property.getOwner();
    if (!owner.isEmbeddable()) {
        return Optional.of(owner);
    }
    ListIterator<Association> listIterator = associations.listIterator(associations.size());
    while (listIterator.hasPrevious()) {
        Association association = listIterator.previous();
        if (!association.getOwner().isEmbeddable()) {
            return Optional.of(association.getOwner());
        }
    }
    return Optional.empty();
}
Also used : Association(io.micronaut.data.model.Association) PersistentEntity(io.micronaut.data.model.PersistentEntity)

Aggregations

PersistentEntity (io.micronaut.data.model.PersistentEntity)27 PersistentProperty (io.micronaut.data.model.PersistentProperty)15 Association (io.micronaut.data.model.Association)13 Embedded (io.micronaut.data.model.Embedded)11 List (java.util.List)11 ArrayList (java.util.ArrayList)10 Collection (java.util.Collection)9 CollectionUtils (io.micronaut.core.util.CollectionUtils)8 MappedEntity (io.micronaut.data.annotation.MappedEntity)8 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)7 NonNull (io.micronaut.core.annotation.NonNull)7 ArrayUtils (io.micronaut.core.util.ArrayUtils)7 Relation (io.micronaut.data.annotation.Relation)7 PersistentPropertyPath (io.micronaut.data.model.PersistentPropertyPath)7 NamingStrategy (io.micronaut.data.model.naming.NamingStrategy)7 JoinPath (io.micronaut.data.model.query.JoinPath)7 ArgumentUtils (io.micronaut.core.util.ArgumentUtils)6 StringUtils (io.micronaut.core.util.StringUtils)6 MappingException (io.micronaut.data.exceptions.MappingException)6 Pageable (io.micronaut.data.model.Pageable)6