使用stringValue或like进行过滤时,带有MongoDB的QueryDSL无法将属性从Long类型序列化为String

问题描述

我正在尝试使用QueryDSL,MongoDB和Spring Data查询/过滤一些简单数据。

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-mongodb</artifactId>
        <version>2.2.0.M4</version>
</dependency>
<dependency>
        <groupId>com.querydsl</groupId>
        <version>4.2.1</version>
        <artifactId>querydsl-core</artifactId>
</dependency>
<dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-apt</artifactId>
        <version>4.2.1</version>
</dependency>
<dependency>
        <groupId>com.querydsl</groupId>
        <artifactId>querydsl-mongodb</artifactId>
        <version>4.2.1</version>
</dependency>
@Getter
@Setter
@Document
public class Library {

  private Address address;

  @NotNull
  private Long books = 4L;

  ...

}

我的第一种方法

public Page<Library> findAll(Predicate predicate,MultiValueMap<String,String> parameters) {
    final QLibrary qLibrary = QLibrary.library;
    final BooleanBuilder builder = new BooleanBuilder();

    if (parameters.containsKey("booksCount")) {
      builder.and(qLibrary.booksCount.stringValue().startsWith(parameters.getFirst("booksCount")));
    }

    final BooleanExpression expression = (BooleanExpression) predicate;
    return repository.findAll(expression.and(builder.getValue()),Pageable.unpaged());
}

第二种方法

public class LibraryBindings implements QuerydslBinderCustomizer<QLibrary> {

    @Override
    public void customize(QuerydslBindings bindings,QLibrary root) {
        bindings.bind(root.booksCount).first(new SingleValueBinding<NumberPath<Long>,Long>() {
            @Override
            public Predicate bind(NumberPath<Long> path,Long value) {
                return path.stringValue().startsWith(value.toString());
            }
        });
    }

}

我的第三种方法

public class LibraryBindings implements QuerydslBinderCustomizer<QLibrary> {

    @Override
    public void customize(QuerydslBindings bindings,Long value) {
                return path.like(value.toString());
            }
        });
    }

}

使用上述方法,我会遇到一个例外:

    java.lang.UnsupportedOperationException: Illegal operation str(library.booksCount)
    at org.springframework.data.mongodb.repository.support.MongodbDocumentSerializer.visit(MongodbDocumentSerializer.java:323) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.MongodbDocumentSerializer.visit(MongodbDocumentSerializer.java:54) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at com.querydsl.core.types.OperationImpl.accept(OperationImpl.java:83) ~[querydsl-core-4.2.1.jar:na]
    at org.springframework.data.mongodb.repository.support.MongodbDocumentSerializer.asDBValue(MongodbDocumentSerializer.java:146) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.MongodbDocumentSerializer.asDBKey(MongodbDocumentSerializer.java:138) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.SpringDataMongodbSerializer.asDBKey(SpringDataMongodbSerializer.java:158) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.MongodbDocumentSerializer.visit(MongodbDocumentSerializer.java:227) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.MongodbDocumentSerializer.visit(MongodbDocumentSerializer.java:54) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at com.querydsl.core.types.OperationImpl.accept(OperationImpl.java:83) ~[querydsl-core-4.2.1.jar:na]
    at org.springframework.data.mongodb.repository.support.MongodbDocumentSerializer.handle(MongodbDocumentSerializer.java:58) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.MongodbDocumentSerializer.visit(MongodbDocumentSerializer.java:185) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.MongodbDocumentSerializer.visit(MongodbDocumentSerializer.java:54) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at com.querydsl.core.types.OperationImpl.accept(OperationImpl.java:83) ~[querydsl-core-4.2.1.jar:na]
    at org.springframework.data.mongodb.repository.support.MongodbDocumentSerializer.handle(MongodbDocumentSerializer.java:58) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.MongodbDocumentSerializer.toQuery(MongodbDocumentSerializer.java:69) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.QuerydslAbstractMongodbQuery.createquery(QuerydslAbstractMongodbQuery.java:166) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.QuerydslFetchableMongodbQuery.createquery(QuerydslFetchableMongodbQuery.java:197) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.QuerydslFetchableMongodbQuery.createquery(QuerydslFetchableMongodbQuery.java:190) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.QuerydslFetchableMongodbQuery.fetch(QuerydslFetchableMongodbQuery.java:111) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.SpringDataMongodbQuery.fetch(SpringDataMongodbQuery.java:28) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.mongodb.repository.support.QuerydslMongoPredicateExecutor.findAll(QuerydslMongoPredicateExecutor.java:160) ~[spring-data-mongodb-2.2.0.M4.jar:2.2.0.M4]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
    at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:359) ~[spring-data-commons-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200) ~[spring-data-commons-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:641) ~[spring-data-commons-2.2.0.M4.jar:2.2.0.M4]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.M2.jar:5.2.0.M2]

所有其他过滤器/查询均正常运行(比较字符串,将数字与数字进行比较或将布尔值与布尔值进行比较,等等)。 QueryDSL配置正确。

假定用户可以按booksCount过滤对象,并且他有四个可用的库对象:

  1. 一本书
  2. 有7本书
  3. 有12本书
  4. 有127本书。

用户按图书数量和类型X筛选时,我要显示数量Y:

  1. 用户键入1时,它应显示具有booksCount 1、12、127的对象。
  2. 用户键入12时,它应显示带有booksCount 12、127的对象。
  3. 用户键入7时,应显示带有booksCount 7的对象。
  4. 用户键入13时,它不应显示任何对象。
  5. 用户键入126时,它不应显示任何对象。
  6. 用户键入127时,它应显示带有booksCount 127的对象。

就这么简单。我的问题是:

  1. 为什么会发生此异常,我该如何解决
  2. 如果这是一个错误(请回答否),如何在这种架构下实现相同的行为?

谢谢。

解决方法

据我们所知,GET groups,challenges/_search { "size": 10,"_source": false,// or ["whatever","data","you","need"] "query": { "bool": { "minimum_should_match": 1,"should": [ {"bool": {"must": [ {"term": {"_index": "groups"}},{"term": {"code": "zamboni"}},{"term": {"name": "zamboni"}},{"term": {"description": "zamboni"}},{"terms": {"id": [1,2,3]}} ]}},{"bool": {"must": [ {"term": {"_index": "challenges"}},{"terms": {"id": [3,4,5]}} ]}} ] } } } 查询不支持将数字强制转换为字符串,因此,当前使用DBObject时不支持stringValue()操作。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...