SlideShare ist ein Scribd-Unternehmen logo
1 von 40
ScalikeJDBC
Tutorial
for Beginners
@seratch
Kazuhiro Sera
Table of contents
What’s this?
ConnectionPool
Implicit Session
SQL Syntax
Query DSL
More Features
Get Started Now
What’s this?
ScalikeJDBC
http://git.io/scalikejdbc
A tidy SQL-based DB access library
for Scala developers.
...SQL-based?
SQL-based
import scalikejdbc._, SQLInterpolation._
val id = 123
// Anorm-like API for Scala 2.9
val name = SQL(“select name from company where id = {id}”)
.bindByName(‘id -> id).map(rs => rs.string(“name”)).single.apply()
// SQL Interpolation since 2.10
val name = sql”select name from company where id = ${id}”
.map(rs => rs.string(“name”)).single.apply()
// Query DSL
val name = withSQL {
select(c.name).from(Company as c).where.eq(c.id, id)
}.map(rs => rs.string(c.resultName.name)).single.apply()
Everybody knows SQL
We don’t need something new and
different from SQL.
Maybe, you can write the code on the
previous slide immediately, right?
Because you already know SQL.
ConnectionPool
Easy-to-use CP
DB block such as DB.readOnly { ... }
borrows a connection from
ConnectionPool.
Since ConnectionPool is a singleton
object, you can easily borrow
anywhere.
ConnectionPool
import scalikejdbc._
Class.forName(“org.h2.Driver”)
// default connection pool
val (url, user, password) = (“jdbc:h2:mem:db”, “sa”, “”)
ConnectionPool.singleton(url, user, password)
val conn: java.sql.Connection = ConnectionPool.borrow()
val names: List[String] = DB readOnly { implicit session =>
sql”select name from company”.map(_.string(“name”).list.apply()
}
// named connection pool
val poolSettings = new ConnectionPoolSettings(maxSize = 50)
ConnectionPool.add(‘secondary, url, user, passsword, poolSettings)
NamedDB(‘secondary) readOnly { implicit session =>
DBCP by default
By default, only Commons DBCP
implementation is provided.
It’s also possible to implement your
preferred connection pool.
(e.g. C3P0, BoneCP)
Implicit Session
Go implicitly
DBSession represents
java.sql.Connection
with a transaction(if exists).
#apply() requires DBSession
implicitly.
Implicit DBSession
import scalikejdbc._, SQLInterpolation._
val id = 123
// DBSession usage
val name: Option[String] = DB readOnly { session: DBSession =>
session.single(“select name from company where id = ?”, id) { rs =>
rs.string(“name”)
}
}
// SQL API requires implicit DBSession
val name: Option[String] = DB readOnly { implicit session =>
sql”select name from company where id = ${id}”
.map(_.string(“name”)).single.apply()
}
Automatic
AutoSession creates & closes an ad-
hoc session if absent.
query: read-only session
update: auto-commit session
Flexible Transaction
import scalikejdbc._, SQLInterpolation._
implicit val session = AutoSession
sql”select name from company”.map(_.string(“name”)).list.apply()
def addCompany(name: String)(implicit s: DBSession = AutoSession) {
sql”insert into company values (${name})”.update.apply()
}
def getAllNames()(implicit s: DBSession = AutoSession): List[String] = {
sql”select name from company”.map(_.string(“name”)).list.apply()
}
val names: List[String] = getAllNames() // read-only session
DB localTx { implicit session =>
addCompany(“Typesafe”) // within a transaction
getAllNames() // within a transaction, includes “Typesafe”
}
SQL Syntax
SQLSyntax?
// SQLSyntax = a part of SQL object, will be embedded as-is
val c: SQLSyntax = sqls”count(*)”
val bobby: String = “Bob%”
val query = sql”select ${c} from members where name like ${bobby}”
// -> “select count(*) from members where name like ?”
A part of SQL object which will be
embedded as-is.
SQLSyntaxSupport
SQLSyntaxSupport provides DRY and
type safe SQL.
- CoC but configurable
- Write complex join queries
- Using type-dynamic(similar to
Ruby’s method-missing) but have
compile-time check with macro
CoC Rules
// Scala object
case class GroupMember(id: Long, fullName: Option[String] = None)
obejct GroupMember extends SQLSyntaxSupport[GroupMember]
// DDL
create table group_member {
id bigint not null primary key,
full_name varchar(255)
}
Simply snake_case’d name
Customize it
// Scala object
case class GroupMember(id: Long, fullName: Option[String] = None)
obejct GroupMember extends SQLSyntaxSupport[GroupMember] {
override val tableName = “group_members”
override val nameConverters = Map(“fullName” -> “fullname”)
}
// DDL
create table group_members {
id bigint not null primary key,
fullname varchar(255)
}
Query & Extracting
import scalikejdbc._, SQLInterpolation._
// entity class (Plain Old Scala Object)
case class Member(id: Long, fullName: Option[String] = None)
// companion object for entity
obejct Member extends SQLSyntaxSupport[Member] {
def apply(m: ResultName[Member])(rs: WrappedResultSet) = new Member(
id = rs.long(m.id), name = rs.stringOpt(m.fullName)
)
)
val m = Member.syntax(“m”)
val id = 123
val memebr: Option[Member] = DB readOnly { implicit s =>
sql”select ${m.result.*} from ${Member as m} where ${m.id} = ${id}”
.map(Member(m.resultName)).single.apply()
}
result? resultName?
val m = Member.syntax(“m”)
m.fullName == “m.full_name”
m.result.fullName == “m.full_name as fn_on_m”
m.resultName.fullName == “fn_on_m”
Scala:
sql”select ${m.result.fullName} from ${Member as m} where ${m.id} = 123”
SQL:
“select m.full_name as fn_on_m from member m where m.id = 123”
ResultSet extractor:
val name = sql”...”.map(rs => rs.string(m.resultName.fullName)).single.apply()
// extracting “fn_on_m” from ResultSet
Type safe dynamic
import scalikejdbc._, SQLInterpolation._
val m = Member.syntax(“m”)
val id = 123
val memebr: Option[Member] = DB readOnly { implicit s =>
sql”select ${m.result.fullNamee} from ${Member as m} where ${m.id} = ${id}”
.map(Member(m.resultName)).single.apply()
}
<console>:28: error: Member#fullNamee not found. Expected fields are #id,
#fullName, #createdAt, #deletedAt.
m.fullNamee
^
Query DSL
Uniqueness
- DBSession inspired by Querulous
- SQL(String) inspired by Anorm
- sql”...” inspired by Slick
Query DSL is surely
ScalikeJDBC’s original
way!
What’s Query DSL
- Just appends SQL parts
- Type safe and pragmatic
- Easy to understand
- Not composable but reusable
- Parts from sqls object
- Append sqls”...” when needed
Query DSL examples
import scalikejdbc._, SQLInterpolation._
implicit val session = AutoSession
val c = Company.syntax(“c”)
val id = 123
val company: Option[Company] = withSQL {
select.from(Company as c).where.eq(c.id, id)
}.map(Company(c.resultName)).single.apply()
insert.into(Company).values(123, “Typesafe”)
val column = Company.column
update(Company).set(column.name -> “Oracle”).where.eq(column.id, 123)
delete.from(Company).where.eq(column.id, 123)
Joins, one-to-x API
val programmerWithSkills = withSQL {
select
.from(Programmer as p)
.leftJoin(Company as c).on(p.companyId, c.id)
.leftJoin(ProgrammerSkill as ps).on(ps.programmerId, p.id)
.leftJoin(Skill as s).(ps.skillId, s.id)
.where
.eq(p.id, id)
.and
.isNull(p.deletedAt)
}
.one(Programmer(p, c))
.toMany(SKill.opt(s))
.map { (pg, skills) => pg.copy(skills = skills) }
.single.apply()
Sub query, Paging
val noSkillProgrammers = withSQL {
select
.from(Programmer as p)
.leftJoin(Company as c).on(p.companyId, c.id)
.where
.notIn(p.id,
select(sqls.distinct(ps.programmerId)).from(ProgrammerSkill as ps))
.isNull(p.deletedAt)
.limit(10).offset(0)
.orderBy(p.id).desc
}
.map(Programmer(p, c))
.list.apply()
sqls.xxx, sqls”...”
val userId =
val orderCount: Long = withSQL {
select(sqls.count(sqls.distinct(o.id))) // sqls object
.from(Order as o)
.innerJoin(Product as p).on(p.id,o.productId)
.where
.append(sqls”${o.userId} = ${userId}”) // direct SQL embedding
}
.map(rs => rs.long(1))
.single.apply().get
More and More
- insert select
- groupBy, having
- in, exists, like, between
- union, unionAll
- withRoundBracket { ... }
- dynamic(And|Or)Conditions { ... }
In detail:
QueryDSLFeature.scala
QueryInterfaceSpec.scala
More Features
Code Generator
- sbt plugin
- Code from existing tables
- project/scalikejdbc.properties
- Play2 style models and tests
In detail:
Wiki Page
sbt “scalikejdbc-gen [table-name]”
Testing with ScalaTest
import scalikejdbc._, scalatest.AutoRollback
import org.scalatest.fixture.FlatSpec
class MemberSpec extends FlatSpec with AutoRollback {
override def fixture(implicit s: DBSession) {
sql”delete from members”.update.apply()
Member.create(1, “Alice”)
}
behavior of “Member”
it should “create a new record” in { implicit s =>
val beforeCount = Member.count
Member.create(123, “Brian”)
Member.count should equal(before + 1)
}
}
Testing with specs2 (1)
import scalikejdbc._, specs2.mutable.AutoRollback
import org.specs2.mutable.Specification
object MemberSpec extends Specification {
“Member should create a new record” in new MyAutoRollback {
val beforeCount = Member.count
Member.create(123, “Brian”)
Member.count should equal(before + 1)
}
}
trait MyAutoRollback extends AutoRollback {
override def fixture(implicit s: DBSession) {
sql”delete from members”.update.apply()
Member.create(1, “Alice”)
}
}
Testing with specs2 (2)
import scalikejdbc._, specs2.AutoRollback
import org.specs2.Specification
object MemberSpec extends Specification { def is =
“Member should create a new record” ! autoRollback().create
end
}
case class autoRollback() extends AutoRollback {
override def fixture(implicit s: DBSession) {
sql”delete from members”.update.apply()
Member.create(1, “Alice”)
}
def create = this {
val beforeCount = Member.count
Member.create(123, “Brian”)
Member.count should equal(before + 1)
}
}
Play2 Support
- Integrates with Play2 seamlessly
- Read conf/application.conf
- Add plugin to conf/play.plugins
- FixturePlugin is also available
- Great contribution by @tototoshi
In detail:
Wiki Page
Get Started Now
More info
Examples
devteam-app example
QueryInterfaceSpec.scala
Reference
Wiki Pages
Users Group
ScalikeJDBC Users Group
ScalikeJDBC Users Group Japan
Enjoy!
Just write SQL
and get things done!
git.io/scalikejdbc

Weitere ähnliche Inhalte

Was ist angesagt?

Was ist angesagt? (20)

Spring data jpa
Spring data jpaSpring data jpa
Spring data jpa
 
The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)
 
Node.js File system & Streams
Node.js File system & StreamsNode.js File system & Streams
Node.js File system & Streams
 
Empower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo MixinsEmpower your App by Inheriting from Odoo Mixins
Empower your App by Inheriting from Odoo Mixins
 
Understanding LINQ in C#
Understanding LINQ in C# Understanding LINQ in C#
Understanding LINQ in C#
 
Java Arrays
Java ArraysJava Arrays
Java Arrays
 
Understanding linq
Understanding linqUnderstanding linq
Understanding linq
 
PUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBootPUC SE Day 2019 - SpringBoot
PUC SE Day 2019 - SpringBoot
 
vitest-en.pdf
vitest-en.pdfvitest-en.pdf
vitest-en.pdf
 
introduction à MongoDB
introduction à MongoDBintroduction à MongoDB
introduction à MongoDB
 
React render props
React render propsReact render props
React render props
 
React with Redux
React with ReduxReact with Redux
React with Redux
 
LINQ in C#
LINQ in C#LINQ in C#
LINQ in C#
 
Solid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJSSolid NodeJS with TypeScript, Jest & NestJS
Solid NodeJS with TypeScript, Jest & NestJS
 
C++ classes tutorials
C++ classes tutorialsC++ classes tutorials
C++ classes tutorials
 
Nest.js Introduction
Nest.js IntroductionNest.js Introduction
Nest.js Introduction
 
React state managmenet with Redux
React state managmenet with ReduxReact state managmenet with Redux
React state managmenet with Redux
 
Spring jdbc
Spring jdbcSpring jdbc
Spring jdbc
 
Why TypeScript?
Why TypeScript?Why TypeScript?
Why TypeScript?
 
Java 8 lambda expressions
Java 8 lambda expressionsJava 8 lambda expressions
Java 8 lambda expressions
 

Andere mochten auch

Andere mochten auch (15)

Learning from "Effective Scala"
Learning from "Effective Scala"Learning from "Effective Scala"
Learning from "Effective Scala"
 
States of Dolphin - MySQL最新技術情報2013秋 -
States of Dolphin - MySQL最新技術情報2013秋 -States of Dolphin - MySQL最新技術情報2013秋 -
States of Dolphin - MySQL最新技術情報2013秋 -
 
MySQL最新情報 ※2015年9月5日「第1回 関西DB勉強会」での発表資料
MySQL最新情報 ※2015年9月5日「第1回 関西DB勉強会」での発表資料MySQL最新情報 ※2015年9月5日「第1回 関西DB勉強会」での発表資料
MySQL最新情報 ※2015年9月5日「第1回 関西DB勉強会」での発表資料
 
MySQL最新動向と便利ツールMySQL Workbench
MySQL最新動向と便利ツールMySQL WorkbenchMySQL最新動向と便利ツールMySQL Workbench
MySQL最新動向と便利ツールMySQL Workbench
 
20160929 inno db_fts_jp
20160929 inno db_fts_jp20160929 inno db_fts_jp
20160929 inno db_fts_jp
 
MySQL最新情報  ※2016年12月
MySQL最新情報  ※2016年12月MySQL最新情報  ※2016年12月
MySQL最新情報  ※2016年12月
 
SQL+NoSQL!? それならMySQL Clusterでしょ。
SQL+NoSQL!? それならMySQL Clusterでしょ。SQL+NoSQL!? それならMySQL Clusterでしょ。
SQL+NoSQL!? それならMySQL Clusterでしょ。
 
MySQL Casual Talks Vol.4 「MySQL-5.6で始める全文検索 〜InnoDB FTS編〜」
MySQL Casual Talks Vol.4 「MySQL-5.6で始める全文検索 〜InnoDB FTS編〜」MySQL Casual Talks Vol.4 「MySQL-5.6で始める全文検索 〜InnoDB FTS編〜」
MySQL Casual Talks Vol.4 「MySQL-5.6で始める全文検索 〜InnoDB FTS編〜」
 
20150920 中国地方db勉強会
20150920 中国地方db勉強会20150920 中国地方db勉強会
20150920 中国地方db勉強会
 
いろいろ考えると日本語の全文検索もMySQLがいいね!
いろいろ考えると日本語の全文検索もMySQLがいいね!いろいろ考えると日本語の全文検索もMySQLがいいね!
いろいろ考えると日本語の全文検索もMySQLがいいね!
 
MySQL 5.7 InnoDB 日本語全文検索(その2)
MySQL 5.7 InnoDB 日本語全文検索(その2)MySQL 5.7 InnoDB 日本語全文検索(その2)
MySQL 5.7 InnoDB 日本語全文検索(その2)
 
Windows環境でのMySQL
Windows環境でのMySQLWindows環境でのMySQL
Windows環境でのMySQL
 
MySQL 5.7 InnoDB 日本語全文検索
MySQL 5.7 InnoDB 日本語全文検索MySQL 5.7 InnoDB 日本語全文検索
MySQL 5.7 InnoDB 日本語全文検索
 
Full Text Search In PostgreSQL
Full Text Search In PostgreSQLFull Text Search In PostgreSQL
Full Text Search In PostgreSQL
 
MySQL 5.7にやられないためにおぼえておいてほしいこと
MySQL 5.7にやられないためにおぼえておいてほしいことMySQL 5.7にやられないためにおぼえておいてほしいこと
MySQL 5.7にやられないためにおぼえておいてほしいこと
 

Ähnlich wie ScalikeJDBC Tutorial for Beginners

Scala ActiveRecord
Scala ActiveRecordScala ActiveRecord
Scala ActiveRecord
scalaconfjp
 
Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»
e-Legion
 
GHC Participant Training
GHC Participant TrainingGHC Participant Training
GHC Participant Training
AidIQ
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 

Ähnlich wie ScalikeJDBC Tutorial for Beginners (20)

3 database-jdbc(1)
3 database-jdbc(1)3 database-jdbc(1)
3 database-jdbc(1)
 
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
 
Scala ActiveRecord
Scala ActiveRecordScala ActiveRecord
Scala ActiveRecord
 
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
 
Knockoutjs UG meeting presentation
Knockoutjs UG meeting presentationKnockoutjs UG meeting presentation
Knockoutjs UG meeting presentation
 
The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84The Ring programming language version 1.2 book - Part 32 of 84
The Ring programming language version 1.2 book - Part 32 of 84
 
XQuery Rocks
XQuery RocksXQuery Rocks
XQuery Rocks
 
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
 
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
 
Slickdemo
SlickdemoSlickdemo
Slickdemo
 
Everything About PowerShell
Everything About PowerShellEverything About PowerShell
Everything About PowerShell
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196
 
Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»
 
jdbc
jdbcjdbc
jdbc
 
Django - sql alchemy - jquery
Django - sql alchemy - jqueryDjango - sql alchemy - jquery
Django - sql alchemy - jquery
 
The Ring programming language version 1.10 book - Part 54 of 212
The Ring programming language version 1.10 book - Part 54 of 212The Ring programming language version 1.10 book - Part 54 of 212
The Ring programming language version 1.10 book - Part 54 of 212
 
GHC Participant Training
GHC Participant TrainingGHC Participant Training
GHC Participant Training
 
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
 

Mehr von Kazuhiro Sera

Future on Servlet #scala_ks
Future on Servlet #scala_ksFuture on Servlet #scala_ks
Future on Servlet #scala_ks
Kazuhiro Sera
 
テストの運用について #m3dev
テストの運用について #m3devテストの運用について #m3dev
テストの運用について #m3dev
Kazuhiro Sera
 

Mehr von Kazuhiro Sera (20)

All I learned while working on a Scala OSS project for over six years #ScalaM...
All I learned while working on a Scala OSS project for over six years #ScalaM...All I learned while working on a Scala OSS project for over six years #ScalaM...
All I learned while working on a Scala OSS project for over six years #ScalaM...
 
Contributing to Scala OSS from East Asia #ScalaMatsuri
 Contributing to Scala OSS from East Asia #ScalaMatsuri Contributing to Scala OSS from East Asia #ScalaMatsuri
Contributing to Scala OSS from East Asia #ScalaMatsuri
 
Skinny Meetup Tokyo 2 日本語スライド
Skinny Meetup Tokyo 2 日本語スライドSkinny Meetup Tokyo 2 日本語スライド
Skinny Meetup Tokyo 2 日本語スライド
 
Skinny 2 Update
Skinny 2 UpdateSkinny 2 Update
Skinny 2 Update
 
Seasar ユーザだったプログラマが目指す OSS の世界展開 #seasarcon
Seasar ユーザだったプログラマが目指す OSS の世界展開 #seasarconSeasar ユーザだったプログラマが目指す OSS の世界展開 #seasarcon
Seasar ユーザだったプログラマが目指す OSS の世界展開 #seasarcon
 
Java エンジニアチームが始めやすい Scala コーディングスタイル #ichigayageek
Java エンジニアチームが始めやすい Scala コーディングスタイル #ichigayageekJava エンジニアチームが始めやすい Scala コーディングスタイル #ichigayageek
Java エンジニアチームが始めやすい Scala コーディングスタイル #ichigayageek
 
Future on Servlet #scala_ks
Future on Servlet #scala_ksFuture on Servlet #scala_ks
Future on Servlet #scala_ks
 
Servlet と Future の関わり方 #scala_ks
Servlet と Future の関わり方 #scala_ksServlet と Future の関わり方 #scala_ks
Servlet と Future の関わり方 #scala_ks
 
マイクロサービス運用の所感 #m3dev
マイクロサービス運用の所感 #m3devマイクロサービス運用の所感 #m3dev
マイクロサービス運用の所感 #m3dev
 
Scala が支える医療系ウェブサービス #jissenscala
Scala が支える医療系ウェブサービス #jissenscalaScala が支える医療系ウェブサービス #jissenscala
Scala が支える医療系ウェブサービス #jissenscala
 
Scala on Rails #rakutentech
Scala on Rails #rakutentechScala on Rails #rakutentech
Scala on Rails #rakutentech
 
Solid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaSolid And Sustainable Development in Scala
Solid And Sustainable Development in Scala
 
Beginning Scala with Skinny Framework #jjug_ccc
Beginning Scala with Skinny Framework #jjug_cccBeginning Scala with Skinny Framework #jjug_ccc
Beginning Scala with Skinny Framework #jjug_ccc
 
[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
 
Skinny Framework 1.0.0
Skinny Framework 1.0.0Skinny Framework 1.0.0
Skinny Framework 1.0.0
 
Skinny Framework Progress Situation
Skinny Framework Progress SituationSkinny Framework Progress Situation
Skinny Framework Progress Situation
 
Skinny Framework 進捗どうですか? #fud_scala
Skinny Framework 進捗どうですか? #fud_scalaSkinny Framework 進捗どうですか? #fud_scala
Skinny Framework 進捗どうですか? #fud_scala
 
テストの運用について #m3dev
テストの運用について #m3devテストの運用について #m3dev
テストの運用について #m3dev
 
めんどくさくない Scala #kwkni_scala
めんどくさくない Scala #kwkni_scalaめんどくさくない Scala #kwkni_scala
めんどくさくない Scala #kwkni_scala
 
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
 

Kürzlich hochgeladen

Kürzlich hochgeladen (20)

TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 

ScalikeJDBC Tutorial for Beginners

  • 2. Table of contents What’s this? ConnectionPool Implicit Session SQL Syntax Query DSL More Features Get Started Now
  • 4. ScalikeJDBC http://git.io/scalikejdbc A tidy SQL-based DB access library for Scala developers. ...SQL-based?
  • 5. SQL-based import scalikejdbc._, SQLInterpolation._ val id = 123 // Anorm-like API for Scala 2.9 val name = SQL(“select name from company where id = {id}”) .bindByName(‘id -> id).map(rs => rs.string(“name”)).single.apply() // SQL Interpolation since 2.10 val name = sql”select name from company where id = ${id}” .map(rs => rs.string(“name”)).single.apply() // Query DSL val name = withSQL { select(c.name).from(Company as c).where.eq(c.id, id) }.map(rs => rs.string(c.resultName.name)).single.apply()
  • 6. Everybody knows SQL We don’t need something new and different from SQL. Maybe, you can write the code on the previous slide immediately, right? Because you already know SQL.
  • 8. Easy-to-use CP DB block such as DB.readOnly { ... } borrows a connection from ConnectionPool. Since ConnectionPool is a singleton object, you can easily borrow anywhere.
  • 9. ConnectionPool import scalikejdbc._ Class.forName(“org.h2.Driver”) // default connection pool val (url, user, password) = (“jdbc:h2:mem:db”, “sa”, “”) ConnectionPool.singleton(url, user, password) val conn: java.sql.Connection = ConnectionPool.borrow() val names: List[String] = DB readOnly { implicit session => sql”select name from company”.map(_.string(“name”).list.apply() } // named connection pool val poolSettings = new ConnectionPoolSettings(maxSize = 50) ConnectionPool.add(‘secondary, url, user, passsword, poolSettings) NamedDB(‘secondary) readOnly { implicit session =>
  • 10. DBCP by default By default, only Commons DBCP implementation is provided. It’s also possible to implement your preferred connection pool. (e.g. C3P0, BoneCP)
  • 12. Go implicitly DBSession represents java.sql.Connection with a transaction(if exists). #apply() requires DBSession implicitly.
  • 13. Implicit DBSession import scalikejdbc._, SQLInterpolation._ val id = 123 // DBSession usage val name: Option[String] = DB readOnly { session: DBSession => session.single(“select name from company where id = ?”, id) { rs => rs.string(“name”) } } // SQL API requires implicit DBSession val name: Option[String] = DB readOnly { implicit session => sql”select name from company where id = ${id}” .map(_.string(“name”)).single.apply() }
  • 14. Automatic AutoSession creates & closes an ad- hoc session if absent. query: read-only session update: auto-commit session
  • 15. Flexible Transaction import scalikejdbc._, SQLInterpolation._ implicit val session = AutoSession sql”select name from company”.map(_.string(“name”)).list.apply() def addCompany(name: String)(implicit s: DBSession = AutoSession) { sql”insert into company values (${name})”.update.apply() } def getAllNames()(implicit s: DBSession = AutoSession): List[String] = { sql”select name from company”.map(_.string(“name”)).list.apply() } val names: List[String] = getAllNames() // read-only session DB localTx { implicit session => addCompany(“Typesafe”) // within a transaction getAllNames() // within a transaction, includes “Typesafe” }
  • 17. SQLSyntax? // SQLSyntax = a part of SQL object, will be embedded as-is val c: SQLSyntax = sqls”count(*)” val bobby: String = “Bob%” val query = sql”select ${c} from members where name like ${bobby}” // -> “select count(*) from members where name like ?” A part of SQL object which will be embedded as-is.
  • 18. SQLSyntaxSupport SQLSyntaxSupport provides DRY and type safe SQL. - CoC but configurable - Write complex join queries - Using type-dynamic(similar to Ruby’s method-missing) but have compile-time check with macro
  • 19. CoC Rules // Scala object case class GroupMember(id: Long, fullName: Option[String] = None) obejct GroupMember extends SQLSyntaxSupport[GroupMember] // DDL create table group_member { id bigint not null primary key, full_name varchar(255) } Simply snake_case’d name
  • 20. Customize it // Scala object case class GroupMember(id: Long, fullName: Option[String] = None) obejct GroupMember extends SQLSyntaxSupport[GroupMember] { override val tableName = “group_members” override val nameConverters = Map(“fullName” -> “fullname”) } // DDL create table group_members { id bigint not null primary key, fullname varchar(255) }
  • 21. Query & Extracting import scalikejdbc._, SQLInterpolation._ // entity class (Plain Old Scala Object) case class Member(id: Long, fullName: Option[String] = None) // companion object for entity obejct Member extends SQLSyntaxSupport[Member] { def apply(m: ResultName[Member])(rs: WrappedResultSet) = new Member( id = rs.long(m.id), name = rs.stringOpt(m.fullName) ) ) val m = Member.syntax(“m”) val id = 123 val memebr: Option[Member] = DB readOnly { implicit s => sql”select ${m.result.*} from ${Member as m} where ${m.id} = ${id}” .map(Member(m.resultName)).single.apply() }
  • 22. result? resultName? val m = Member.syntax(“m”) m.fullName == “m.full_name” m.result.fullName == “m.full_name as fn_on_m” m.resultName.fullName == “fn_on_m” Scala: sql”select ${m.result.fullName} from ${Member as m} where ${m.id} = 123” SQL: “select m.full_name as fn_on_m from member m where m.id = 123” ResultSet extractor: val name = sql”...”.map(rs => rs.string(m.resultName.fullName)).single.apply() // extracting “fn_on_m” from ResultSet
  • 23. Type safe dynamic import scalikejdbc._, SQLInterpolation._ val m = Member.syntax(“m”) val id = 123 val memebr: Option[Member] = DB readOnly { implicit s => sql”select ${m.result.fullNamee} from ${Member as m} where ${m.id} = ${id}” .map(Member(m.resultName)).single.apply() } <console>:28: error: Member#fullNamee not found. Expected fields are #id, #fullName, #createdAt, #deletedAt. m.fullNamee ^
  • 25. Uniqueness - DBSession inspired by Querulous - SQL(String) inspired by Anorm - sql”...” inspired by Slick Query DSL is surely ScalikeJDBC’s original way!
  • 26. What’s Query DSL - Just appends SQL parts - Type safe and pragmatic - Easy to understand - Not composable but reusable - Parts from sqls object - Append sqls”...” when needed
  • 27. Query DSL examples import scalikejdbc._, SQLInterpolation._ implicit val session = AutoSession val c = Company.syntax(“c”) val id = 123 val company: Option[Company] = withSQL { select.from(Company as c).where.eq(c.id, id) }.map(Company(c.resultName)).single.apply() insert.into(Company).values(123, “Typesafe”) val column = Company.column update(Company).set(column.name -> “Oracle”).where.eq(column.id, 123) delete.from(Company).where.eq(column.id, 123)
  • 28. Joins, one-to-x API val programmerWithSkills = withSQL { select .from(Programmer as p) .leftJoin(Company as c).on(p.companyId, c.id) .leftJoin(ProgrammerSkill as ps).on(ps.programmerId, p.id) .leftJoin(Skill as s).(ps.skillId, s.id) .where .eq(p.id, id) .and .isNull(p.deletedAt) } .one(Programmer(p, c)) .toMany(SKill.opt(s)) .map { (pg, skills) => pg.copy(skills = skills) } .single.apply()
  • 29. Sub query, Paging val noSkillProgrammers = withSQL { select .from(Programmer as p) .leftJoin(Company as c).on(p.companyId, c.id) .where .notIn(p.id, select(sqls.distinct(ps.programmerId)).from(ProgrammerSkill as ps)) .isNull(p.deletedAt) .limit(10).offset(0) .orderBy(p.id).desc } .map(Programmer(p, c)) .list.apply()
  • 30. sqls.xxx, sqls”...” val userId = val orderCount: Long = withSQL { select(sqls.count(sqls.distinct(o.id))) // sqls object .from(Order as o) .innerJoin(Product as p).on(p.id,o.productId) .where .append(sqls”${o.userId} = ${userId}”) // direct SQL embedding } .map(rs => rs.long(1)) .single.apply().get
  • 31. More and More - insert select - groupBy, having - in, exists, like, between - union, unionAll - withRoundBracket { ... } - dynamic(And|Or)Conditions { ... } In detail: QueryDSLFeature.scala QueryInterfaceSpec.scala
  • 33. Code Generator - sbt plugin - Code from existing tables - project/scalikejdbc.properties - Play2 style models and tests In detail: Wiki Page sbt “scalikejdbc-gen [table-name]”
  • 34. Testing with ScalaTest import scalikejdbc._, scalatest.AutoRollback import org.scalatest.fixture.FlatSpec class MemberSpec extends FlatSpec with AutoRollback { override def fixture(implicit s: DBSession) { sql”delete from members”.update.apply() Member.create(1, “Alice”) } behavior of “Member” it should “create a new record” in { implicit s => val beforeCount = Member.count Member.create(123, “Brian”) Member.count should equal(before + 1) } }
  • 35. Testing with specs2 (1) import scalikejdbc._, specs2.mutable.AutoRollback import org.specs2.mutable.Specification object MemberSpec extends Specification { “Member should create a new record” in new MyAutoRollback { val beforeCount = Member.count Member.create(123, “Brian”) Member.count should equal(before + 1) } } trait MyAutoRollback extends AutoRollback { override def fixture(implicit s: DBSession) { sql”delete from members”.update.apply() Member.create(1, “Alice”) } }
  • 36. Testing with specs2 (2) import scalikejdbc._, specs2.AutoRollback import org.specs2.Specification object MemberSpec extends Specification { def is = “Member should create a new record” ! autoRollback().create end } case class autoRollback() extends AutoRollback { override def fixture(implicit s: DBSession) { sql”delete from members”.update.apply() Member.create(1, “Alice”) } def create = this { val beforeCount = Member.count Member.create(123, “Brian”) Member.count should equal(before + 1) } }
  • 37. Play2 Support - Integrates with Play2 seamlessly - Read conf/application.conf - Add plugin to conf/play.plugins - FixturePlugin is also available - Great contribution by @tototoshi In detail: Wiki Page
  • 39. More info Examples devteam-app example QueryInterfaceSpec.scala Reference Wiki Pages Users Group ScalikeJDBC Users Group ScalikeJDBC Users Group Japan
  • 40. Enjoy! Just write SQL and get things done! git.io/scalikejdbc