简体   繁体   English

如何从scala case类生成java数组

[英]how to generate a java array from a scala case class

I'm writing a small data access library to help me use Cassandra prepared statements in a Scala program (its not open source but maybe one day). 我正在编写一个小型数据访问库,以帮助我在Scala程序中使用Cassandra准备的语句(它不是开源的,但可能有一天)。 What I'd like to do is automatically generate a Java Array for the bind statement from the case class 我想做的是为case类的bind语句自动生成一个Java Array。

com.datastax.driver.core
PreparedStatement...
  public BoundStatement bind(Object... values);

So currently I have 所以目前我有

case class Entity(foo:String, optionalBar:Option[String]) 

object Entity { 
  def toJArray(e:Entity) = { Array(e.foo, e.optionalBar.getOrElse(null)) } 
}

val e1 = Entity("fred", Option("bill"))
val e2 = Entity("fred", None)

Entity.toJArray(e1)
res5: Array[String] = Array(fred, bill)
Entity.toJArray(e2)
res6: Array[String] = Array(fred, null)

The toJArray returns an Array I can use in the bind statement. toJArray返回一个我可以在bind语句中使用的Array。 The boiler plate code gets worse if there is a date or double or a java enum 如果有日期,双精度数或Java枚举,则样板代码会变得更糟

new java.util.Date(createdOn)
scala.Double.box(price)
priceType.name

Is there a way of automatically generating the Array in Scala assuming the bind parameters have the same order as the case class fields? 假设绑定参数与case类字段具有相同的顺序,是否可以在Scala中自动生成Array?

EDIT Thanks to @srgfed01 Here's what I came up with (not complete) but allows me to do something like 编辑感谢@ srgfed01这是我想出的(不完整),但允许我做类似的事情

val customer1 = Customer( "email", "name", None, Option(new Date), OrdStatus.New)
session.execute(populate(customer1, insert))
val customer2 = Customer( "email2", "name2", Option(22), Option(new Date), OrdStatus.Rejected)
session.execute(populate(customer2, insert))

using this function 使用此功能

def populate(state:Product, statement:PreparedStatement): BoundStatement = {
  def set(bnd:BoundStatement, i:Int, aval:Any): Unit = {
    aval match {
      case v:Date => bnd.setDate(i, v)
      case v:Int => bnd.setInt(i, v)
      case v:Long => bnd.setLong(i, v)
      case v:Double => bnd.setDouble(i, v)
      case v:String => bnd.setString(i, v)
      case null => bnd.setToNull(i)
      case _ => bnd.setString(i, aval.toString)
    }
  }

  val bnd = statement.bind
  for(i <- 0 until state.productArity) {
    state.productElement(i) match {
      case op: Option[_]  => set(bnd, i, op.getOrElse(null))
      case v => set(bnd, i, v)
    }
  }
  bnd
}

You can use productIterator call for your case class object: 您可以将productIterator调用用于您的case类对象:

case class Entity(foo: String, optionalBar: Option[String])

val e1 = Entity("fred", Option("bill"))
val e2 = Entity("fred", None)

def run(e: Entity): Array[Any] = e.productIterator
  .map {
    case op: Option[_] => op.getOrElse(null)
    case v             => v
  }
  .toArray

println(run(e1).mkString(" ")) // fred bill
println(run(e2).mkString(" ")) // fred null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM