Spring BootとCassandraで列挙型を序数として永続化する方法は?

トビアスヘルマン

私のエンティティの列挙型フィールドに追加しました@CassandraType(type = DataType.Name.INT)ただし、列挙型の序数ではなく、文字列表現が、Cassandraに送信されるステートメントで使用されます。したがって、次のエラーが発生します。

org.springframework.data.cassandra.CassandraInvalidQueryException: SessionCallback; CQL [INSERT INTO thing (thing_id,some_enum) VALUES (1,'Foo');]; Expected 4 or 0 byte int (3); nested exception is com.datastax.driver.core.exceptions.InvalidQueryException: Expected 4 or 0 byte int (3)

以下に、問題を再現した最小限の例を示します。

私は何が間違っているのですか?

test/src/main/kotlin/enumtest/Application.kt

package enumtest

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication


@SpringBootApplication
class Application

fun main(args: Array<String>) {
    runApplication<Application>(*args)
}

test/src/main/kotlin/enumtest/SomeEnum.kt

package enumtest


enum class SomeEnum {
    Foo,
    Bar
}

test/src/main/kotlin/enumtest/Thing.kt

package enumtest

import com.datastax.driver.core.DataType
import org.springframework.data.cassandra.core.cql.PrimaryKeyType
import org.springframework.data.cassandra.core.mapping.CassandraType
import org.springframework.data.cassandra.core.mapping.Column
import org.springframework.data.cassandra.core.mapping.PrimaryKeyColumn
import org.springframework.data.cassandra.core.mapping.Table


@Table("thing")
@Suppress("unused")
class Thing(

    @PrimaryKeyColumn(name = "thing_id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
    var thingId: Long,

    @CassandraType(type = DataType.Name.INT)
    @Column("some_enum")
    var someEnum: SomeEnum

)

test/src/main/kotlin/enumtest/ThingRepository.kt

package enumtest

import org.springframework.data.cassandra.repository.CassandraRepository
import org.springframework.stereotype.Repository

@Repository
interface ThingRepository : CassandraRepository<Thing, Long>

test/src/main/resources/application.yml

spring:
  data:
    cassandra:
      contact-points: localhost
      port: 9142
      keyspace_name: enumtest

test/src/test/kotlin/enumtest/PersistenceTest.kt

package enumtest

import org.cassandraunit.spring.CassandraDataSet
import org.cassandraunit.spring.CassandraUnitDependencyInjectionTestExecutionListener
import org.cassandraunit.spring.EmbeddedCassandra
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.TestExecutionListeners
import org.springframework.test.context.junit4.SpringRunner

@RunWith(SpringRunner::class)
@SpringBootTest
@TestExecutionListeners(
    listeners = [CassandraUnitDependencyInjectionTestExecutionListener::class],
    mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
)
@CassandraDataSet(value = ["cql/cassandra_schema.cql"], keyspace = "enumtest")
@EmbeddedCassandra
class PersistenceTest {
    @Autowired
    lateinit var thingRepository: ThingRepository

    @Test
    fun `test save`() {
        thingRepository.save(Thing(1, SomeEnum.Foo))
        val things = thingRepository.findAll()
        Assert.assertEquals(1, things.size)
        val thing = things[0]
        Assert.assertEquals(SomeEnum.Foo, thing.someEnum)
    }
}

test/src/test/resources/cql/cassandra_schema.cql

CREATE KEYSPACE IF NOT exists enumtest
WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':1};

CREATE TABLE IF NOT exists enumtest.thing (
    thing_id     bigint,
    some_enum    int,
    PRIMARY KEY (thing_id)
);

test/build.gradle

plugins {
    id 'org.springframework.boot' version '2.1.4.RELEASE'
    id 'org.jetbrains.kotlin.jvm' version '1.3.30'
    id 'org.jetbrains.kotlin.plugin.spring' version '1.3.30'
}

apply plugin: 'io.spring.dependency-management'

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
    maven { url "https://repository.apache.org/snapshots/" }
}

dependencies {
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter'
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-cassandra'
    implementation group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib-jdk8'
    implementation group: 'org.jetbrains.kotlin', name: 'kotlin-reflect'

    testImplementation group: 'org.cassandraunit', name: 'cassandra-unit-spring', version: '3.5.0.1'
    testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test'
}

compileKotlin {
    kotlinOptions {
        freeCompilerArgs = ['-Xjsr305=strict']
        jvmTarget = '1.8'
    }
}

compileTestKotlin {
    kotlinOptions {
        freeCompilerArgs = ['-Xjsr305=strict']
        jvmTarget = '1.8'
    }
}

実験を容易にするためのダウンロードとしての最小限の例の完全版は次のとおりです:https://drive.google.com/open ?id = 1zzIDhbWycaj4WXrze2sAmw8xRPacA8Js

編集:バグのようですので、Jiraの問題を開きまし

chas spenlau

私はこれをかなり長い間機能させようとしてきました、そして私はついにそれを手に入れたようです!

私はあなたがコーデックで持っていたのと同じ問題に遭遇していました...なぜそれが機能しないのか分かりません。彼らのドキュメントによると、あなたはそれを正確に正しく行っていました。

そこで、独自のCassandra WriteConverterを実装しました。下記参照

@Configuration
class CassandraConfig(val cluster: Cluster){

    @Bean
    fun setCustomCassandraConversions() = CassandraCustomConversions(listOf(EnumWriteConverter.INSTANCE, EnumReadConverter.INSTANCE))

    @WritingConverter
    enum class EnumWriteConverter : Converter<Enum<MyEnum>, Int> {
        INSTANCE;
        override fun convert(source: Enum<MyEnum>) = source.ordinal
    }
     @ReadingConverter
    enum class EnumReadConverter : Converter<Int, Enum<MyEnum>> {
        INSTANCE;
        override fun convert(source: Int) = MyEnum.values()[source]
    }
}

これは、Cassandraに対して行うすべての書き込みで、オーバーライドされたコンバーターを使用して、MyEnum型のすべての列挙型をIntに変換する必要があります。これにより、さまざまなタイプの列挙型に対してこれらが複数ある可能性があります。何らかの理由で、常にすべての列挙型を変換するのではなく、それらから他のカスタム値を記述したい場合があります。

これがうまくいくことを願っています!

編集各コンバーターでINSTANCEの{}を削除し、ReadingConverterをCassandraCustomConversionsに登録する際の変更に注意してください

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Thymeleaf + Spring MVC-フォームのリストまたは列挙型から値を永続化する方法は?

分類Dev

Thymeleaf + Spring MVC-フォームのリストまたは列挙型から値を永続化する方法は?

分類Dev

Javaを使用して列挙型でSpring Bootで親子Json応答を作成する方法

分類Dev

Spring Boot Restレスポンスでブール値を文字列としてシリアル化する方法は?

分類Dev

Spring Entityクラス内でArrayListを永続化する方法は?

分類Dev

Springを使用して列挙型の値を取得する方法

分類Dev

Spring-BootとJPAを使用して、永続化されていない別のエンティティの複数の同一インスタンスを含む新しいエンティティを永続化するにはどうすればよいですか?

分類Dev

SSLとSpring Bootを使用してPostgresQLに接続する方法

分類Dev

Spring Boot:リポジトリを使用して1対多の関係を個別に永続化する方法

分類Dev

Spring Bootと組み込みTomcatでセッションの永続化を有効にする

分類Dev

Spring Bootで列挙型の適切な検証エラーを返す方法は?

分類Dev

Spring Boot-文字列から列挙への変換は、列挙の値とインデックスを受け入れます。数値入力を拒否して列挙値のみを受け入れる方法は?

分類Dev

Springサービス内で永続化すると、TransactionRequiredExceptionが発生します

分類Dev

Java Spring Boot、JPA、Hibernateは、OBJECT型のオブジェクトを永続化します

分類Dev

Hibernate / Spring Bootを使用してJSONファイルをJSONデータ型としてmysqlに保存する方法は?

分類Dev

Springの値として列挙型を使用してマップを挿入する

分類Dev

Spring BootとMongoDBで「_class」列を削除する方法は?

分類Dev

Spring Data Cassandraを使用してjava.util.Date値をCassandra日付型列に挿入する方法は?

分類Dev

Spring Data JPAでJSR-310タイプを永続化する方法は?

分類Dev

Spring BootでMapstructを使用して親と子をマップする方法は?

分類Dev

Springを使用しているときに複数のJPA EntityManager(永続性ユニット)を挿入する方法

分類Dev

spring-data-elasticsearchを使用してJava列挙型を保存する方法

分類Dev

Spring BootとSpring SecurityでREST APIを保護する方法は?

分類Dev

列挙型序数を文字列としてキャストする方法は?

分類Dev

列挙型とSpringの@RequestParam

分類Dev

列挙型とSpringの@RequestParam

分類Dev

Hibernateの列挙型、列挙型として永続化

分類Dev

Spring MVCで多次元配列を@RequestParamとして処理する方法は?

分類Dev

Spring JPA-永続化してもオブジェクトが永続化されないというエラーが発生する

Related 関連記事

  1. 1

    Thymeleaf + Spring MVC-フォームのリストまたは列挙型から値を永続化する方法は?

  2. 2

    Thymeleaf + Spring MVC-フォームのリストまたは列挙型から値を永続化する方法は?

  3. 3

    Javaを使用して列挙型でSpring Bootで親子Json応答を作成する方法

  4. 4

    Spring Boot Restレスポンスでブール値を文字列としてシリアル化する方法は?

  5. 5

    Spring Entityクラス内でArrayListを永続化する方法は?

  6. 6

    Springを使用して列挙型の値を取得する方法

  7. 7

    Spring-BootとJPAを使用して、永続化されていない別のエンティティの複数の同一インスタンスを含む新しいエンティティを永続化するにはどうすればよいですか?

  8. 8

    SSLとSpring Bootを使用してPostgresQLに接続する方法

  9. 9

    Spring Boot:リポジトリを使用して1対多の関係を個別に永続化する方法

  10. 10

    Spring Bootと組み込みTomcatでセッションの永続化を有効にする

  11. 11

    Spring Bootで列挙型の適切な検証エラーを返す方法は?

  12. 12

    Spring Boot-文字列から列挙への変換は、列挙の値とインデックスを受け入れます。数値入力を拒否して列挙値のみを受け入れる方法は?

  13. 13

    Springサービス内で永続化すると、TransactionRequiredExceptionが発生します

  14. 14

    Java Spring Boot、JPA、Hibernateは、OBJECT型のオブジェクトを永続化します

  15. 15

    Hibernate / Spring Bootを使用してJSONファイルをJSONデータ型としてmysqlに保存する方法は?

  16. 16

    Springの値として列挙型を使用してマップを挿入する

  17. 17

    Spring BootとMongoDBで「_class」列を削除する方法は?

  18. 18

    Spring Data Cassandraを使用してjava.util.Date値をCassandra日付型列に挿入する方法は?

  19. 19

    Spring Data JPAでJSR-310タイプを永続化する方法は?

  20. 20

    Spring BootでMapstructを使用して親と子をマップする方法は?

  21. 21

    Springを使用しているときに複数のJPA EntityManager(永続性ユニット)を挿入する方法

  22. 22

    spring-data-elasticsearchを使用してJava列挙型を保存する方法

  23. 23

    Spring BootとSpring SecurityでREST APIを保護する方法は?

  24. 24

    列挙型序数を文字列としてキャストする方法は?

  25. 25

    列挙型とSpringの@RequestParam

  26. 26

    列挙型とSpringの@RequestParam

  27. 27

    Hibernateの列挙型、列挙型として永続化

  28. 28

    Spring MVCで多次元配列を@RequestParamとして処理する方法は?

  29. 29

    Spring JPA-永続化してもオブジェクトが永続化されないというエラーが発生する

ホットタグ

アーカイブ