前提
play-slickを使用。
https://www.playframework.com/documentation/2.4.x/PlaySlick
本題
たとえば
/**
* Created by FScoward on 2015/09/29.
*/
@Singleton
class GroupService @Inject()(groupPersistence: GroupPersistence,
eventPersistence: EventPersistence,
groupHasUserPersistence: GroupHasUserPersistence,
protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
def createGroup(groupName: String, event: Event)(implicit session: Session, user: User) = {
val q = for {
eid <- eventPersistence.save(event.toEventRow)
gid <- groupPersistence.save(groupName, eid)
_ <- groupHasUserPersistence.save(gid, 1L, false)
} yield ()
db.run(q)
}
}
こんな感じで使いたかったとする。
単純に
@Singleton
class EventPersistenceObj extends EventPersistence
@ImplementedBy(classOf[EventPersistenceObj])
trait EventPersistence {
def save(eventRow: EventRow)(implicit s: Session) = {
Event += eventRow
}
}
と書いただけでは eid
には常に1が返ってきてしまう。
auto incrementされた戻りの値を使用する際には
Event += eventRow
の部分を
Event returning Event.map(_.eventId) += eventRow
と書いてやるときちんと値が帰ってくる
補足 抜粋
gen-tablesで生成したTable
Tables.scala
/** Entity class storing rows of table Event
* @param eventId Database column EVENT_ID SqlType(BIGINT), AutoInc, PrimaryKey
* @param title Database column TITLE SqlType(VARCHAR), Length(45,true)
* @param artist Database column ARTIST SqlType(VARCHAR), Length(45,true), Default(None)
* @param location Database column LOCATION SqlType(VARCHAR), Length(45,true)
* @param yearMonthDate Database column YEAR_MONTH_DATE SqlType(VARCHAR), Length(8,true)
* @param startTime Database column START_TIME SqlType(VARCHAR), Length(4,true), Default(None)
* @param endTime Database column END_TIME SqlType(VARCHAR), Length(4,true), Default(None) */
case class EventRow(eventId: Long, title: String, artist: Option[String] = None, location: String, yearMonthDate: String, startTime: Option[String] = None, endTime: Option[String] = None)
/** GetResult implicit for fetching EventRow objects using plain SQL queries */
implicit def GetResultEventRow(implicit e0: GR[Long], e1: GR[String], e2: GR[Option[String]]): GR[EventRow] = GR{
prs => import prs._
EventRow.tupled((<<[Long], <<[String], <<?[String], <<[String], <<[String], <<?[String], <<?[String]))
}
/** Table description of table event. Objects of this class serve as prototypes for rows in queries. */
class Event(_tableTag: Tag) extends Table[EventRow](_tableTag, "event") {
def * = (eventId, title, artist, location, yearMonthDate, startTime, endTime) <> (EventRow.tupled, EventRow.unapply)
/** Maps whole row to an option. Useful for outer joins. */
def ? = (Rep.Some(eventId), Rep.Some(title), artist, Rep.Some(location), Rep.Some(yearMonthDate), startTime, endTime).shaped.<>({r=>import r._; _1.map(_=> EventRow.tupled((_1.get, _2.get, _3, _4.get, _5.get, _6, _7)))}, (_:Any) => throw new Exception("Inserting into ? projection not supported."))
/** Database column EVENT_ID SqlType(BIGINT), AutoInc, PrimaryKey */
val eventId: Rep[Long] = column[Long]("EVENT_ID", O.AutoInc, O.PrimaryKey)
/** Database column TITLE SqlType(VARCHAR), Length(45,true) */
val title: Rep[String] = column[String]("TITLE", O.Length(45,varying=true))
/** Database column ARTIST SqlType(VARCHAR), Length(45,true), Default(None) */
val artist: Rep[Option[String]] = column[Option[String]]("ARTIST", O.Length(45,varying=true), O.Default(None))
/** Database column LOCATION SqlType(VARCHAR), Length(45,true) */
val location: Rep[String] = column[String]("LOCATION", O.Length(45,varying=true))
/** Database column YEAR_MONTH_DATE SqlType(VARCHAR), Length(8,true) */
val yearMonthDate: Rep[String] = column[String]("YEAR_MONTH_DATE", O.Length(8,varying=true))
/** Database column START_TIME SqlType(VARCHAR), Length(4,true), Default(None) */
val startTime: Rep[Option[String]] = column[Option[String]]("START_TIME", O.Length(4,varying=true), O.Default(None))
/** Database column END_TIME SqlType(VARCHAR), Length(4,true), Default(None) */
val endTime: Rep[Option[String]] = column[Option[String]]("END_TIME", O.Length(4,varying=true), O.Default(None))
}
/** Collection-like TableQuery object for table Event */
lazy val Event = new TableQuery(tag => new Event(tag))
build.sbt
"com.typesafe.slick" %% "slick" % "3.0.2",
"com.typesafe.slick" %% "slick-codegen" % "3.0.0",
"com.typesafe.play" %% "play-slick" % "1.0.1",
"com.typesafe.play" %% "play-slick-evolutions" % "1.0.1",
application.conf
db.default.driver="com.mysql.jdbc.Driver"
db.default.url="jdbc:mysql://localhost:3306/xxxx?characterEncoding=UTF8"
db.default.username=root
db.default.password=""
slick.dbs.default.driver="slick.driver.MySQLDriver$"
slick.dbs.default.url="jdbc:mysql://localhost:3306/xxxx?characterEncoding=UTF8"
slick.dbs.default.username=root
slick.dbs.default.password=""
slick.dbs.default.db.driver="com.mysql.jdbc.Driver"
slick.dbs.default.db.url="jdbc:mysql://localhost:3306/xxxx?characterEncoding=UTF8"
slick.dbs.default.db.user=root
mysql {
dataSourceClass = "slick.jdbc.DatabaseUrlDataSource"
properties = {
driver=com.mysql.jdbc.Driver
url="jdbc:mysql://localhost:3306/xxxx"
user="root"
password=""
}
numThreads = 10
}