카테고리 없음

Spring Cassandra UDT converting 삽질 과정

스프링피바라기 2022. 9. 12. 19:30

안녕하세요.

Spring Data Cassandra 를 사용하면서 삽질한 과정을 정리해보고자 합니다.

 

우선 배경설명을 드리겠습니다.

Spring cassandra 2.6.11

 

CREATE TABLE table (
 partition_key text,
 clusering_key_1 text,
 detail frozen<Detail>,
 primary key (partition_key, clusering_key_1)
) with clustering order by (clustering_key_1 desc);

CREATE TYPE Detail (
 name text,
 male boolean
)

 

테이블은 위와 같이 구성되어 있으며,

UDT (user defined type) 은 Detail 이라는 이름으로 생성했습니다.

 

제가 접한 문제점은

CassandraRepository 의 save() (혹은 CassnadraTemplate 의 insert() )  과정에 있어,

UDT인 Detail 이 converting 을 수행할 수 없다는 오류였습니다.

 

GenericConverionService 에서 

sourceType 으로는 제가 정의한 클래스가,

targetType 으로는 UdtValue 인터페이스가 정의가되어

둘이 매칭이 되지 않은 NO_MATCH 상태가 되고, converting 을 할 수 없다고 에러를 발생시킨것입니다.

 

 

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type

 

 

위와 같은 문제를 해결한 과정과 원인에 대해서 설명을 드리겠습니다.

 

문제가 된 부분은 바로

 

@CassandraType(type = CassandraType.Name.UDT)

해당 어노테이션 이었습니다.

 

Spring Cassandra 에서 UDT type 을 사용할 때는 Embedded 방식을 사용하게 되는데,

이때 Class 상위에 

@UserDefinedType

어노테이션을 붙혀 해당 클래스가 UDT 로 활용됨을 명시합니다.

 

그러나 저는 여기서 Embedded 되는 클래스 가 선언된 클래스내에서도 

위에서 문제가 된 어노테이션을 선언해주었습니다.

 

Cassandra Config 과정에서 선언된 MappingCassandraConverter 가

@CassandraColumnType 으로 명시된 field 들을 불러와 

해당 필드의 타입을 source 로, 선언한 어노테이션 안의 타입을 target 으로 선언하게 되는데요,

 

 

이때 Name.UDT 의 대상은 UdtValue 인터페이스가 되고, 어노테이션의 대상이 되는 필드는 Detail 이라는 클래스 이므로, 

이 둘을 converting 할 수 있는 방법이 없어 예외가 발생하는 것 입니다.

 

우리가 UDT 타입을 쓰면서도 원하는 것은

클래스 자체보다는 embedded 된 클래스 내부의 필드이므로, 

내부 필드들이 convert 될 수 있게

@CassandraType 어노테이션만 지운다면 해당 문제는 해결됩니다.