在尝试弄清QueryDSL如何使用Java 8 Optional属性时遇到了一些麻烦。
我已经配置了QueryDSL,并且tests?field=value
之类的查询正在处理String属性。但是,由于类的某些getter具有可选的返回类型,因此生成的QTest类包含SimplePath<Optional<String>>
,而不是String属性的简单StringPath
。见下文:
Test.class
@QueryEntity
@Document(collection = "test")
public class Test {
private String field;
private String optionalField;
Test(String field,String optionalField) {
this.field = field;
this.optionalField = optionalField;
}
public String getField() {
return field;
}
public Optional<String> getOptionalField() {
return Optional.ofNullable(optionalField);
}
}
生成的QTest.class
@Generated("com.querydsl.codegen.EntitySerializer")
public class QTest extends EntityPathBase<Test> {
private static final long serialVersionUID = -609090735L;
public static final QTest test = new QTest("test");
public final StringPath field = createString("field");
public final ComparablePath<java.util.UUID> id = createComparable("id",java.util.UUID.class);
public final SimplePath<java.util.Optional<String>> optionalField = createSimple("optionalField",java.util.Optional.class);
}
数据库中的对象是这样的:
{
"field":"value","optionalField":"optionalValue"
}
控制器:
@RestController
@RequestMapping("/tests")
public class TestController {
private final TestService testService;
@Inject
public TestController (final TestService testService) {
this.testService = testService;
}
@GetMapping()
public ResponseEntity<Page<Test>> getallWithPredicate(Pageable pageable,@QuerydslPredicate(root = Test.class) Predicate predicate) {
return new ResponseEntity<>(this.testService.getallTestsWithPredicate(pageable,predicate),HttpStatus.OK);
}
@PostMapping
public ResponseEntity<Test> createTest(@RequestBody Test test) {
return new ResponseEntity<>(this.testService.createTest(test),HttpStatus.CREATED);
}
}
服务:
@Service
public class TestService {
private final TestRepository testRepository;
@Inject
public TestService(final TestRepository repo) {
this.testRepository = repo;
}
public Page<Test> getallTestsWithPredicate(Pageable pageable,Predicate predicate) {
return this.testRepository.findAll(predicate,pageable);
}
public Test createTest(Test test) {
Test savedTest = testRepository.save(test);
return savedTest;
}
}
还有存储库:
@Repository
public interface TestRepository extends JpaRepository<Test,String>,QuerydslPredicateExecutor<Test>,QuerydslBinderCustomizer<QTest> {
@Override
default public void customize(QuerydslBindings bindings,QTest root) {
bindings.bind(String.class).first((StringPath path,String value) -> path.containsIgnoreCase(value));
}
}
因此,首先,我想在我的两个字段上处理一个containsIgnoreCase。这个containsIgnoreCase在普通字段上可以正常工作。
但是当涉及到Optional时,请求如下:tests?optionalField=optionalValue
我收到了此错误消息:
java.lang.ClassCastException: com.querydsl.core.types.dsl.SimplePath cannot be cast to com.querydsl.core.types.dsl.StringPath
at org.springframework.data.querydsl.binding.QuerydslBindings$MultiValueBindingAdapter.bind(QuerydslBindings.java:506) ~[spring-data-commons-1.13.10.RELEASE.jar:na]
at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.invokeBinding(QuerydslPredicateBuilder.java:139) ~[spring-data-commons-1.13.10.RELEASE.jar:na]
at org.springframework.data.querydsl.binding.QuerydslPredicateBuilder.getPredicate(QuerydslPredicateBuilder.java:113) ~[spring-data-commons-1.13.10.RELEASE.jar:na]
...
由于此字段生成了QTest类型(SimplePath<Optional<String>>
而不是StringPath
),因此这似乎是正常现象,但事实是我找不到任何有效的处理方式此optionalField。
所以我的问题是:
QueryDSL可以使用Optional<String>
值吗?如果是这样,我应该如何查询这些字段?
谢谢您的帮助! :)