Specification
DBでを使用して彼の名前で列挙型を検索しようとするとSpring @Repository
、次の例外が発生します。
Caused by: java.lang.IllegalArgumentException: Parameter value [HELLO] did not match expected type [application.springEnum.Hello (n/a)]
しかし、DBで保存された列挙型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] at org.hibernate.query.internal.QueryParameterBindingImpl.setBindValue(QueryParameterBindingImpl.java:55)〜[hibernate-core-5.2.16.Final.jar:5.2 .16.Final] at 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
リフレクションを使用しての要素がフェッチされます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加