как вставить пользовательский тип в cassandra с помощью lagom scala framework

Я использую структуру Lagom (scala), и я могу найти любой способ сохранить объект класса scala case в cassandra со сложным типом. Итак, как мне вставить cassandra UDT в Lagom scala. и может ли кто-нибудь объяснить, как использовать метод 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()
  } 

person Anish    schedule 27.06.2019    source источник
comment
@UDT аннотация используется только с Object Mapper - она ​​не поможет с прямыми вставками - см. ссылку, которую я добавил в своем комментарии к предыдущему вопросу   -  person Alex Ott    schedule 28.06.2019


Ответы (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)
  }

Это не очень хорошо написанный код, но я думаю, он поможет продолжить работу.

person Vladislav Kievski    schedule 09.08.2019