Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@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.

like image 616
Himanshu Ahire Avatar asked Jan 09 '19 10:01

Himanshu Ahire


2 Answers

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!

like image 83
veysiertekin Avatar answered Sep 23 '22 10:09

veysiertekin


Its working when used with class instated of case class.

@PrimaryKeyClass
class SimpleKey{

 @PrimaryKeyColumn( `type` = PrimaryKeyType.PARTITIONED, ordinal = 0, name = "id")
 var id: Int =_ 
 @PrimaryKeyColumn( `type` = PrimaryKeyType.CLUSTERED, ordinal = 1,  name = "name")
 var name: String =_
}
like image 34
Himanshu Ahire Avatar answered Sep 24 '22 10:09

Himanshu Ahire