@Column (Cassandra) 注释被 Spring Boot 2.5.0 忽略(适用于 2.4.6)
@Column (Cassandra) annotation ignored with Spring Boot 2.5.0 (works with 2.4.6)
在尝试使用 spring-boot-starter-data-cassandra
将项目从 Spring 引导 2.4.6
更新到 2.5.0
时,我 运行 遇到了 [=23] 的问题=] 注释被忽略。
使用以下注释
@Column("blabla")
val buz: Long
导致此错误:
Query; CQL [INSERT INTO bar (baz,buz) VALUES (?,?)]; Undefined column name buz; nested exception is com.datastax.oss.driver.api.core.servererrors.InvalidQueryException: Undefined column name buz
因此查询使用 buz
而不是预期的 blabla
。使用 Spring Boot 2.4.6
而不是 2.5.0
它工作正常。有什么改变,所以我需要调整我的代码,或者这是一个错误?
问题似乎来自 spring-data-cassandra
,它使用 Spring Boot.
更新
- 当使用 Spring 引导
2.4.6
和 implementation(group = "org.springframework.data", name = "spring-data-cassandra", version = "3.1.9")
时一切正常。
- 当使用 Spring 引导时
2.4.6
和 implementation(group = "org.springframework.data", name = "spring-data-cassandra", version = "3.2.0")
事情失败。
看起来整个 @Column
注释都被忽略了,因为在我添加它时 forceQuote = true
也没有被使用。
可以使用以下最小示例 (docker build .
) 重现错误:
Dockerfile
FROM openjdk:11-jdk-slim
WORKDIR /home/test
ADD . /home/test
RUN ./gradlew test
build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
val kotlinVersion = "1.5.10"
val springBootVersion = "2.4.6"
plugins {
val pluginKotlinVersion = "1.5.10"
val pluginSpringBootVersion = "2.5.0"
id("org.springframework.boot") version pluginSpringBootVersion
kotlin("jvm") version pluginKotlinVersion
kotlin("plugin.spring") version pluginKotlinVersion
kotlin("plugin.jpa") version pluginKotlinVersion
}
group = "com.acme"
version = "1.0.0-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}
dependencies {
implementation(
group = "org.springframework.boot",
name = "spring-boot-starter-data-cassandra",
version = springBootVersion
)
// 3.1.9 -> fine
// 3.2.0 -> broken
// 3.2.1 -> broken
implementation(group = "org.springframework.data", name = "spring-data-cassandra", version = "3.2.0")
implementation(group = "org.springframework.boot", name = "spring-boot-starter-web", version = springBootVersion)
implementation(group = "org.jetbrains.kotlin", name = "kotlin-reflect", version = kotlinVersion)
implementation(
group = "org.cassandraunit",
name = "cassandra-unit-spring",
version = "4.3.1.0"
) {
exclude(group = "org.hibernate")
testImplementation(group = "com.google.guava", name = "guava") {
version {
// https://github.com/jsevellec/cassandra-unit/issues/248
// https://issues.apache.org/jira/browse/CASSANDRA-15245
strictly("18.0")
}
}
}
testImplementation(
group = "org.springframework.boot",
name = "spring-boot-starter-test",
version = springBootVersion
)
}
tasks {
withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}
withType<Test> {
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
}
}
settings.gradle.kts
rootProject.name = "acmetest"
src/main/kotlin/com/acme/Application.kt
package com.acme
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.data.cassandra.core.mapping.Column
import org.springframework.data.cassandra.core.mapping.PrimaryKey
import org.springframework.data.cassandra.core.mapping.Table
import org.springframework.data.cassandra.repository.CassandraRepository
import org.springframework.stereotype.Repository
@SpringBootApplication
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
@Table("bar")
class Bar(
@PrimaryKey("baz")
val baz: Long,
@Column("blabla")
val buz: Long
)
@Repository
interface BarRepository : CassandraRepository<Bar, Long>
src/main/resources/application.yml
spring:
data:
cassandra:
contact-points: localhost
port: 9142
keyspace_name: foo
local-datacenter: datacenter1
src/test/kotlin/com/acme/integration/TestFullStack.kt
package com.acme.integration
import com.acme.Bar
import com.acme.BarRepository
import org.cassandraunit.spring.CassandraDataSet
import org.cassandraunit.spring.CassandraUnitDependencyInjectionTestExecutionListener
import org.cassandraunit.spring.EmbeddedCassandra
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.ActiveProfiles
import org.springframework.test.context.TestExecutionListeners
import org.springframework.test.context.junit4.SpringRunner
@ActiveProfiles("test")
@RunWith(SpringRunner::class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestExecutionListeners(
listeners = [CassandraUnitDependencyInjectionTestExecutionListener::class],
mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
)
@CassandraDataSet(value = ["cql/foo.cql"], keyspace = "foo")
@EmbeddedCassandra
class TestFullStack {
@Autowired
lateinit var barRepository: BarRepository
@Test
fun `test init`() {
barRepository.save(Bar(1, 2))
}
}
src/test/resources/cql/foo.cql
DROP KEYSPACE IF EXISTS foo;
CREATE KEYSPACE foo WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':1};
CREATE TABLE foo.bar
(
baz bigint,
blabla bigint,
PRIMARY KEY (baz)
);
好的,问题似乎出在构造函数中已经声明了 Bar
的成员。即,替换这个
@Table("bar")
class Bar(
@PrimaryKey("baz")
val baz: Long,
@Column("blabla")
val buz: Long
)
有了那个
@Table("bar")
class Bar(baz: Long, buz: Long) {
@PrimaryKey("baz")
val baz: Long = baz
@Column("blabla")
val buz: Long = buz
}
让它再次工作。
org.springframework.data:spring-data-cassandra
的 3.1.9
版本都工作正常,但第一个在更新到 3.2.0
时出现故障。我们已经打开了一个问题:https://github.com/spring-projects/spring-data-cassandra/issues/1136
编辑 2022-02-01:以下也适用:
@Table("bar")
class Bar(
@PrimaryKey("baz")
val baz: Long,
@field:Column("blabla")
val buz: Long
)
在尝试使用 spring-boot-starter-data-cassandra
将项目从 Spring 引导 2.4.6
更新到 2.5.0
时,我 运行 遇到了 [=23] 的问题=] 注释被忽略。
使用以下注释
@Column("blabla")
val buz: Long
导致此错误:
Query; CQL [INSERT INTO bar (baz,buz) VALUES (?,?)]; Undefined column name buz; nested exception is com.datastax.oss.driver.api.core.servererrors.InvalidQueryException: Undefined column name buz
因此查询使用 buz
而不是预期的 blabla
。使用 Spring Boot 2.4.6
而不是 2.5.0
它工作正常。有什么改变,所以我需要调整我的代码,或者这是一个错误?
问题似乎来自 spring-data-cassandra
,它使用 Spring Boot.
- 当使用 Spring 引导
2.4.6
和implementation(group = "org.springframework.data", name = "spring-data-cassandra", version = "3.1.9")
时一切正常。 - 当使用 Spring 引导时
2.4.6
和implementation(group = "org.springframework.data", name = "spring-data-cassandra", version = "3.2.0")
事情失败。
看起来整个 @Column
注释都被忽略了,因为在我添加它时 forceQuote = true
也没有被使用。
可以使用以下最小示例 (docker build .
) 重现错误:
Dockerfile
FROM openjdk:11-jdk-slim
WORKDIR /home/test
ADD . /home/test
RUN ./gradlew test
build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
val kotlinVersion = "1.5.10"
val springBootVersion = "2.4.6"
plugins {
val pluginKotlinVersion = "1.5.10"
val pluginSpringBootVersion = "2.5.0"
id("org.springframework.boot") version pluginSpringBootVersion
kotlin("jvm") version pluginKotlinVersion
kotlin("plugin.spring") version pluginKotlinVersion
kotlin("plugin.jpa") version pluginKotlinVersion
}
group = "com.acme"
version = "1.0.0-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}
dependencies {
implementation(
group = "org.springframework.boot",
name = "spring-boot-starter-data-cassandra",
version = springBootVersion
)
// 3.1.9 -> fine
// 3.2.0 -> broken
// 3.2.1 -> broken
implementation(group = "org.springframework.data", name = "spring-data-cassandra", version = "3.2.0")
implementation(group = "org.springframework.boot", name = "spring-boot-starter-web", version = springBootVersion)
implementation(group = "org.jetbrains.kotlin", name = "kotlin-reflect", version = kotlinVersion)
implementation(
group = "org.cassandraunit",
name = "cassandra-unit-spring",
version = "4.3.1.0"
) {
exclude(group = "org.hibernate")
testImplementation(group = "com.google.guava", name = "guava") {
version {
// https://github.com/jsevellec/cassandra-unit/issues/248
// https://issues.apache.org/jira/browse/CASSANDRA-15245
strictly("18.0")
}
}
}
testImplementation(
group = "org.springframework.boot",
name = "spring-boot-starter-test",
version = springBootVersion
)
}
tasks {
withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}
withType<Test> {
testLogging.exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
}
}
settings.gradle.kts
rootProject.name = "acmetest"
src/main/kotlin/com/acme/Application.kt
package com.acme
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.data.cassandra.core.mapping.Column
import org.springframework.data.cassandra.core.mapping.PrimaryKey
import org.springframework.data.cassandra.core.mapping.Table
import org.springframework.data.cassandra.repository.CassandraRepository
import org.springframework.stereotype.Repository
@SpringBootApplication
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
@Table("bar")
class Bar(
@PrimaryKey("baz")
val baz: Long,
@Column("blabla")
val buz: Long
)
@Repository
interface BarRepository : CassandraRepository<Bar, Long>
src/main/resources/application.yml
spring:
data:
cassandra:
contact-points: localhost
port: 9142
keyspace_name: foo
local-datacenter: datacenter1
src/test/kotlin/com/acme/integration/TestFullStack.kt
package com.acme.integration
import com.acme.Bar
import com.acme.BarRepository
import org.cassandraunit.spring.CassandraDataSet
import org.cassandraunit.spring.CassandraUnitDependencyInjectionTestExecutionListener
import org.cassandraunit.spring.EmbeddedCassandra
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.ActiveProfiles
import org.springframework.test.context.TestExecutionListeners
import org.springframework.test.context.junit4.SpringRunner
@ActiveProfiles("test")
@RunWith(SpringRunner::class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestExecutionListeners(
listeners = [CassandraUnitDependencyInjectionTestExecutionListener::class],
mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
)
@CassandraDataSet(value = ["cql/foo.cql"], keyspace = "foo")
@EmbeddedCassandra
class TestFullStack {
@Autowired
lateinit var barRepository: BarRepository
@Test
fun `test init`() {
barRepository.save(Bar(1, 2))
}
}
src/test/resources/cql/foo.cql
DROP KEYSPACE IF EXISTS foo;
CREATE KEYSPACE foo WITH REPLICATION = {'class':'SimpleStrategy', 'replication_factor':1};
CREATE TABLE foo.bar
(
baz bigint,
blabla bigint,
PRIMARY KEY (baz)
);
好的,问题似乎出在构造函数中已经声明了 Bar
的成员。即,替换这个
@Table("bar")
class Bar(
@PrimaryKey("baz")
val baz: Long,
@Column("blabla")
val buz: Long
)
有了那个
@Table("bar")
class Bar(baz: Long, buz: Long) {
@PrimaryKey("baz")
val baz: Long = baz
@Column("blabla")
val buz: Long = buz
}
让它再次工作。
org.springframework.data:spring-data-cassandra
的 3.1.9
版本都工作正常,但第一个在更新到 3.2.0
时出现故障。我们已经打开了一个问题:https://github.com/spring-projects/spring-data-cassandra/issues/1136
编辑 2022-02-01:以下也适用:
@Table("bar")
class Bar(
@PrimaryKey("baz")
val baz: Long,
@field:Column("blabla")
val buz: Long
)