添加到实体的枚举字段 @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)
下面你可以找到一个最小的例子,再现问题。
我做错什么了?
测试/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>
测试/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\u 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)
);
测试/生成.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
编辑:因为它似乎是一个bug,我刚刚打开了一个jira问题。
2条答案
按热度按时间wgxvkvu91#
我已经试着让这个工作了很长一段时间,似乎我终于得到了!
我遇到了和你在编解码器上遇到的相同的问题…我不知道为什么那不起作用。根据他们的文件你做得很对。
所以我实现了自己的cassandra写转换器。见下文
这应该在每次编写cassandra时使用重写的转换器将它看到的myenum类型的所有枚举转换为int。这使您可以为不同类型的枚举使用多个这样的值,因为某些原因,您可能希望从这些值中写入其他自定义值,而不是始终转换所有枚举。
希望这能奏效!
请注意删除{}的更改,例如在每个转换器上,并向cassandracustomconversions注册readingconverter
bzzcjhmw2#
这是固定的,因为 Spring 启动版本
2.1.5
.然而
@CassandraType
需要显式地放置在kotlin中的getter中,否则在运行时就看不到它。实际上,这仅仅意味着替换:
因此: