【发布时间】:2018-04-29 08:33:33
【问题描述】:
我的团队维护着一个使用 Spring Boot、Spring Data、Thymeleaf 和 JPA/Hibernate 构建的 Web 应用。我们最近遇到了一个 Thymeleaf 模板 SpringEL 表达式由于类型转换问题而无法评估的问题:
原因:org.springframework.core.convert.ConverterNotFoundException:找不到能够从类型 [com.xyz.app.model.Employee_$$_jvst7ca_34] 转换为类型 [java.lang.String] 的转换器
表达式是 ${{employee}},其中employee 是一个由 Spring 控制器放入模型的实体。通过对 Spring Data 存储库的简单调用来检索员工实体:
@ModelAttribute("employee")
public Employee getEmployee(@PathVariable("employeeId") long employeeId) {
return employeeRepository.findOne(employeeId);
}
在调试时,我注意到返回的 Employee 实体实际上是一个 Hibernate 代理,正如您在日志中的异常原因中看到的那样 - Employee 类具有 javassist 后缀:_$$_jvst7ca_34
Spring Data 使用 Spring 的 GenericConversionService 注册 DomainClassConverter,当 @EnableSpringDataWebSupport 注解存在时,它应该将实体转换为像 ${{employee}} 这样的表达式的 ID。 Spring Boot 提供了一个自动配置类SpringDataWebAutoConfiguration,它默认启用此功能。我确认我们的应用程序应用了这个自动配置类。
我还通过调试确认 GenericConversionService 在尝试从 Employee_$$_jvst7ca_34 转换为 String 时检索到 DomainClassConverter.ToIdConverter。但是 DomainClassConverter.ToIdConverter.matches(sourceType, targetType) 返回 false,因此不使用转换器。它返回 false,因为它在 Repositories 中找不到类型为 Employee_$$_jvst7ca_34 的存储库。我在调试器中看到存储库列表中唯一的员工存储库是用于Employee。
这是DomainClassConverter 中的错误吗?它不应该能够检索代理的存储库吗?似乎代理应该很常见,因为任何具有惰性集合(推荐的集合类型)的实体都会作为代理返回。还是我们做错了什么?任何提示将不胜感激!
【问题讨论】:
标签: hibernate spring-boot spring-data thymeleaf