Reputation: 522
To be honest I am fairly new to Scala and Slick.
The problem: I generated the tables.scala using Slick 2.1.0 and for a table with more than 22 columns I get a 'type' definition instead of a case class, which makes it not possible to use name attributes.
in 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) Because of this I cannot call TransactionRow by attribute name, something like:
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) Now is it possible to -for example- have a function to query the database and return a TransactionRow or similar object which I can access an attribute by name?
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?
}
I understand the solution might be related to the def * function and probably an additional <> operator that I should put manually, but I am not sure how to write these since the generated def * uses the :: operator.
Thank you in advance! I really appreciate your time.
Upvotes: 2
Views: 409
Reputation: 522
Thank you for the answer, cvogt! I like the idea to include this in Slick.
If anyone is in a similar situation, I came across a temporal work around to map the TransactionRow to a smaller case class (with less attributes in the case we do not need all in our business logic). I believe if we need all attributes we can use the multiple case classes approach, but the idea in a smaller example is this:
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")
}
Now we can use fv as:
val z = fv(x)
//| z : com.viglink.batch.network.Tables.Transaction = Transaction(1,TestCode,2)
Upvotes: 0
Reputation: 11270
Named access to result fields for tables >22 is currently not supported. I added a ticket to add this: https://github.com/slick/slick/issues/1130
Upvotes: 1