slick @ confitura 2013

Post on 15-Jan-2015

89 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Slick @ Confitura 2013

TRANSCRIPT

Maciek Próchniak

Jak udawaćże nie mamybazy danych

Oracle view

DDD/OOP view

Larry

Uncle Bob

Repozytorium?

public interface Repository<T> {

void save(T object);

Collection<T> loadAll();

T load(Id id);

}

Repozytorium?

public interface Repository<Presentation> {

Collection<Presentation>

findByCategoryWithPopularityGreaterThan

(String name, double popularity, int limit);

...

}

Zapytania też mogą być

logiką!

Dashboard

Kolekcje - Java

Collection<Presentation> ret =

new HashSet<Presentation>();

for (Presentation presentation : presentations) {

if (presentation.getPopularity() > popularity) {

for (Author author : authors) {

if (author.getName().equals(name)

&& author.getId()

== presentation.getAuthorId() ) {

ret.add(presentation);

}

}

}

}

return ret;

Techniki

● JDBC

● i(my??)Batis

● Hibernate/JPA

● Hades

● SpringData

● jOOQ

● OneWEBSQL

Object/Relational Mapping is the Vietnam of Computer Science

- Ted Neward

ORM - OMG- Rich Hickey

SQL?

SELECT p.* from PRESENTATIONS p, AUTHORS a where p.authorId = a.id and p.popularity > :popularity and a.name = :name

SQL - kompozycja???

???

.Net

LINQ makes a query a first-class language construct in C# and Visual Basic.

var results = from c in Suppliers where c.size < 1 select new {c.name, c.address};

JVM?

map

tasks

:List[Task]

convert:Task->View

tasks.map(convert) : List[View]

flatMap

tasks:List[Task]

createSubtasks:Task->List[Task]

tasks.flatMap(createSubtasks):List[Task]

Kolekcje - Scala!

presentations.flatMap(presentation =>

authors

.filter(author =>

author.id == presentation.authorId)

.filter(author => author.name == name

&& presentation.popularity > popularity)

.map(_ => presentation)

)

Kolekcje - Scala!

for {

presentation <- presentations

author <- authors

if (author.id == presentation.authorId)

if (author.name == name &&

presentation.popularity > popularity)

} yield presentation

SQL - Scala

SELECT p.* from PRESENTATIONS p

for {p <- presentations

} yield p

Filtrowanie

SELECT p.* from PRESENTATIONS pWHERE p.rank > 5

for {p <- presentationsif p.rank > 5

} yield p

Projekcja

SELECT p.name from PRESENTATIONS pWHERE p.rank > 5

for {p <- presentationsif p.rank > 5

} yield p.name

Join

SELECT p.name,a.name from PRESENTATIONS p, AUTHORS a WHERE

p.authorId = a.id

for { p <- presentations a <- authors if

(p.authorId==a.id)} yield (p.name,a.name)

InnerJoin

SELECT p.name,a.name from PRESENTATIONS p, INNER JOIN AUTHORS a ON

p.authorId = a.id

for { p <- presentations a <-

authors(p.authorId)} yield (p.name,a.name)

Order by, limit

SELECT p.* from PRESENTATIONS porder by p.namelimit 10

(for {p <- presentations

} yield p).sortBy(_.name).take(10)

Deklaratywność w Scali

tasks

.map(_.name)

.filter(_.priority > 4)

.take(3)

● Statyczne typowanie

● Deklaratywność

● Predykaty = wyrażenia Scali

● Standardowe API - (flat)Map

Logika DAO DB

findByNameOrderByTypefindByTypeGroupByCategory

...

Logika DAO DB

query

???

Scala

Language

Integrated

Connectivity

Kit

Play!

Akka

Slick

Scala

Typesafe

Slick

● Obsługa różnych baz

● Łatwa konfiguracja

● DML

● Ochrona przed SQL injection

● bla

● bla

● bla

zapytania ~

operacje na kolekcjachScali

SLICK - architektura

AST

H2MySQL

Lifted

Lifted - predykaty

for {

speaker <- Query(Speakers)

if (speaker.name startsWith "Maciek")

} yield (speaker.twitter)

Lifted - metadane

object Speakers extends Table[Speaker]("speakers") {

def id = column[Long]("id")

def name = column[String]("name")

def twitter = column[TwitterId]("twitterId")

def * = id ~ name ~ twitter <> (

Speaker.apply _, Speaker.unapply _)

}

Lifted - predykaty

for {

speaker <- Query(Speakers)

if (speaker.name startsWith "Maciek")

} yield (speaker.twitter)

abstract class Query[+E, U] {

def flatMap[F, T](f: E => Query[F, T]): Query[F, T] = ...

def map[F, G, T](f: E => F)

(implicit shape: Shape[F, T, G]): Query[G, T] = ...

def filter[T](f: E => T)

(implicit wt: CanBeQueryCondition[T]): Query[E, U]

}

trait UnitInvoker[+R] extends Invoker[Unit, R] {

final def list()(implicit session: JdbcBackend#Session): List[R]

final def first()(implicit session: JdbcBackend#Session) : R

final def foreach(f: R => Unit, maxRows: Int)

(implicit session: JdbcBackend#Session): Unit

....

}

Lifted - predykaty

for {

speaker <- Query(Speakers)

if (speaker.name startsWith "Mac")

} yield (speaker.twitter)

====!=

notNull

Lifted - predykaty

for {

speaker <- Query(Speakers)

if (speaker.name startsWith "Mac")

} yield (speaker.twitter)

Rep[String]

Rep[TwitterId]

Rep[String]

Lifted - Join

for {

(s,p) <- Query(Speakers)

innerJoin Presentations

on (_.id === _.authorId)

} yield (s.twitter,p.abstr)

Lifted - własne typy

case class TwitterId(id:String) extends AnyVal

implicit val twitterId = MappedJdbcType.base[TwitterId,String]

(_.id,TwitterId.apply)

object Speakers extends Table[Speaker]("speakers") {

def twitter = column[TwitterId]("twitterId")

}

Lifted - kompozycja

def filter(pred

:Presentations=>Column[Boolean]) = {

for {

p <- Query(Presentations)

if (pred(p))

} yield (p.id)

}

Lifted - kompozycja

for {

presentation <- Query(Presentations)

author <- presentation.author

if author.name startsWith "Mac"

} yield presentation.title

Lifted - kompozycja

object Presentations

extends Table[Presentation] {

...

def author = foreignKey("author_fk",

authorId, Speakers)(_.id)

}

Lifted - podsumowanie

Czego brakuje lifted?

for {

speaker <- Query(Speakers)

if (speaker.name === "Mac")

} yield (speaker.twitter)

WIP - direct

Makra

● C - syntaktyczne

● Lisp - higieniczne

● Scala 2.10 - typowane

def filter(filter:T => Boolean)

: Queryable[T] =

macro QueryableMacros.filter[T]

def filter[T:c.WeakTypeTag]

(c: scala.reflect.macros.Context)

(projection: c.Expr[T => Boolean]) : c.Expr

[scala.slick.direct.Queryable[T]] = ...

Makro - przykład

.filter(s => s.name == "Henry")

("filter", Supplier, Function( List("s"), Apply( Select("s", "name"), "==",

List(Literal(Constant("Henry"))))))

("filter", Supplier, Function( List("s"), Apply( Select("s", "name"), "==",

List(Literal(Constant("Henry"))))))

Slick Query AST

SLICK - architektura

AST

H2MySQL

Lifted Direct

Direct - metadane

@table("presentation")

case class Presentation(@column("id") id:Long,

@column("authorId") authorId:Long,

@column("title") title:String,

@column("abstract")abstr:String)

Direct - przykład

val query = for {

speaker <- Queryable[Speaker]

if speaker.name == "Kuba Nabrdalik"

} yield speaker.bio

Direct - przykładval backend = new SlickBackend(profile,

AnnotationMapper)

def list[H](query:BaseQueryable[H])

: Iterable[H]

= backend.result(query, session)

dao.list(query) : List[Speaker]

Direct - typesafety :|

for {

presentation <- Queryable[Presentation]

if (presentation.title.contains("scala"))

} yield (presentation.id)

Direct - kompozycja??

def filter(pred:Presentation=>Boolean) = {

for {

p <- Queryable[Presentation]

if (pred(p))

} yield (presentation.id)

}

Slick - architektura

AST

H2MySQL

Lifted Direct

OrientDB

Slick OrientDB

@table("presentation")

case class Presentation(@column("id") id:Long,

@column("title") title:String,

@column("comments") comments:List[Comment])

case class Comment(@column("number") author:String,

@column("rate") rate:Integer,

@column("content") content:String)

Slick OrientDB

for {

presentation <- Queryable[Presentation]

if (presentation.comments

.filter(_.ratio > 5).size > 0)

} yield (presentation.title)

SLICK - architektura

AST

H2MySQL

Lifted Direct

OrientDBMemory

SLICK - architektura

AST

H2MySQL

Lifted

18 faz kompilacji...

OrientDBMemory

Direct

there is no valid translation of arbitrary monadic Query expressions to SQL (whose semantics are stuck half-way between applicative functors and monads)

- Stefan Zeiger

czy to się opłaca?● Deklaratywne zapytania

● Znane API

● Brak magii

● ... oprócz odrobiny makr

● Skomplikowane :(

Takk/Tänan/Dzięki

* we're hiring :)

top related