如何通过使用Lagom Scala框架在Cassandra中插入用户定义的类型

时间:2019-06-27 16:37:00

标签: scala cassandra lagom

我正在使用Lagom(scala)框架,我可以找到任何方法来在具有复杂Type的cassandra中保存scala case类对象。所以我如何在Lagom scala中插入cassandra UDT。谁能解释使用BoundStatement.setUDTValue()方法。

I have tried to do by using com.datastax.driver.mapping.annotations.UDT.
but does not work for me. I have also tried com.datastax.driver.core
 Session Interface. but again it does not.

case class LeadProperties(
                           name: String,
                           label: String,
                           description: String,
                           groupName: String,
                           fieldDataType: String,
                           options: Seq[OptionalData]
                         )
object LeadProperties{
  implicit val format: Format[LeadProperties] = Json.format[LeadProperties]
}
@UDT(keyspace = "leadpropertieskeyspace", name="optiontabletype")
case class OptionalData(label: String)
object OptionalData {
  implicit val format: Format[OptionalData] = Json.format[OptionalData]
}

my query:----
val optiontabletype= """
      |CREATE TYPE IF NOT EXISTS optiontabletype(
      |value text
      |);
    """.stripMargin


   val createLeadPropertiesTable: String =       """
                          |CREATE TABLE IF NOT EXISTS leadpropertiestable(
                          |name text Primary Key,
                          |label text,
                          |description text,
                          |groupname text,
                          |fielddatatype text,
                          |options List<frozen<optiontabletype>>
                          );
                        """.stripMargin

def createLeadProperties(obj: LeadProperties): Future[List[BoundStatement]] = {
    val bindCreateLeadProperties: BoundStatement = createLeadProperties.bind()
    bindCreateLeadProperties.setString("name", obj.name)
    bindCreateLeadProperties.setString("label", obj.label)
    bindCreateLeadProperties.setString("description", obj.description)
    bindCreateLeadProperties.setString("groupname", obj.groupName)
    bindCreateLeadProperties.setString("fielddatatype", obj.fieldDataType)

     here is the problem I am not getting any method for cassandra Udt.

    Future.successful(List(bindCreateLeadProperties))
  }

override def buildHandler(): ReadSideProcessor.ReadSideHandler[PropertiesEvent] = {
    readSide.builder[PropertiesEvent]("PropertiesOffset")
      .setGlobalPrepare(() => PropertiesRepository.createTable)
      .setPrepare(_ => PropertiesRepository.prepareStatements)
      .setEventHandler[PropertiesCreated](ese ⇒ 
        PropertiesRepository.createLeadProperties(ese.event.obj))
      .build()
  } 

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,并通过以下方式解决了该问题:

  1. 定义类型和表:
     def createTable(): Future[Done] = {
        session.executeCreateTable("CREATE TYPE IF NOT EXISTS optiontabletype(filed1 text, field2 text)")
          .flatMap(_ => session.executeCreateTable(
            "CREATE TABLE IF NOT EXISTS leadpropertiestable ( " +
              "id TEXT, options list<frozen <optiontabletype>>, PRIMARY KEY (id))"
          ))
      }
  1. buildHandler()中调用此方法,如下所示:
      override def buildHandler(): ReadSideProcessor.ReadSideHandler[FacilityEvent] =
        readSide.builder[PropertiesEvent]("PropertiesOffset")
          .setPrepare(_ => prepare())
          .setGlobalPrepare(() => {
            createTable()
          })
          .setEventHandler[PropertiesCreated](processPropertiesCreated)
          .build()
  1. 然后在 processPropertiesCreated()中,我像这样使用它:
  private val writePromise = Promise[PreparedStatement] // initialized in prepare
  private def writeF: Future[PreparedStatement] = writePromise.future

  private def processPropertiesCreated(eventElement: EventStreamElement[PropertiesCreated]): Future[List[BoundStatement]] = {
    writeF.map { ps =>
      val userType = ps.getVariables.getType("options").getTypeArguments.get(0).asInstanceOf[UserType]
      val newValue = userType.newValue().setString("filed1", "1").setString("filed2", "2")
      val bindWriteTitle = ps.bind()
      bindWriteTitle.setString("id", eventElement.event.id)
      bindWriteTitle.setList("options", eventElement.event.keys.map(_ => newValue).toList.asJava) // todo need to convert, now only stub
      List(bindWriteTitle)
    }
  }
  1. 这样阅读:
  def toFacility(r: Row): LeadPropertiesTable = {
    LeadPropertiesTable(
      id = r.getString(fId),
      options = r.getList("options", classOf[UDTValue]).asScala.map(udt => OptiontableType(field1 = udt.getString("field1"), field2 = udt.getString("field2"))
    )
  }
  1. 我的 prepare()函数:
  private def prepare(): Future[Done] = {
    val f = session.prepare("INSERT INTO leadpropertiestable (id, options) VALUES (?, ?)")
    writePromise.completeWith(f)
    f.map(_ => Done)
  }

这不是写得很好的代码,但我认为这将有助于进行工作。