Search code examples
scalacassandraspring-dataspring-data-cassandra

@PrimaryKeyColumn annotations must have a type of PARTITIONED for scala Cassandra Spring Data application


I am working on Cassandra Spring-data module using Scala. I have created domain model & setup crud repository.

Spring data repository is setup as below:

@Repository
trait SampleRepository extends CassandraRepository[Sample, SampleKey]

Table domain model is setup as below:

@Table
 case class Sample(@PrimaryKey
              sampleKey: SampleKey,
              @Column("surName")
              surName: String)

Primary Key is composite key. Id column as Partition key. name column as Cluster key

@PrimaryKeyClass
case class SampleKey(
                  @PrimaryKeyColumn( `type` = PrimaryKeyType.PARTITIONED, ordinal = 0, name = "id")
                  id: Int,
                  @PrimaryKeyColumn( `type` = PrimaryKeyType.CLUSTERED, ordinal = 1,  name = "name")
                  name: String
                )

In scala type is a valid keyword hence used backward quotes. I am expecting this to work but when I start the application but I get

Suppressed: org.springframework.data.mapping.MappingException: Composite primary key type [com.barclays.decisionstore.trac.model.SampleKey] has no fields annotated with @PrimaryKeyColumn
    at org.springframework.data.cassandra.core.mapping.PrimaryKeyClassEntityMetadataVerifier.verify(PrimaryKeyClassEntityMetadataVerifier.java:91)
    ... 262 common frames omitted
Suppressed: org.springframework.data.mapping.MappingException: At least one of the @PrimaryKeyColumn annotations must have a type of PARTITIONED
    at org.springframework.data.cassandra.core.mapping.PrimaryKeyClassEntityMetadataVerifier.verify(PrimaryKeyClassEntityMetadataVerifier.java:98)
    ... 262 common frames omitted

This means type parameter to annotation is not recognized by Spring-Data.
The same code with java model classes works without issue.

Would appreciate any pointers or substitute to solve this.


Solution

  • Actually java bean properties not recognized other than annotations.

    Scala does not bind instance variables as bean properties by default at case classes. For this you need to add @BeanProperty annotations to each properties.

    import scala.beans.BeanProperty
    
    @PrimaryKeyClass
    case class SampleKey(@BeanProperty
                         @PrimaryKeyColumn(`type` = PrimaryKeyType.PARTITIONED, ordinal = 0, name = "id")
                         id: Int,
                         @BeanProperty
                         @PrimaryKeyColumn(`type` = PrimaryKeyType.CLUSTERED, ordinal = 1, name = "name")
                         name: String)
    

    Also if you get an object construction error, add a constructor with default values (this requires to make variables var):

    @PrimaryKeyClass
    case class SampleKey(@BeanProperty
                         @PrimaryKeyColumn(`type` = PrimaryKeyType.PARTITIONED, ordinal = 0, name = "id")
                         var id: Int,
                         @BeanProperty
                         @PrimaryKeyColumn(`type` = PrimaryKeyType.CLUSTERED, ordinal = 1, name = "name")
                         var name: String) {
      def this() = this(0, "")
    }
    

    Hope this helps!