在第5季度将Query dsl与Reactive Mongo Repository集成

时间:2017-09-02 15:46:40

标签: java spring mongodb reactive-programming

在i能够使用QuerydslPredicateExecutor扩展我的mongo存储库之前,Spring 5附带了spring数据mongo的被动实现

 @Repository
 public interface AccountRepo extends MongoRepository<Account,String> 
 ,QuerydslPredicateExecutor<Account>

如果我试试这个

 @Repository
 public interface AccountRepo extends
 ReactiveMongoRepository<Account,String>,
 QuerydslPredicateExecutor<Account>

我的应用程序无法启动它,因为:

引起:org.springframework.data.mapping.PropertyReferenceException:找不到类型为Account的属性!

有没有办法绕过这个

这是帐户类

package com.devop.models;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document
@Data
public class Account {
@Id
String id;

String accountName;

String accountNumber;

String schemeCode;

String openDate;

String accountCategory;

String accountCurrency = "Naira";

String accountSecondaryCategory;

String receiveSmsAlert;

String recieveEmailAlert;

String cifId;

}

这里是AccountRepo接口

 package com.devop.mongoRepo;

 import com.devop.models.Account;
 import org.springframework.data.mongodb.repository.*;
 import org.springframework.data.mongodb.repository.support*;
 import org.springframework.data.querydsl.QuerydslPredicateExecutor;
 import org.springframework.stereotype.Repository;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;

 @Repository
 public interface AccountRepo extends 
 ReactiveMongoRepository<Account,String> 
 ,QuerydslPredicateExecutor<Account> {

Flux<Account> findAccountByAccountNameContains(String accountName);
Mono<Account> findAccountByAccountNumberEquals(String accountNumber);

}

2 个答案:

答案 0 :(得分:0)

我找到了使用自定义workaround solutionReactiveMongoRepositoryFactoryBean的{​​{1}},它可以帮助那些正在努力解决的人

首先,您需要在反应性注释中使用repositoryFactoryBeanClass。

ReactiveMongoRepositoryFactory

CustomReactiveMongoRepositoryFactoryBean类

@EnableReactiveMongoRepositories(repositoryFactoryBeanClass = CustomReactiveMongoRepositoryFactoryBean.class)
@Configuration
public class ReactiveMongoDbHack {
}

CustomReactiveMongoRepositoryFactory类

import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.repository.support.ReactiveMongoRepositoryFactoryBean;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

public class CustomReactiveMongoRepositoryFactoryBean extends ReactiveMongoRepositoryFactoryBean {
    public CustomReactiveMongoRepositoryFactoryBean(Class repositoryInterface) {
        super(repositoryInterface);
    }

    @Override
    protected RepositoryFactorySupport getFactoryInstance(ReactiveMongoOperations operations) {
        return new CustomReactiveMongoRepositoryFactory(operations);
    }
}

import static org.springframework.data.querydsl.QuerydslUtils.QUERY_DSL_PRESENT; public class CustomReactiveMongoRepositoryFactory extends ReactiveMongoRepositoryFactory { private static MongoOperations operations; private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext; public CustomReactiveMongoRepositoryFactory(ReactiveMongoOperations operations) { super(operations); this.mappingContext = operations.getConverter().getMappingContext(); } //TODO Must set MongoOperations(MongoTemplate) public static void setOperations(MongoOperations operations) { CustomReactiveMongoRepositoryFactory.operations = operations; } @Override protected RepositoryComposition.RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata) { RepositoryComposition.RepositoryFragments fragments = RepositoryComposition.RepositoryFragments.empty(); boolean isQueryDslRepository = QUERY_DSL_PRESENT && QuerydslPredicateExecutor.class.isAssignableFrom(metadata.getRepositoryInterface()); if (isQueryDslRepository) { MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType(), metadata); fragments = fragments.append(RepositoryFragment.implemented( getTargetRepositoryViaReflection(QuerydslMongoPredicateExecutor.class, entityInformation, operations))); } return fragments; } private <T, ID> MongoEntityInformation<T, ID> getEntityInformation(Class<T> domainClass, @Nullable RepositoryMetadata metadata) { MongoPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(domainClass); return MongoEntityInformationSupport.<T, ID> entityInformationFor(entity, metadata != null ? metadata.getIdType() : null); } }

复制的MongoEntityInformationSupport类
spring-data-mongodb

PersistableMongoEntityInformation类也从import org.springframework.data.domain.Persistable; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; import org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** * Support class responsible for creating {@link MongoEntityInformation} instances for a given * {@link MongoPersistentEntity}. * * @author Christoph Strobl * @author Mark Paluch * @since 1.10 */ final class MongoEntityInformationSupport { private MongoEntityInformationSupport() {} /** * Factory method for creating {@link MongoEntityInformation}. * * @param entity must not be {@literal null}. * @param idType can be {@literal null}. * @return never {@literal null}. */ @SuppressWarnings("unchecked") static <T, ID> MongoEntityInformation<T, ID> entityInformationFor(MongoPersistentEntity<?> entity, @Nullable Class<?> idType) { Assert.notNull(entity, "Entity must not be null!"); MappingMongoEntityInformation<T, ID> entityInformation = new MappingMongoEntityInformation<T, ID>( (MongoPersistentEntity<T>) entity, (Class<ID>) idType); return ClassUtils.isAssignable(Persistable.class, entity.getType()) ? new PersistableMongoEntityInformation<>(entityInformation) : entityInformation; } }

复制
spring-data-mongodb

然后,带有查询DSL的Reactive Repository可以正常工作。

import lombok.NonNull;
import lombok.RequiredArgsConstructor;

import org.springframework.data.domain.Persistable;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;

/**
 * {@link MongoEntityInformation} implementation wrapping an existing {@link MongoEntityInformation} considering
 * {@link Persistable} types by delegating {@link #isNew(Object)} and {@link #getId(Object)} to the corresponding
 * {@link Persistable#isNew()} and {@link Persistable#getId()} implementations.
 *
 * @author Christoph Strobl
 * @author Oliver Gierke
 * @since 1.10
 */
@RequiredArgsConstructor
class PersistableMongoEntityInformation<T, ID> implements MongoEntityInformation<T, ID> {

    private final @NonNull MongoEntityInformation<T, ID> delegate;

    /*
     * (non-Javadoc)
     * @see org.springframework.data.mongodb.repository.MongoEntityInformation#getCollectionName()
     */
    @Override
    public String getCollectionName() {
    return delegate.getCollectionName();
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.mongodb.repository.MongoEntityInformation#getIdAttribute()
     */
    @Override
    public String getIdAttribute() {
    return delegate.getIdAttribute();
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.core.EntityInformation#isNew(java.lang.Object)
     */
    @Override
    @SuppressWarnings("unchecked")
    public boolean isNew(T t) {

    if (t instanceof Persistable) {
        return ((Persistable<ID>) t).isNew();
    }

    return delegate.isNew(t);
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.core.EntityInformation#getId(java.lang.Object)
     */
    @Override
    @SuppressWarnings("unchecked")
    public ID getId(T t) {

    if (t instanceof Persistable) {
        return ((Persistable<ID>) t).getId();
    }

    return delegate.getId(t);
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.core.support.PersistentEntityInformation#getIdType()
     */
    @Override
    public Class<ID> getIdType() {
    return delegate.getIdType();
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.data.repository.core.support.EntityMetadata#getJavaType()
     */
    @Override
    public Class<T> getJavaType() {
    return delegate.getJavaType();
    }
}

PS:必须在public interface AssetRepository extends ReactiveCrudRepository<Asset, String>, QuerydslPredicateExecutor<Asset> { } 设置MongoOperations,我所做的是为Mongo使用自动配置类(MongoAutoConfiguration和MongoDataAutoConfiguration),然后在方法中使用CustomReactiveMongoRepositoryFactory.setOperations来设置它。 / p>

答案 1 :(得分:0)

您可以使用ReactiveQuerydslPredicateExecutor。有关更多信息,请参见示例https://github.com/spring-projects/spring-data-examples/tree/master/mongodb/querydsl