java - Spring CriteriaBuilder 按名称搜索枚举
问题描述
当我尝试Specification
在我的数据库中使用他的名字搜索枚举时Spring @Repository
,出现以下异常:
Caused by: java.lang.IllegalArgumentException: Parameter value [HELLO] did not match expected type [application.springEnum.Hello (n/a)]
但是在数据库中,枚举保存为VARCHAR(255)
为什么我可以用 搜索枚举String
,为什么它需要一个枚举类型?
DTO 类
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DTO {
@Id
private String id;
@Enumerated(EnumType.STRING)
private Hello helloEnum; // My Enum
}
数据库连接器
@Repository
public interface Connector extends JpaRepository<DTO, String>, JpaSpecificationExecutor<DTO> {
}
起动机
@Component
public class Starter {
@Autowired
private Connector connector;
@PostConstruct
public void init(){
// Create DTO entity
DTO dto = DTO.builder()
.id(UUID.randomUUID().toString())
.helloEnum(Hello.HELLO)
.build();
// Save the entity in the db
connector.save(dto);
// Search by the name, here I get the excpetion
List<DTO> result = connector.findAll((root, query, cb) ->
cb.equal(root.get("helloEnum"), "HELLO")
);
}
}
我将不胜感激。
解决方案
您正在尝试比较Enum
和String
。
试试这个方法:
List<DTO> result = connector.findAll((root, query, cb) ->
cb.equal(root.get("helloEnum"), Hello.HELLO);
我将尝试提供一些解释为什么会发生这种情况。Hibernate使用. ResultSet
_Class
Reflection
观察堆栈跟踪,您会看到如下内容:
org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:54) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.query.spi.QueryParameterBindingValidator.validate (QueryParameterBindingValidator.java:27) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] at org.hibernate.query.internal.QueryParameterBindingImpl.validate(QueryParameterBindingImpl.java:90) ~[hibernate- core-5.2.16.Final.jar:5.2.16.Final] 在 org.hibernate.query.internal.QueryParameterBindingImpl.setBindValue(QueryParameterBindingImpl.java:55) ~[hibernate-core-5.2.16.Final.jar:5.2 .16.Final] 在 org.hibernate.query.internal.AbstractProducedQuery.setParameter(AbstractProducedQuery.java:486) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] 在 org.hibernate.query .internal.AbstractProducedQuery.setParameter(AbstractProducedQuery。java:104) ~[hibernate-core-5.2.16.Final.jar:5.2.16.Final]
Hibernate 在设置参数之前会执行一系列验证。
这是初始化根本原因的最后一个方法Exception
:
public <P> void validate(Type paramType, Object bind, TemporalType temporalType) {
if ( bind == null || paramType == null ) {
// nothing we can check
return;
}
final Class parameterType = paramType.getReturnedClass();
if ( parameterType == null ) {
// nothing we can check
return;
}
if ( Collection.class.isInstance( bind ) && !Collection.class.isAssignableFrom( parameterType ) ) {
// we have a collection passed in where we are expecting a non-collection.
// NOTE : this can happen in Hibernate's notion of "parameter list" binding
// NOTE2 : the case of a collection value and an expected collection (if that can even happen)
// will fall through to the main check.
validateCollectionValuedParameterBinding( parameterType, (Collection) bind, temporalType );
}
else if ( bind.getClass().isArray() ) {
validateArrayValuedParameterBinding( parameterType, bind, temporalType );
}
else {
if ( !isValidBindValue( parameterType, bind, temporalType ) ) {
throw new IllegalArgumentException(
String.format(
"Parameter value [%s] did not match expected type [%s (%s)]",
bind,
parameterType.getName(),
extractName( temporalType )
)
);
}
}
}
private static boolean isValidBindValue(Class expectedType, Object value, TemporalType temporalType)
有一堆检查的方法会返回,false
因为您期望的类型是class com.whatever.Hello
并且要检查的值是HELLO
什么String
,但是Enum
类型和String
不兼容!
如果您Enum
在搜索条件中输入正确,则验证将通过,因为private static boolean isValidBindValue(Class expectedType, Object value, TemporalType temporalType)
包含isInstance
将通过的检查:
else if ( expectedType.isInstance( value ) ) {
return true;
}
在所有检查之后,Hibernate 从 中提取值ResultSet
并构建List
,在这种特殊情况下,List
使用反射获取 的元素。
推荐阅读
- r - r igraph - 查找连接选定节点的边
- javascript - 如何使用 Ajax 的 PUT 请求来更改变量的值?
- scala - 如何在Scala中快速编写“过滤满足给定函数的第一个/最后n个元素”?
- docker - phpMyAdmin 没有连接到 MariaDB 并且 MariaDB 没有在 docker compose 上设置默认的 MYSQL_ROOT_PASSWORD 变量
- swift - Swift如何手动设置photoLibrary和相机授权?
- javascript - react-native-firebase/messaging 的 sendMessage() 在 6.2.0 版本中不起作用
- powerpoint - 是否有一个 openTBS 命令来编写/更新 pptx 幻灯片的注释部分?
- java - 无法以编程方式隐藏弧形菜单中的 fab 按钮。尝试上传.hide(); 无法弄清楚如何隐藏fab按钮
- sql - 用于计算总数的 SQL 查询
- tensorflow2.0 - 加载 tensorflow2.0 模型时出现错误