gpt4 book ai didi

java - Spring CriteriaBuilder 按名称搜索枚举

转载 作者:行者123 更新时间:2023-11-29 09:27:11 25 4
gpt4 key购买 nike

当我尝试使用 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")
);
}
}

如有解释,我将不胜感激。

最佳答案

您正在尝试比较 EnumString

试试这个方法:

List<DTO> result = connector.findAll((root, query, cb) ->
cb.equal(root.get("helloEnum"), Hello.HELLO);

我将尝试提供一些解释为什么会发生这种情况。 Hibernate 使用 Reflection 从数据库中获取 ResultSetClass 签名。

观察堆栈跟踪你会看到类似的东西:

org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:54)~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] atorg.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:27)~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] atorg.hibernate.query.internal.QueryParameterBindingImpl.validate(QueryParameterBindingImpl.java:90)~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] atorg.hibernate.query.internal.QueryParameterBindingImpl.setBindValue(QueryParameterBindingImpl.java:55)~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] atorg.hibernate.query.internal.AbstractProducedQuery.setParameter(AbstractProducedQuery.java:486)~[hibernate-core-5.2.16.Final.jar:5.2.16.Final] atorg.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 的元素.

关于java - Spring CriteriaBuilder 按名称搜索枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50215909/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com