使用PageRequest查找所有文档时出现spring-data-couchbase错误

时间:2015-06-05 20:13:41

标签: java spring-data couchbase spring-data-couchbase

使用Spring Data Couchbase我创建了一个非常简单的存储库

public interface UserDao extends PagingAndSortingRepository<User, String>

这应该允许我按如下方式执行分页的findAll:

Page<User> userResult = repo.findAll(new PageRequest(1, 20));

但是总是抛出以下内容:

Exception in thread "main" java.lang.IllegalStateException: Unknown query param: Page request [number: 1, size 20, sort: null]
at org.springframework.data.couchbase.repository.query.ViewBasedCouchbaseQuery.execute(ViewBasedCouchbaseQuery.java:47)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:337)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.couchbase.repository.support.ViewPostProcessor$ViewInterceptor.invoke(ViewPostProcessor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at $Proxy14.findAll(Unknown Source)
at com.polycom.cloudAxis.proxymanagement.model.Main.main(Main.java:41)

如果我创建一个Query并使用skip / limit / startKeyDocId,但是如果可能的话,我想使用PagingAndSortingRepository,这不会发生。

知道可能出现什么问题吗?感谢所有友好的帮助:)

1 个答案:

答案 0 :(得分:0)

我也有同样的问题,这是我采取的方法。它实际上是核心实现的一个非常小的变化(目前只支持Query对象类型),基本上我所做的就是添加另一个check实例:

 if (param instanceof Query) {
            query = (Query) param;
        } else if (param instanceof Pageable) {
            pageable = (Pageable) param;
        }

然后在这里添加了分页的逻辑,它到目前为止一直在工作,但我还没有完全审查它,所以社区的任何评论都会受到赞赏。

 if (pageable != null) {

        CouchbaseClient client = operations.getCouchbaseClient();
        View view = client.getView(designDocName(), viewName());

        // Paginator p = new Paginator(client, view, query,
        // pageable.getPageSize());
        Paginator paginator = client.paginatedQuery(view, query, pageable.getPageSize());
        // now we need to goto the start point
        ViewResponse viewResponse = null;
        // views are 0 base
        int i = 0;
        while (paginator.hasNext()) {
            viewResponse = paginator.next();
            if (pageable.getPageNumber() == i++) {
                LOGGER.debug("Found the response for this page: {} ", i);
                break;
            }
        }

        if (viewResponse == null) {
            LOGGER.debug("no view response so leaving now");
            return null;
        }
        Class<?> type = method.getEntityInformation().getJavaType();

        final List result = new ArrayList(viewResponse.size());
        for (final ViewRow row : viewResponse) {
            result.add(operations.findById(row.getId(), type));
        }
        return result;

    } 

为了得到这个有线电视,我不得不做一些我不想做的事情:D,我想要覆盖一个方法,但要到达它需要我覆盖许多其他的东西,所以我最终复制了一点点代码,理想情况下我希望将此添加为https://jira.spring.io/browse/DATACOUCH-93

的一部分

整个impl在这里:

public class DCORepositoryFactory extends CouchbaseRepositoryFactory {

CouchbaseOperations                                                                 couchbaseOperations;
MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext;

public DCORepositoryFactory(CouchbaseOperations couchbaseOperations) {
    super(couchbaseOperations);
    mappingContext = couchbaseOperations.getConverter().getMappingContext();
    this.couchbaseOperations = couchbaseOperations;
}

@Override
protected Object getTargetRepository(RepositoryMetadata metadata) {
    // TODO Auto-generated method stub
    CouchbaseEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
    final DCORepository simpleCouchbaseRepository = new DCORepository(entityInformation, couchbaseOperations);

    simpleCouchbaseRepository.setViewMetadataProvider(ViewPostProcessor.INSTANCE.getViewMetadataProvider());
    return simpleCouchbaseRepository;
}

@Override
protected QueryLookupStrategy getQueryLookupStrategy(QueryLookupStrategy.Key key) {
    return new CouchbaseQueryLookupStrategy();
}

/**
 * Currently, only views are supported. N1QL support to be added.
 */
private class CouchbaseQueryLookupStrategy implements QueryLookupStrategy {
    @Override
    public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
        CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method, metadata, mappingContext);
        return new PagingViewBasedCouchbaseQuery(queryMethod, couchbaseOperations);
    }
}

private static class PagingViewBasedCouchbaseQuery extends ViewBasedCouchbaseQuery {

    private static final org.slf4j.Logger   LOGGER  = org.slf4j.LoggerFactory
                                                            .getLogger(DCORepositoryFactory.PagingViewBasedCouchbaseQuery.class);

    private CouchbaseOperations             operations;
    private CouchbaseQueryMethod            method;

    public PagingViewBasedCouchbaseQuery(CouchbaseQueryMethod method, CouchbaseOperations operations) {
        super(method, operations);
        this.operations = operations;
        this.method = method;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.data.couchbase.repository.query.
     * ViewBasedCouchbaseQuery#execute(java.lang.Object[]) added the ability
     * to support paging
     */
    @Override
    public Object execute(Object[] runtimeParams) {
        Query query = null;
        Pageable pageable = null;
        for (Object param : runtimeParams) {
            if (param instanceof Query) {
                query = (Query) param;
            } else if (param instanceof Pageable) {
                pageable = (Pageable) param;
            } else {
                throw new IllegalStateException(
                        "Unknown query param: (btw null is also not allowed and pagable cannot be null) " + param);
            }
        }

        if (query == null) {
            query = new Query();
        }
        query.setReduce(false);
        if (pageable != null) {

            CouchbaseClient client = operations.getCouchbaseClient();
            View view = client.getView(designDocName(), viewName());

            // Paginator p = new Paginator(client, view, query,
            // pageable.getPageSize());
            Paginator paginator = client.paginatedQuery(view, query, pageable.getPageSize());
            // now we need to goto the start point
            ViewResponse viewResponse = null;
            // views are 0 base
            int i = 0;
            while (paginator.hasNext()) {
                viewResponse = paginator.next();
                if (pageable.getPageNumber() == i++) {
                    LOGGER.debug("Found the response for this page: {} ", i);
                    break;
                }
            }

            if (viewResponse == null) {
                LOGGER.debug("no view response so leaving now");
                return null;
            }
            Class<?> type = method.getEntityInformation().getJavaType();

            final List result = new ArrayList(viewResponse.size());
            for (final ViewRow row : viewResponse) {
                result.add(operations.findById(row.getId(), type));
            }
            return result;

        } else {
            return operations.findByView(designDocName(), viewName(), query, method.getEntityInformation()
                    .getJavaType());
        }
    }

    /**
     * Returns the best-guess design document name.
     *
     * @return the design document name.
     */
    private String designDocName() {
        if (method.hasViewAnnotation()) {
            return method.getViewAnnotation().designDocument();
        } else {
            return StringUtils.uncapitalize(method.getEntityInformation().getJavaType().getSimpleName());
        }
    }

    /**
     * Returns the best-guess view name.
     *
     * @return the view name.
     */
    private String viewName() {
        if (method.hasViewAnnotation()) {
            return method.getViewAnnotation().viewName();
        } else {
            return StringUtils.uncapitalize(method.getName().replaceFirst("find", ""));
        }
    }
}

@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata repositoryMetadata) {
    return DCORepository.class;
}

}