SlideShare ist ein Scribd-Unternehmen logo
1 von 57
Downloaden Sie, um offline zu lesen
Scala ActiveRecord
The elegant ORM library for Scala
Author              github.com/y-yoshinoya

主にScalaとRuby on Railsの業務をやってます

Play Framework 2.0 を Beta バージョンから業務で
採用を試みる

 DBライブラリにはSqueryl, Anorm, ScalaQuery を
 採用

Scala ActiveRecord はより使えるDBライブラリを求
めた結果の産物
概要
Summary
Scala ActiveRecord
https://github.com/aselab/scala-activerecord


Latest version: 0.2.1
License: MIT
Features                          Version 0.1

Squeryl wrapper
Type-safe (most part)
Rails ActiveRecord-like operability
  CoC (Convention over Configuration)
  DRY (Don't Repeat Yourself) principles.	
Auto transaction control

“Type-safed ActiveRecord model for Scala”
Features               Version 0.2

Validations
Associations
Testing support
Improving query performance
Scala 2.10 support
背景
Background
Why created? (1)
Scalaの大半のDBライブラリはSQLをWrapしたもの

関数型言語としての方向性としては正しい、かつ合理
的な方法
   val selectCountries = SQL("Select * from Country")

   val countries = selectCountries().map(row =>
     row[String]("code") -> row[String]("name")
   ).toList


しかし、オブジェクト (Model) にマッピングするため
には全て自前で定義しないといけない
                     Not DRY!!
Why created? (2)
関連マッピングをまともに扱いたい・なるべく簡単に
使いたい

ClassごとにFinder methodを定義しなければならない
などDRYに書けない

本質的な処理についてだけ記述したいのにできない。
操作を書きたいのであってSQLを書きたいわけでは
ない

           Not DRY!!!
Other libraries
      Anorm
      Slick (ScalaQuery)
      Squeryl
(1) Anorm
ORMではなく、Model層を提供しない設計思想のため、
どうしてもClassごとに同じようなメソッドを定義せざ
るを得なくなる
 case class Person(id: Pk[Long], name: String)

 object Person {
   def create(person: Person): Unit = {
      DB.withConnection { implicit connection =>
        SQL("insert into person(name) values ({name})").on(
         'name -> person.name).executeUpdate()
      }
   }
  ...
 }

                        Not DRY...
(2) Slick (ScalaQuery)
Queryの使用感は良いが、テーブル定義がやや冗長。
Modelとマッピングする場合、その対応をテーブルごと
に明示的に記述する必要がある

 case class Member(id: Int, name: String, email: Option[String])

 object Members extends Table[Member]("MEMBERS") {
    def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
    def name = column[String]("NAME")
    def email = column[Option[String]]("EMAIL")
    def * = id.? ~ name ~ email <> (Member, Member.unapply _)
  }

                  Query interface is Good.
                But, not DRY defining tables.
(3) Squeryl
 ScalaのORMとしては最も良い出来

 Queryに対してさらに条件を指定したQueryを作成すると
 Sub-QueryなSQLが呼び出される

val query = from(table)(t => where(t.id.~ > 20) select(t))
from(query)(t => where(t.name like “%test%”) select(t))

Select * From
  (Select * From table Where table.id > 20) q1
Where q1.name like “test”
              Very nice ORM library.
     Need to be aware of the SQL performance.
Improvements from Squeryl
Queryの合成結果が単なるSub Queryにならないように
   Queryの条件をパフォーマンス劣化せず流用可能


 val query = Table.where(_.id.~ > 20)
 query.where(_.name like “%test%”).toList


Select * From table
Where
 table.id > 20 and table.name like “test”

    Generates more simple SQL statement.
Improvements from Squeryl
Iterable#iterator にアクセスした時点で inTransaction す
るよう変更

save, delete 時にデフォルトで inTransaction するように

 もちろん明示的に transaction もできる

      // auto inTransaction
      query.toList
      model.save
      model.delete
Improvements from Squeryl
 関連設定ルールをCoCで結び付けられるように

 関連参照時のQueryがSubQueryにならないように

 Eager loadingを実装




     Simpler association definition rule.
Association definition (Squeryl)
object Schema extends Schema {
  val foo = table[Foo]
  val bar = table[Bar]
  val fooToBar = oneToManyRelation(Foo, Bar).via(
    (f, b) => f.barId === b.id
  )
}

class Foo(var barId: Long) extends SomeEntity {
  lazy val bar: ManyToOne[Bar] =
    schema.fooToBar.right(this)
}

class Bar(var bar: String) extends SomeEntity {
  lazy val foos: OneToMany[Foo] =
    schema.fooToBar.left(this)
}
Association definition
(Scala ActiveRecord)
 object Tables extends ActiveRecordTables {
   val foo = table[Foo]
   val bar = table[Bar]
 }

 class Foo(var barId: Long) extends ActiveRecord {
   lazy val bar = belongsTo[Bar]
 }

 class Bar(var bar: String) extends ActiveRecord {
   lazy val foos = hasMany[Foo]
 }
Minimal example
Model implementation
case class Person(var name: String, var age: Int)
 extends ActiveRecord

object Person
 extends ActiveRecordCompanion[Person]



       Schema definition
 object Tables extends ActiveRecordTables {
   val people = table[Person]
 }
Create

 val person = Person("person1", 25)
 person.save
        true



val person = Person("person1", 25).create
       Person(“person1”, 25)
Read
Person.find(1)
       Some(Person(“person1”))

Person.toList
       List(Person(“person1”), ...)

Person.findBy(“name”, “john”)
      Some(Person(“john”))

* Type-safe approach
Person.where(_.name === “john”).headOption
      Some(Person(“john”))
Update
Person.find(1).foreach { p =>
  p.name = “aaa”
  p.age = 19
                     Callback hook
  p.save               Validations
}


Person.forceUpdate(_.id === 1)(
  _.name := “aa”, _.age := 19
)
Delete
Person.where(_.name === “john”)
      .foreach(_.delete)

Person.find(1) match {
  case Some(person) => person.delete
  case _ =>
}

Person.delete(1)
Query interface
Single object finder
  val client = Client.find(10)
           Some(Client) or None


   val john = Client.findBy("name", "john")
           Some(Client("john")) or None



val john25 = Client.findBy(("name", "john"), ("age", 25))
        Some(Client("john", 25)) or None
Multiple object finder
Clients.where(c =>
  c.name === "john" and c.age.~ > 25
).toList

Clients.where(_.name === "john")
       .where(_.age.~ > 25)
       .toList
Select
 clients.name, clients.age, clients.id
From
 clients
Where
 clients.name = “john” and clients.age > 25
Using `Iterable` methods
val client = Client.head
         First Client or RecordNotFoundException


val client = Client.lastOption
         Some(Last Client) or None


val (adults, children) = Client.partition(_.age >= 20)
        Parts of clients
Ordering
* Simple order (ORDER BY client.name)
Client.orderBy(_.name)

* Set order (use for 'asc' or 'desc')
Client.orderBy(_.name asc)


* Ordering by multiple fields
Client.orderBy(_.name asc, _.age desc)
Limit and Offset
 Client.limit(10)

 Client.page(2, 5)


Existence of objects
Client.exists(_.name like "john%")
        true or false
Selecting specific fields
Client.select(_.name).toList
       List[String]



Client.select(c => (c.name, c.age)).toList
        List[(String, Int)]
Combining Queries
Clients.where(_.name like "john%”)
       .orderBy(_.age desc)
       .where(_.age.~ < 25)
       .page(2, 5)
       .toList
Select
  clients.name, clients.age, clients.id
From
  clients
Where
  ((clients.name like “john%”) and (clients.age < 25))
Order By
  clients.age Desc
limit 5 offset 2
Cache control
QueryからIterableに暗黙変換される際に取得したListを
キャッシュとして保持

  val orders = Order.where(_.age.~ > 20)

  // execute SQL query, and cached query
  orders.toList

  // non-execute SQL query.
  orders.toList
Validations
Annotation-based Validation
 case class User(
   @Required name: String,
   @Length(max=20) profile: String,
   @Range(min=0, max=150) age: Int
 ) extends ActiveRecord

 object User extends
  ActiveRecordCompanion[User]
Validation Sample
// it’s not save in the database
// because the object is not valid
val user = User("", “Profile”, 25).create

user.isValid
       false
user.hasErrors
       true
user.errors.messges
       Seq("Name is required")
user.hasError("name")
       true
More functional error handling...
 User("John", “profile”, 20).saveEither match {
   case Right(user) => println(user.name)
   case Left(errors) => println(errors.messages)
 }
        "John"


 User("", “profile”, 15).saveEither match {
   case Right(user) => println(user.name)
   case Left(errors) => println(errors.messages)
 }
        "Name is required"
Callbacks
Available hooks
•beforeValidation()
•beforeCreate()
•afterCreate()
•beforeUpdate()
•afterUpdate()
•beforeSave()
•afterSave()
•beforeDelete()
•afterDelete()
Callback example
case class User(login: String) extends ActiveRecord {
  @Transient
  @Length(min=8, max=20)
  var password: String = _
  var hashedPassword: String = _

    override def beforeSave() {
      hashedPassword = SomeLibrary.encrypt(password)
    }
}

val user = User(“john”)
user.password = “raw_password”
user.save
        Storing encrypted password
Associations
One-to-Many



case class User(name: String) extends ActiveRecord {
  val groupId: Option[Long] = None
  lazy val group = belongsTo[Group]
}

case class Group(name: String) extends ActiveRecord {
  lazy val users = hasMany[User]
}
One-to-Many
val user1 = User("user1").create
val user2 = User("user2").create
val group1 = Group("group1").create

group1.users << user1

group1.users.toList
       List(User("user1"))
user1.group.getOrElse(Group(“group2”))
       Group("group1")
Association is Queryable
   group1.users.where(_.name like “user%”)
               .orderBy(_.id desc)
               .limit(5)
               .toList
Select
  users.name, users.id
From
  users
Where
  ((users.group_id = 1) AND (users.name like “user%”))
Order By
  users.id Desc
limit 5 offset 0
Many-to-Many (HABTM)



case class User(name: String) extends ActiveRecord {
  lazy val groups = hasAndBelongsToMany[Group]
}

case class Group(name: String) extends ActiveRecord {
  lazy val users = hasAndBelongsToMany[User]
}
Many-to-Many (HABTM)
val   user1 = User("user1").create
val   user2 = User("user2").create
val   group1 = Group("group1").create
val   group2 = Group("group2").create

user1.groups := List(group1, group2)

user1.groups.toList
       List(Group(“group1”), Group(“group2”))
group1.users.toList
       List(User(“user1”))
Many-to-Many (hasManyThrough)
* Intermediate table's model
  case class Membership(
    userId: Long,
    projectId: Long,
    isAdmin: Boolean = false
  ) extends ActiveRecord
  {
    lazy val user = belongsTo[User]
    lazy val group = belongsTo[Group]
  }
Many-to-Many (hasManyThrough)



case class User(name: String) extends ActiveRecord {
  lazy val memberships = hasMany[Membership]
  lazy val groups =
    hasManyThrough[Group, Membership](memberships)
}

case class Group(name: String) extends ActiveRecord {
  lazy val memberships = hasMany[Membership]
  lazy val users =
    hasManyThrough[User, Membership](memberships)
}
Conditions option
case class Group(name: String) extends ActiveRecord {
  lazy val adminUsers =
    hasMany[User](conditions = Map("isAdmin" -> true))
}

 group.adminUsers << user
         user.isAdmin == true


            ForeignKey option
case class Comment(name: String) extends ActiveRecord {
  val authorId: Long
  lazy val author =
    belongsTo[User](foreignKey = “authorId”)
}
Joining tables
Client.joins[Order](
  (client, order) => client.id === order.clientId
).where(
  (client, order) => client.age.~ < 20 and order.price.~ > 1000
).select(
  (client, order) => (client.name, client.age, order.price)
).toList

  Select
   clients.name, clients.age, orders.price
  From
   clients inner join orders on (clients.id = orders.client_id)
  Where
   ((clients.age < 20) and (groups.price > 1000))
Eager loading associations
          Solution to N + 1 queries problem
       Order.includes(_.client).limit(10).map {
         order => order.client.name
       }.mkString(“n”)

Select orders.price, orders.id From orders limit 10 offset 0;

Select
 clients.name, clients.age, clients.id
From
 clients inner join orders on (clients.id = orders.client_id)
Where
 (orders.id in (1,2,3,4,5,6,7,8,9,10))
Future
Future prospects

Compile time validation (using macro)
Serialization support
Web framework support
(Offers view helpers for Play 2.x and Scalatra)
STI, Polymorphic Association
Compile time validation
     (using macro)
型安全性が確保できていない部分について
Scala macro を利用した型安全化

ActiveRecord#findBy(key: String, value: Any)

 Association(                                  fe
   conditions: Map[String, Any],         e- sa
   foreignKey: String               ttyp
 )                               No


      Type-safe binding configuration
Serialization support
  パーサを個別に定義することなく、モデルを
  定義するだけで済むように


                                 JSON
        Bind
Form               Model         XML
         View
        helper
                 Validation   MessagePack
View
Web framework support
 CRUD controller
 Form helper
      scala-activerecord-play2
      scala-activerecord-scalatra
 Code generator           Controller, Model, View
sbt generate scaffold Person name:string:required age:int

      scala-activerecord-play2-sbt-plugin
      scala-activerecord-scalatra-sbt-plugin etc..
Thank you

Weitere ähnliche Inhalte

Was ist angesagt?

Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Railsrstankov
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of JavascriptTarek Yehia
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmineRubyc Slides
 
JavaScript Unit Testing with Jasmine
JavaScript Unit Testing with JasmineJavaScript Unit Testing with Jasmine
JavaScript Unit Testing with JasmineRaimonds Simanovskis
 
Hidden Treasures in Project Wonder
Hidden Treasures in Project WonderHidden Treasures in Project Wonder
Hidden Treasures in Project WonderWO Community
 
Softshake 2013: 10 reasons why java developers are jealous of Scala developers
Softshake 2013: 10 reasons why java developers are jealous of Scala developersSoftshake 2013: 10 reasons why java developers are jealous of Scala developers
Softshake 2013: 10 reasons why java developers are jealous of Scala developersMatthew Farwell
 
Omnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the ThingsOmnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the ThingsJustin Edelson
 
Rapid Prototyping with Solr
Rapid Prototyping with SolrRapid Prototyping with Solr
Rapid Prototyping with SolrErik Hatcher
 
Testing Javascript with Jasmine
Testing Javascript with JasmineTesting Javascript with Jasmine
Testing Javascript with JasmineTim Tyrrell
 
Demystifying Oak Search
Demystifying Oak SearchDemystifying Oak Search
Demystifying Oak SearchJustin Edelson
 
Rapid prototyping search applications with solr
Rapid prototyping search applications with solrRapid prototyping search applications with solr
Rapid prototyping search applications with solrLucidworks (Archived)
 
Testing Web Applications with GEB
Testing Web Applications with GEBTesting Web Applications with GEB
Testing Web Applications with GEBHoward Lewis Ship
 
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkBen Scofield
 
Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Jiayun Zhou
 
Beyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeBeyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeAijaz Ansari
 
Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Juriy Zaytsev
 
Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015Lukas Ruebbelke
 

Was ist angesagt? (20)

Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of Javascript
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
 
JavaScript Unit Testing with Jasmine
JavaScript Unit Testing with JasmineJavaScript Unit Testing with Jasmine
JavaScript Unit Testing with Jasmine
 
Hidden Treasures in Project Wonder
Hidden Treasures in Project WonderHidden Treasures in Project Wonder
Hidden Treasures in Project Wonder
 
Softshake 2013: 10 reasons why java developers are jealous of Scala developers
Softshake 2013: 10 reasons why java developers are jealous of Scala developersSoftshake 2013: 10 reasons why java developers are jealous of Scala developers
Softshake 2013: 10 reasons why java developers are jealous of Scala developers
 
Omnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the ThingsOmnisearch in AEM 6.2 - Search All the Things
Omnisearch in AEM 6.2 - Search All the Things
 
Fatc
FatcFatc
Fatc
 
Rapid Prototyping with Solr
Rapid Prototyping with SolrRapid Prototyping with Solr
Rapid Prototyping with Solr
 
Testing Javascript with Jasmine
Testing Javascript with JasmineTesting Javascript with Jasmine
Testing Javascript with Jasmine
 
Demystifying Oak Search
Demystifying Oak SearchDemystifying Oak Search
Demystifying Oak Search
 
Rapid prototyping search applications with solr
Rapid prototyping search applications with solrRapid prototyping search applications with solr
Rapid prototyping search applications with solr
 
Testing Web Applications with GEB
Testing Web Applications with GEBTesting Web Applications with GEB
Testing Web Applications with GEB
 
Frontin like-a-backer
Frontin like-a-backerFrontin like-a-backer
Frontin like-a-backer
 
All I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web FrameworkAll I Need to Know I Learned by Writing My Own Web Framework
All I Need to Know I Learned by Writing My Own Web Framework
 
Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015Akka Cluster in Java - JCConf 2015
Akka Cluster in Java - JCConf 2015
 
Beyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeBeyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCode
 
Say Hello To Ecmascript 5
Say Hello To Ecmascript 5Say Hello To Ecmascript 5
Say Hello To Ecmascript 5
 
Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015Impress Your Friends with EcmaScript 2015
Impress Your Friends with EcmaScript 2015
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 

Andere mochten auch

Scala in Model-Driven development for Apparel Cloud Platform
Scala in Model-Driven development for Apparel Cloud PlatformScala in Model-Driven development for Apparel Cloud Platform
Scala in Model-Driven development for Apparel Cloud PlatformTomoharu ASAMI
 
WebStormでできること
WebStormでできることWebStormでできること
WebStormでできることkamiyam .
 
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜scalaconfjp
 
タイムマシン採用:明日のエンタープライズJavaの世界を予想する -Java EE7/クラウド/Docker/etc.-
タイムマシン採用:明日のエンタープライズJavaの世界を予想する -Java EE7/クラウド/Docker/etc.-タイムマシン採用:明日のエンタープライズJavaの世界を予想する -Java EE7/クラウド/Docker/etc.-
タイムマシン採用:明日のエンタープライズJavaの世界を予想する -Java EE7/クラウド/Docker/etc.-Takakiyo Tanaka
 
Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3
Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3
Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3Toshiaki Maki
 
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugjPhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugjHisateru Tanaka
 
Java EEハンズオン資料 JJUG CCC 2015 Fall
Java EEハンズオン資料 JJUG CCC 2015 FallJava EEハンズオン資料 JJUG CCC 2015 Fall
Java EEハンズオン資料 JJUG CCC 2015 FallMasatoshi Tada
 
訳書『デザイニング・インターフェース』について
訳書『デザイニング・インターフェース』について訳書『デザイニング・インターフェース』について
訳書『デザイニング・インターフェース』についてNoriyo Asano
 
実践アニメーション
実践アニメーション実践アニメーション
実践アニメーションNaoya Yunoue
 
Akkaの翻訳みんなでやろう Let's translate akka doc
Akkaの翻訳みんなでやろう Let's translate akka docAkkaの翻訳みんなでやろう Let's translate akka doc
Akkaの翻訳みんなでやろう Let's translate akka doc賢太郎 前多
 
Atomic Design powered by React @ AbemaTV
Atomic Design powered by React @ AbemaTVAtomic Design powered by React @ AbemaTV
Atomic Design powered by React @ AbemaTVYusuke Goto
 
リアクティブ・アーキテクチャ ~大規模サービスにおける必要性と課題〜 #devsumi
リアクティブ・アーキテクチャ ~大規模サービスにおける必要性と課題〜 #devsumiリアクティブ・アーキテクチャ ~大規模サービスにおける必要性と課題〜 #devsumi
リアクティブ・アーキテクチャ ~大規模サービスにおける必要性と課題〜 #devsumiYuta Okamoto
 

Andere mochten auch (14)

IDEALIZE YOU
IDEALIZE YOUIDEALIZE YOU
IDEALIZE YOU
 
Scala in Model-Driven development for Apparel Cloud Platform
Scala in Model-Driven development for Apparel Cloud PlatformScala in Model-Driven development for Apparel Cloud Platform
Scala in Model-Driven development for Apparel Cloud Platform
 
WebStormでできること
WebStormでできることWebStormでできること
WebStormでできること
 
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜
芸者東京とScala〜おみせやさんから脳トレクエストまでの軌跡〜
 
タイムマシン採用:明日のエンタープライズJavaの世界を予想する -Java EE7/クラウド/Docker/etc.-
タイムマシン採用:明日のエンタープライズJavaの世界を予想する -Java EE7/クラウド/Docker/etc.-タイムマシン採用:明日のエンタープライズJavaの世界を予想する -Java EE7/クラウド/Docker/etc.-
タイムマシン採用:明日のエンタープライズJavaの世界を予想する -Java EE7/クラウド/Docker/etc.-
 
Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3
Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3
Reactive Webアプリケーション - そしてSpring 5へ #jjug_ccc #ccc_ef3
 
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugjPhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
 
Java EEハンズオン資料 JJUG CCC 2015 Fall
Java EEハンズオン資料 JJUG CCC 2015 FallJava EEハンズオン資料 JJUG CCC 2015 Fall
Java EEハンズオン資料 JJUG CCC 2015 Fall
 
訳書『デザイニング・インターフェース』について
訳書『デザイニング・インターフェース』について訳書『デザイニング・インターフェース』について
訳書『デザイニング・インターフェース』について
 
実践アニメーション
実践アニメーション実践アニメーション
実践アニメーション
 
Akkaの翻訳みんなでやろう Let's translate akka doc
Akkaの翻訳みんなでやろう Let's translate akka docAkkaの翻訳みんなでやろう Let's translate akka doc
Akkaの翻訳みんなでやろう Let's translate akka doc
 
Atomic Design powered by React @ AbemaTV
Atomic Design powered by React @ AbemaTVAtomic Design powered by React @ AbemaTV
Atomic Design powered by React @ AbemaTV
 
リアクティブ・アーキテクチャ ~大規模サービスにおける必要性と課題〜 #devsumi
リアクティブ・アーキテクチャ ~大規模サービスにおける必要性と課題〜 #devsumiリアクティブ・アーキテクチャ ~大規模サービスにおける必要性と課題〜 #devsumi
リアクティブ・アーキテクチャ ~大規模サービスにおける必要性と課題〜 #devsumi
 
Atomic design
Atomic designAtomic design
Atomic design
 

Ähnlich wie Scala ActiveRecord

pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
ScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersKazuhiro Sera
 
The Ring programming language version 1.5.4 book - Part 44 of 185
The Ring programming language version 1.5.4 book - Part 44 of 185The Ring programming language version 1.5.4 book - Part 44 of 185
The Ring programming language version 1.5.4 book - Part 44 of 185Mahmoud Samir Fayed
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189Mahmoud Samir Fayed
 
Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010Derek Chen-Becker
 
Venturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby DeveloperVenturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby DeveloperJon Kruger
 
Java7 New Features and Code Examples
Java7 New Features and Code ExamplesJava7 New Features and Code Examples
Java7 New Features and Code ExamplesNaresh Chintalcheru
 
Http4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackGaryCoady
 
jQuery Rescue Adventure
jQuery Rescue AdventurejQuery Rescue Adventure
jQuery Rescue AdventureAllegient
 
Lambda functions in java 8
Lambda functions in java 8Lambda functions in java 8
Lambda functions in java 8James Brown
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Jonas Bonér
 
Pragmatic Real-World Scala
Pragmatic Real-World ScalaPragmatic Real-World Scala
Pragmatic Real-World Scalaparag978978
 
Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Leonardo Soto
 
The Ring programming language version 1.5.3 book - Part 44 of 184
The Ring programming language version 1.5.3 book - Part 44 of 184The Ring programming language version 1.5.3 book - Part 44 of 184
The Ring programming language version 1.5.3 book - Part 44 of 184Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 54 of 184
The Ring programming language version 1.5.3 book - Part 54 of 184The Ring programming language version 1.5.3 book - Part 54 of 184
The Ring programming language version 1.5.3 book - Part 54 of 184Mahmoud Samir Fayed
 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?Tomasz Wrobel
 

Ähnlich wie Scala ActiveRecord (20)

pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
ScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for Beginners
 
The Ring programming language version 1.5.4 book - Part 44 of 185
The Ring programming language version 1.5.4 book - Part 44 of 185The Ring programming language version 1.5.4 book - Part 44 of 185
The Ring programming language version 1.5.4 book - Part 44 of 185
 
The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189The Ring programming language version 1.6 book - Part 46 of 189
The Ring programming language version 1.6 book - Part 46 of 189
 
Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010Starting with Scala : Frontier Developer's Meetup December 2010
Starting with Scala : Frontier Developer's Meetup December 2010
 
Venturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby DeveloperVenturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Venturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
 
Java7 New Features and Code Examples
Java7 New Features and Code ExamplesJava7 New Features and Code Examples
Java7 New Features and Code Examples
 
Http4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web Stack
 
jQuery Rescue Adventure
jQuery Rescue AdventurejQuery Rescue Adventure
jQuery Rescue Adventure
 
Lambda functions in java 8
Lambda functions in java 8Lambda functions in java 8
Lambda functions in java 8
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
 
Pragmatic Real-World Scala
Pragmatic Real-World ScalaPragmatic Real-World Scala
Pragmatic Real-World Scala
 
Sql alchemy bpstyle_4
Sql alchemy bpstyle_4Sql alchemy bpstyle_4
Sql alchemy bpstyle_4
 
Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)
 
The Ring programming language version 1.5.3 book - Part 44 of 184
The Ring programming language version 1.5.3 book - Part 44 of 184The Ring programming language version 1.5.3 book - Part 44 of 184
The Ring programming language version 1.5.3 book - Part 44 of 184
 
The Ring programming language version 1.5.3 book - Part 54 of 184
The Ring programming language version 1.5.3 book - Part 54 of 184The Ring programming language version 1.5.3 book - Part 54 of 184
The Ring programming language version 1.5.3 book - Part 54 of 184
 
(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
 

Mehr von scalaconfjp

脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~scalaconfjp
 
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会scalaconfjp
 
GraalVM Overview Compact version
GraalVM Overview Compact versionGraalVM Overview Compact version
GraalVM Overview Compact versionscalaconfjp
 
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...scalaconfjp
 
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...scalaconfjp
 
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan GoyeauScala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeauscalaconfjp
 
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...scalaconfjp
 
Scala ♥ Graal by Flavio Brasil
Scala ♥ Graal by Flavio BrasilScala ♥ Graal by Flavio Brasil
Scala ♥ Graal by Flavio Brasilscalaconfjp
 
Introduction to GraphQL in Scala
Introduction to GraphQL in ScalaIntroduction to GraphQL in Scala
Introduction to GraphQL in Scalascalaconfjp
 
Safety Beyond Types
Safety Beyond TypesSafety Beyond Types
Safety Beyond Typesscalaconfjp
 
Reactive Kafka with Akka Streams
Reactive Kafka with Akka StreamsReactive Kafka with Akka Streams
Reactive Kafka with Akka Streamsscalaconfjp
 
Reactive microservices with play and akka
Reactive microservices with play and akkaReactive microservices with play and akka
Reactive microservices with play and akkascalaconfjp
 
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメントScalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメントscalaconfjp
 
DWANGO by ドワンゴ
DWANGO by ドワンゴDWANGO by ドワンゴ
DWANGO by ドワンゴscalaconfjp
 
OCTOPARTS by M3, Inc.
OCTOPARTS by M3, Inc.OCTOPARTS by M3, Inc.
OCTOPARTS by M3, Inc.scalaconfjp
 
Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.scalaconfjp
 
統計をとって高速化する
Scala開発 by CyberZ,Inc.
統計をとって高速化する
Scala開発 by CyberZ,Inc.統計をとって高速化する
Scala開発 by CyberZ,Inc.
統計をとって高速化する
Scala開発 by CyberZ,Inc.scalaconfjp
 
Short Introduction of Implicit Conversion by TIS, Inc.
Short Introduction of Implicit Conversion by TIS, Inc.Short Introduction of Implicit Conversion by TIS, Inc.
Short Introduction of Implicit Conversion by TIS, Inc.scalaconfjp
 
ビズリーチ x ScalaMatsuri by BIZREACH, Inc.
ビズリーチ x ScalaMatsuri  by BIZREACH, Inc.ビズリーチ x ScalaMatsuri  by BIZREACH, Inc.
ビズリーチ x ScalaMatsuri by BIZREACH, Inc.scalaconfjp
 
sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策scalaconfjp
 

Mehr von scalaconfjp (20)

脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
脆弱性対策のためのClean Architecture ~脆弱性に対するレジリエンスを確保せよ~
 
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
Alp x BizReach SaaS事業を営む2社がお互い気になることをゆるゆる聞いてみる会
 
GraalVM Overview Compact version
GraalVM Overview Compact versionGraalVM Overview Compact version
GraalVM Overview Compact version
 
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
Run Scala Faster with GraalVM on any Platform / GraalVMで、どこでもScalaを高速実行しよう by...
 
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
Monitoring Reactive Architecture Like Never Before / 今までになかったリアクティブアーキテクチャの監視...
 
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan GoyeauScala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
Scala 3, what does it means for me? / Scala 3って、私にはどんな影響があるの? by Joan Goyeau
 
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
 
Scala ♥ Graal by Flavio Brasil
Scala ♥ Graal by Flavio BrasilScala ♥ Graal by Flavio Brasil
Scala ♥ Graal by Flavio Brasil
 
Introduction to GraphQL in Scala
Introduction to GraphQL in ScalaIntroduction to GraphQL in Scala
Introduction to GraphQL in Scala
 
Safety Beyond Types
Safety Beyond TypesSafety Beyond Types
Safety Beyond Types
 
Reactive Kafka with Akka Streams
Reactive Kafka with Akka StreamsReactive Kafka with Akka Streams
Reactive Kafka with Akka Streams
 
Reactive microservices with play and akka
Reactive microservices with play and akkaReactive microservices with play and akka
Reactive microservices with play and akka
 
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメントScalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
Scalaに対して意識の低いエンジニアがScalaで何したかの話, by 芸者東京エンターテインメント
 
DWANGO by ドワンゴ
DWANGO by ドワンゴDWANGO by ドワンゴ
DWANGO by ドワンゴ
 
OCTOPARTS by M3, Inc.
OCTOPARTS by M3, Inc.OCTOPARTS by M3, Inc.
OCTOPARTS by M3, Inc.
 
Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.Try using Aeromock by Marverick, Inc.
Try using Aeromock by Marverick, Inc.
 
統計をとって高速化する
Scala開発 by CyberZ,Inc.
統計をとって高速化する
Scala開発 by CyberZ,Inc.統計をとって高速化する
Scala開発 by CyberZ,Inc.
統計をとって高速化する
Scala開発 by CyberZ,Inc.
 
Short Introduction of Implicit Conversion by TIS, Inc.
Short Introduction of Implicit Conversion by TIS, Inc.Short Introduction of Implicit Conversion by TIS, Inc.
Short Introduction of Implicit Conversion by TIS, Inc.
 
ビズリーチ x ScalaMatsuri by BIZREACH, Inc.
ビズリーチ x ScalaMatsuri  by BIZREACH, Inc.ビズリーチ x ScalaMatsuri  by BIZREACH, Inc.
ビズリーチ x ScalaMatsuri by BIZREACH, Inc.
 
sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策sbt, past and future / sbt, 傾向と対策
sbt, past and future / sbt, 傾向と対策
 

Scala ActiveRecord

  • 1. Scala ActiveRecord The elegant ORM library for Scala
  • 2. Author github.com/y-yoshinoya 主にScalaとRuby on Railsの業務をやってます Play Framework 2.0 を Beta バージョンから業務で 採用を試みる DBライブラリにはSqueryl, Anorm, ScalaQuery を 採用 Scala ActiveRecord はより使えるDBライブラリを求 めた結果の産物
  • 5. Features Version 0.1 Squeryl wrapper Type-safe (most part) Rails ActiveRecord-like operability CoC (Convention over Configuration) DRY (Don't Repeat Yourself) principles. Auto transaction control “Type-safed ActiveRecord model for Scala”
  • 6. Features Version 0.2 Validations Associations Testing support Improving query performance Scala 2.10 support
  • 8. Why created? (1) Scalaの大半のDBライブラリはSQLをWrapしたもの 関数型言語としての方向性としては正しい、かつ合理 的な方法 val selectCountries = SQL("Select * from Country") val countries = selectCountries().map(row => row[String]("code") -> row[String]("name") ).toList しかし、オブジェクト (Model) にマッピングするため には全て自前で定義しないといけない Not DRY!!
  • 9. Why created? (2) 関連マッピングをまともに扱いたい・なるべく簡単に 使いたい ClassごとにFinder methodを定義しなければならない などDRYに書けない 本質的な処理についてだけ記述したいのにできない。 操作を書きたいのであってSQLを書きたいわけでは ない Not DRY!!!
  • 10. Other libraries Anorm Slick (ScalaQuery) Squeryl
  • 11. (1) Anorm ORMではなく、Model層を提供しない設計思想のため、 どうしてもClassごとに同じようなメソッドを定義せざ るを得なくなる case class Person(id: Pk[Long], name: String) object Person { def create(person: Person): Unit = { DB.withConnection { implicit connection => SQL("insert into person(name) values ({name})").on( 'name -> person.name).executeUpdate() } } ... } Not DRY...
  • 12. (2) Slick (ScalaQuery) Queryの使用感は良いが、テーブル定義がやや冗長。 Modelとマッピングする場合、その対応をテーブルごと に明示的に記述する必要がある case class Member(id: Int, name: String, email: Option[String]) object Members extends Table[Member]("MEMBERS") { def id = column[Int]("ID", O.PrimaryKey, O.AutoInc) def name = column[String]("NAME") def email = column[Option[String]]("EMAIL") def * = id.? ~ name ~ email <> (Member, Member.unapply _) } Query interface is Good. But, not DRY defining tables.
  • 13. (3) Squeryl ScalaのORMとしては最も良い出来 Queryに対してさらに条件を指定したQueryを作成すると Sub-QueryなSQLが呼び出される val query = from(table)(t => where(t.id.~ > 20) select(t)) from(query)(t => where(t.name like “%test%”) select(t)) Select * From (Select * From table Where table.id > 20) q1 Where q1.name like “test” Very nice ORM library. Need to be aware of the SQL performance.
  • 14. Improvements from Squeryl Queryの合成結果が単なるSub Queryにならないように    Queryの条件をパフォーマンス劣化せず流用可能 val query = Table.where(_.id.~ > 20) query.where(_.name like “%test%”).toList Select * From table Where table.id > 20 and table.name like “test” Generates more simple SQL statement.
  • 15. Improvements from Squeryl Iterable#iterator にアクセスした時点で inTransaction す るよう変更 save, delete 時にデフォルトで inTransaction するように もちろん明示的に transaction もできる // auto inTransaction query.toList model.save model.delete
  • 16. Improvements from Squeryl 関連設定ルールをCoCで結び付けられるように 関連参照時のQueryがSubQueryにならないように Eager loadingを実装 Simpler association definition rule.
  • 17. Association definition (Squeryl) object Schema extends Schema { val foo = table[Foo] val bar = table[Bar] val fooToBar = oneToManyRelation(Foo, Bar).via( (f, b) => f.barId === b.id ) } class Foo(var barId: Long) extends SomeEntity {   lazy val bar: ManyToOne[Bar] = schema.fooToBar.right(this) } class Bar(var bar: String) extends SomeEntity {   lazy val foos: OneToMany[Foo] = schema.fooToBar.left(this) }
  • 18. Association definition (Scala ActiveRecord) object Tables extends ActiveRecordTables { val foo = table[Foo] val bar = table[Bar] } class Foo(var barId: Long) extends ActiveRecord {   lazy val bar = belongsTo[Bar] } class Bar(var bar: String) extends ActiveRecord {   lazy val foos = hasMany[Foo] }
  • 20. Model implementation case class Person(var name: String, var age: Int) extends ActiveRecord object Person extends ActiveRecordCompanion[Person] Schema definition object Tables extends ActiveRecordTables { val people = table[Person] }
  • 21. Create val person = Person("person1", 25) person.save true val person = Person("person1", 25).create Person(“person1”, 25)
  • 22. Read Person.find(1) Some(Person(“person1”)) Person.toList List(Person(“person1”), ...) Person.findBy(“name”, “john”) Some(Person(“john”)) * Type-safe approach Person.where(_.name === “john”).headOption Some(Person(“john”))
  • 23. Update Person.find(1).foreach { p => p.name = “aaa” p.age = 19 Callback hook p.save Validations } Person.forceUpdate(_.id === 1)( _.name := “aa”, _.age := 19 )
  • 24. Delete Person.where(_.name === “john”) .foreach(_.delete) Person.find(1) match { case Some(person) => person.delete case _ => } Person.delete(1)
  • 26. Single object finder val client = Client.find(10) Some(Client) or None val john = Client.findBy("name", "john") Some(Client("john")) or None val john25 = Client.findBy(("name", "john"), ("age", 25)) Some(Client("john", 25)) or None
  • 27. Multiple object finder Clients.where(c => c.name === "john" and c.age.~ > 25 ).toList Clients.where(_.name === "john") .where(_.age.~ > 25) .toList Select clients.name, clients.age, clients.id From clients Where clients.name = “john” and clients.age > 25
  • 28. Using `Iterable` methods val client = Client.head First Client or RecordNotFoundException val client = Client.lastOption Some(Last Client) or None val (adults, children) = Client.partition(_.age >= 20) Parts of clients
  • 29. Ordering * Simple order (ORDER BY client.name) Client.orderBy(_.name) * Set order (use for 'asc' or 'desc') Client.orderBy(_.name asc) * Ordering by multiple fields Client.orderBy(_.name asc, _.age desc)
  • 30. Limit and Offset Client.limit(10) Client.page(2, 5) Existence of objects Client.exists(_.name like "john%") true or false
  • 31. Selecting specific fields Client.select(_.name).toList List[String] Client.select(c => (c.name, c.age)).toList List[(String, Int)]
  • 32. Combining Queries Clients.where(_.name like "john%”) .orderBy(_.age desc) .where(_.age.~ < 25) .page(2, 5) .toList Select clients.name, clients.age, clients.id From clients Where ((clients.name like “john%”) and (clients.age < 25)) Order By clients.age Desc limit 5 offset 2
  • 33. Cache control QueryからIterableに暗黙変換される際に取得したListを キャッシュとして保持 val orders = Order.where(_.age.~ > 20) // execute SQL query, and cached query orders.toList // non-execute SQL query. orders.toList
  • 35. Annotation-based Validation case class User( @Required name: String, @Length(max=20) profile: String, @Range(min=0, max=150) age: Int ) extends ActiveRecord object User extends ActiveRecordCompanion[User]
  • 36. Validation Sample // it’s not save in the database // because the object is not valid val user = User("", “Profile”, 25).create user.isValid false user.hasErrors true user.errors.messges Seq("Name is required") user.hasError("name") true
  • 37. More functional error handling... User("John", “profile”, 20).saveEither match { case Right(user) => println(user.name) case Left(errors) => println(errors.messages) } "John" User("", “profile”, 15).saveEither match { case Right(user) => println(user.name) case Left(errors) => println(errors.messages) } "Name is required"
  • 40. Callback example case class User(login: String) extends ActiveRecord { @Transient @Length(min=8, max=20) var password: String = _ var hashedPassword: String = _ override def beforeSave() { hashedPassword = SomeLibrary.encrypt(password) } } val user = User(“john”) user.password = “raw_password” user.save Storing encrypted password
  • 42. One-to-Many case class User(name: String) extends ActiveRecord { val groupId: Option[Long] = None lazy val group = belongsTo[Group] } case class Group(name: String) extends ActiveRecord { lazy val users = hasMany[User] }
  • 43. One-to-Many val user1 = User("user1").create val user2 = User("user2").create val group1 = Group("group1").create group1.users << user1 group1.users.toList List(User("user1")) user1.group.getOrElse(Group(“group2”)) Group("group1")
  • 44. Association is Queryable group1.users.where(_.name like “user%”) .orderBy(_.id desc) .limit(5) .toList Select users.name, users.id From users Where ((users.group_id = 1) AND (users.name like “user%”)) Order By users.id Desc limit 5 offset 0
  • 45. Many-to-Many (HABTM) case class User(name: String) extends ActiveRecord { lazy val groups = hasAndBelongsToMany[Group] } case class Group(name: String) extends ActiveRecord { lazy val users = hasAndBelongsToMany[User] }
  • 46. Many-to-Many (HABTM) val user1 = User("user1").create val user2 = User("user2").create val group1 = Group("group1").create val group2 = Group("group2").create user1.groups := List(group1, group2) user1.groups.toList List(Group(“group1”), Group(“group2”)) group1.users.toList List(User(“user1”))
  • 47. Many-to-Many (hasManyThrough) * Intermediate table's model case class Membership( userId: Long, projectId: Long, isAdmin: Boolean = false ) extends ActiveRecord { lazy val user = belongsTo[User] lazy val group = belongsTo[Group] }
  • 48. Many-to-Many (hasManyThrough) case class User(name: String) extends ActiveRecord { lazy val memberships = hasMany[Membership] lazy val groups = hasManyThrough[Group, Membership](memberships) } case class Group(name: String) extends ActiveRecord { lazy val memberships = hasMany[Membership] lazy val users = hasManyThrough[User, Membership](memberships) }
  • 49. Conditions option case class Group(name: String) extends ActiveRecord { lazy val adminUsers = hasMany[User](conditions = Map("isAdmin" -> true)) } group.adminUsers << user user.isAdmin == true ForeignKey option case class Comment(name: String) extends ActiveRecord { val authorId: Long lazy val author = belongsTo[User](foreignKey = “authorId”) }
  • 50. Joining tables Client.joins[Order]( (client, order) => client.id === order.clientId ).where( (client, order) => client.age.~ < 20 and order.price.~ > 1000 ).select( (client, order) => (client.name, client.age, order.price) ).toList Select clients.name, clients.age, orders.price From clients inner join orders on (clients.id = orders.client_id) Where ((clients.age < 20) and (groups.price > 1000))
  • 51. Eager loading associations Solution to N + 1 queries problem Order.includes(_.client).limit(10).map { order => order.client.name }.mkString(“n”) Select orders.price, orders.id From orders limit 10 offset 0; Select clients.name, clients.age, clients.id From clients inner join orders on (clients.id = orders.client_id) Where (orders.id in (1,2,3,4,5,6,7,8,9,10))
  • 53. Future prospects Compile time validation (using macro) Serialization support Web framework support (Offers view helpers for Play 2.x and Scalatra) STI, Polymorphic Association
  • 54. Compile time validation (using macro) 型安全性が確保できていない部分について Scala macro を利用した型安全化 ActiveRecord#findBy(key: String, value: Any) Association( fe conditions: Map[String, Any], e- sa foreignKey: String ttyp ) No Type-safe binding configuration
  • 55. Serialization support パーサを個別に定義することなく、モデルを 定義するだけで済むように JSON Bind Form Model XML View helper Validation MessagePack View
  • 56. Web framework support CRUD controller Form helper scala-activerecord-play2 scala-activerecord-scalatra Code generator Controller, Model, View sbt generate scaffold Person name:string:required age:int scala-activerecord-play2-sbt-plugin scala-activerecord-scalatra-sbt-plugin etc..