我使用Spring数据来管理REST API。我的postgresql数据库中的所有表都有一个UUID类型的主键。我能够保留这些数据但无法获取它。下面是我正在使用的代码和我面临的问题。
MyTableParent.java
@MappedSuperclass
public class MyTableParent {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(
name = "uuid",
strategy = "com.mypackage.UUIDGenerator",
parameters = {
@Parameter(
name = UUID_NAMESPACE,
value = "something"
)
}
)
private UUID id;
// Constructor getter setter
}
MyTable.java
@Entity
@Table(name = "my_table")
public class MyTable extends MyTableParent {
private String name;
// constructor getter setter
}
这是我的表
的服务类 TableService.java
@Service("tableservice")
public class TableService {
private TableRepository tableRepository;
public TableService(TableRepository tableRepository) {
this.tableRepository = tableRepository;
}
public List<MyTable> read(MultiValueMap<String, String> queryParams) {
return this.tableRepository.findAll(TableSpecification.searchByParams(queryParams));
}
public MyTable read(UUID id) {
return this.tableRepository.findById(id).orElse(null);
}
}
正如您所看到的,我正在使用存储库对象以及规范。我已经将存储库定义为
@Repository
interface TableRepository extends JpaRepository<MyTable, UUID>, JpaSpecificationExecutor<MyTable> {
}
规范创建为
public class TableSpecification {
public static <T> Specification<T> searchByParams(MultiValueMap<String, String> queryMap) {
return (Specification<T>) (Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) -> {
Set<Map.Entry<String, List<String>>> fields = queryMap.entrySet();
if (queryMap.size() != 0) {
List<Predicate> predicates = new ArrayList<>();
for (MultiValueMap.Entry<String, List<String>> field : fields) {
List<String> params = new ArrayList<>(field.getValue());
String property = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, field.getKey());
Expression<String> expression = root.get(property);
predicates.add(expression.in(params));
}
return criteriaBuilder.and(predicates.toArray(new Predicate[]{}));
}
return null;
};
}
}
第一个问题出现在我致电read(MultiValueMap)
时。假设我的请求参数为/my_table?id=12345678-1234-1234-1234-123456789012
,触发代码this.tableRepository.findAll(TableSpecification.searchByParams(queryParams))
其中queryParams
MultiValueMap
。这是一个错误
java.lang.IllegalArgumentException: Parameter value [12345678-1234-1234-1234-123456789012] did not match expected type [java.util.UUID (n/a)]
at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:54) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:27) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.query.internal.QueryParameterBindingImpl.validate(QueryParameterBindingImpl.java:90) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.query.internal.QueryParameterBindingImpl.setBindValue(QueryParameterBindingImpl.java:55) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.query.internal.AbstractProducedQuery.setParameter(AbstractProducedQuery.java:486) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.query.internal.AbstractProducedQuery.setParameter(AbstractProducedQuery.java:104) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.query.criteria.internal.compile.CriteriaCompiler$1$1.bind(CriteriaCompiler.java:119) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.query.criteria.internal.CriteriaQueryImpl$1.buildCompiledQuery(CriteriaQueryImpl.java:368) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:149) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3616) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:203) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
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:564) ~[na:na]
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350) ~[spring-orm-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at com.sun.proxy.$Proxy125.createQuery(Unknown Source) ~[na:na]...
所以我尝试检查findById
方法。这导致this.tableRepository.findById(id).orElse(null)
返回null,这意味着查找也失败了。
我不知道如何处理这个问题。请指教。
N.B。我可以正确获取 name
字段的记录。我有一种预感,春天数据正在弄乱某些类型。
修改 即使对于字符串类型字段也不起作用。
答案 0 :(得分:2)
Parameter value [12345678-1234-1234-1234-123456789012] did not match expected type [java.util.UUID (n/a)]
错误表示从数据库读取的值无法映射到相应的字段类型。
请参阅HHH-9562 Dialect specific UUID handling改进了Hibernate 5中的UUID处理。您的问题可能通过@Column(columnDefinition = "uuid", updatable = false)
注释解决。
@Id
@Column(columnDefinition = "uuid", updatable = false)
@GeneratedValue(generator = "uuid")
@GenericGenerator(
name = "uuid",
strategy = "com.mypackage.UUIDGenerator",
parameters = {
@Parameter(
name = UUID_NAMESPACE,
value = "something"
)
}
)
private UUID id;
如果需要进一步调试,请检查您在代码中配置的PostgreSQL Dialect类,并确保实体中的字段定义正确声明了PostgreSQL UUID列类型。 UUID存在许多问题,例如HHH-9577
答案 1 :(得分:1)
我正在使用Hibernate 5.3.11并遇到相同的问题。多亏了答案Luca Basso Ricci in 'FindByUUID() using Spring Data's JPA Repository',该问题已得到解决。
(对我而言)解决方案是在UUID字段中添加以下注释:
https://example.com/users?sortBy=createdAt:asc,name:desc
答案 2 :(得分:0)
尝试确保您的映射实体类以及列表类型中的数据类型。请参考此休眠映射类型 https://examples.javacodegeeks.com/enterprise-java/hibernate/hibernate-mapping-types-example/