InvalidDataAccessApiUsageException: 参数值 [...] 与预期类型 [java.util.UUID (n/a)] 不匹配

Edw*_*ard 5 java predicate criteria-api spring-data-jpa

我正在使用 Criteria API 使用过滤器构建命名查询。它适用于普通的字符串比较,但在过滤 UUID 时会引发以下错误:

org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [67279329-5096-4196-9E73-748B33122CE2] did not match expected type [java.util.UUID (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [67279329-5096-4196-9E73-748B33122CE2] did not match expected type [java.util.UUID (n/a)]
Run Code Online (Sandbox Code Playgroud)

有几个问题解决了这个问题,但都没有奏效,我尝试了以下方法:

  • 添加@Column(name = "id", updatable = false, nullable = false)到实体字段
  • 添加@Type(type="org.hibernate.type.UUIDCharType")到实体字段
  • 添加@Type(type="uuid-char")到实体字段

Foo 实体:

org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [67279329-5096-4196-9E73-748B33122CE2] did not match expected type [java.util.UUID (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [67279329-5096-4196-9E73-748B33122CE2] did not match expected type [java.util.UUID (n/a)]
Run Code Online (Sandbox Code Playgroud)

SQL 变体:

@Entity
//lombok stuff
public class Foo {

    @Id
    private UUID id;
    private String name;
    //...
}
Run Code Online (Sandbox Code Playgroud)

FooController:

CREATE TABLE foo
(
    id                    UUID    NOT NULL PRIMARY KEY,
    name                  VARCHAR NOT NULL,
    ...
);
Run Code Online (Sandbox Code Playgroud)

Foo规格:

@GetMapping(value = "/foo")
public ResponseEntity<List<Foo>> findFoos(@RequestParam Map<String, String> filterArguments) {
    FooFilter filter = filterMapper.map(filterArguments);
    FooSpecification spec = new FooSpecification(filter);

    List<Foo> foos = fooRepo.findAll(spec);
    //...
}
Run Code Online (Sandbox Code Playgroud)

addAndPredicate 是一个简单的辅助方法,它只使用criteriaBuilder.and(predicate,newPredicate)

FooFilter 只有字符串字段

Edw*_*ard 2

我使用 Criteria API 提供的类型转换解决了该问题。

前:

addAndPredicate(..., ..., cb.like(cb.upper(foo.get("id")), ...));
Run Code Online (Sandbox Code Playgroud)

后:

addAndPredicate(..., ..., cb.like(cb.upper(foo.get("id").as(String.class)), ...));
Run Code Online (Sandbox Code Playgroud)

来自: https: //docs.oracle.com/javaee/6/api/javax/persistence/criteria/Expression.html#as(java.lang.Class)

<X> Expression<X> as(java.lang.Class<X> type)

对表达式执行类型转换,返回一个新的表达式对象。此方法不会引起类型转换:运行时类型不会更改。警告:可能会导致运行时失败。