如果 table 的列数超过 22,因此它被定义为一种类型,如何使用属性名称。光滑/斯卡拉

How to use attribute names if the table has more than 22 columns so it is defined as a type. Slick / Scala

老实说,我对 Scala 和 Slick 还很陌生。

问题:我使用 Slick 2.1.0 生成了 tables.scala,对于超过 22 列的 table,我得到了 'type' 定义而不是大小写 class,这使得无法使用名称属性。

在Tables.scala...

/** Row type of table Transaction */
type TransactionRow = HCons[Int,HCons[String,HCons[Int,HCons[Int.....,HNil]...]]

/** Constructor for TransactionRow providing default values if available in the database schema. */
def TransactionRow(id: Int, code: String, placeId: Int, userId: Int,  .... ): TransactionRow = {
  id :: code :: placeId :: userId :: memberId    .......
}

/** GetResult implicit for fetching TransactionRow objects using  plain SQL queries */ .......
implicit def GetResultTransactionRow(implicit e0: GR[Int], e1: GR[String], e2: GR[java.sql.Date], e3: GR[scala.math.BigDecimal], e4: GR[Option[Int]], e5: GR[Boolean], e6: GR[java.sql.Timestamp], e7: GR[Option[String]], e8: GR[Option[Double]]): GR[TransactionRow] = GR{
  prs => import prs._
  <<[Int] :: <<[String] :: <<[Int] :: <<[Int] :: <<[Int] :: <<[java.sql.Date] :: <<[java.sql.Date] :: <<[scala.math.BigDecimal] :: <<[scala.math.BigDecimal] :: <<?[Int] :: <<[scala.math.BigDecimal] :: <<[String] :: <<[Boolean] :: <<[java.sql.Timestamp] :: <<[java.sql.Timestamp] :: <<[java.sql.Date] :: <<[scala.math.BigDecimal] ::  <<?[String] :: <<?[Int] :: <<?[String] :: HNil
}

/** Table description of table transaction. Objects of this class serve as prototypes for rows in queries. */
class Transaction(_tableTag: Tag) extends Table[TransactionRow](_tableTag, "transaction") {
  def * = id :: code :: placeId :: userId :: memberId ::    .........

  /** Database column id DBType(INT UNSIGNED), AutoInc, PrimaryKey */
  val id: Column[Int] = column[Int]("id", O.AutoInc, O.PrimaryKey)
  /** Database column code DBType(VARCHAR), Length(16,true) */
  val code: Column[String] = column[String]("code", O.Length(16,varying=true))
   ...

lazy val Transaction = new TableQuery(tag => new Transaction(tag))

2) 因此我无法通过属性名称调用 TransactionRow,例如:

val x: Row = getTransactionRowFromDatabase()
println(x.code) 
// x.code is not possible because this is not a case class so mapping to variable names is not possible. 

3) 现在是否可以 - 例如 - 具有查询数据库的功能和 return 我可以按名称访问属性的 TransactionRow 或类似对象?

def getTransactionByCode(code: String): TransactionRow = {
    val result = slickDbDef.withSession { implicit session =>
      Transaction.filter(_.code === code).run
    }
    result(0) // This is of type TransactionRow as a result attributes are not mapped by name, instead they are a List.
    // How can I make this a kind of entity I can use in my business logic?
  }

我知道解决方案可能与 def * 函数有关,并且可能与我应该手动放置的附加 <> 运算符有关,但我不确定如何编写这些,因为生成的 def * 使用 :: 运算符。

提前致谢!非常感谢您的宝贵时间。

目前不支持对大于 22 的表的结果字段进行命名访问。我添加了一张票来添加这个:https://github.com/slick/slick/issues/1130

谢谢你的回答,cvogt!我喜欢将它包含在 Slick 中的想法。

如果有人遇到类似情况,我遇到了一个暂时的解决方法,将 TransactionRow 映射到一个较小的案例 class(在我们的业务逻辑中不需要所有属性的情况下,属性较少) .我相信如果我们需要所有属性,我们可以使用多案例 classes 方法,但在一个较小的示例中的想法是这样的:

case class Transaction(a:Int, b:String, c:Int)

/** Row type of table Transaction */
type TransactionRow = HCons[Int, HCons[String, HCons[Int, HNil]]]

/** Constructor for TransactionRow providing default values if available in the database schema. */
def TransactionRow(id: Int, code: String, domainId: Int): TransactionRow = {
    id :: code :: domainId :: HNil
}

val x = TransactionRow(1, "TestCode", 2)

val fv:(Int :: String :: Int :: HNil) => Transaction = {
    case aa :: bb :: cc :: HNil => {
      Transaction(aa,bb,cc)
    }
    case _ => error("unknown")
}

现在我们可以将 fv 用作:

val z = fv(x)
//| z  : com.viglink.batch.network.Tables.Transaction = Transaction(1,TestCode,2)