2013_scaladays

download 2013_scaladays

of 60

Transcript of 2013_scaladays

  • 7/21/2019 2013_scaladays

    1/60

    Slick vs ORMJan Christopher Vogt, EPFL

    Stefan Zeiger, Typesafe

  • 7/21/2019 2013_scaladays

    2/60

    Object-Orientation + Relational

  • 7/21/2019 2013_scaladays

    3/60

    Functional + Relational

  • 7/21/2019 2013_scaladays

    4/60

    Slick is a Functional-Relational Mapper

    embraces relational (not hidden)

    natural fit (no impedance mismatch) stateless (not stateful)

    Slick is to ORM what Scala is to Java

  • 7/21/2019 2013_scaladays

    5/60

    8 Reasons for using Slick

  • 7/21/2019 2013_scaladays

    6/60

    Sample App Data Model

    !"#$%"

    !"# %&'(

    )*!+,# -&./0,

    1+2.!3!4&'# -15,

  • 7/21/2019 2013_scaladays

    7/60

    1Scala collection-like

    API

  • 7/21/2019 2013_scaladays

    8/60

    Scala collection-like API

    !"#% & '( )*+,-*./

    ,!&12#,-* 3 455515

    6 7,*8&&19-:;,.,

  • 7/21/2019 2013_scaladays

    9/60

    2

    Minimal configuration

  • 7/21/2019 2013_scaladays

    10/60

    Configuration

    Do mappings in Scala

    No XML, no "magic" behind the scenes

    Connect to a JDBC URL or DataSource

    Use an external connection pool

    Wrap raw JDBC connections for use with DI

    containers that handle the transactionmanagement

  • 7/21/2019 2013_scaladays

    11/60

    Connect

    !"#$%&.-9891.8,-A1,+*#1BC)#,+*#1.,@28*1?

    ()*&D E )9

  • 7/21/2019 2013_scaladays

    12/60

    3Loosely-coupled, flexible

    mapping

  • 7/21/2019 2013_scaladays

    13/60

    Keep Your Data Model Clean

    caseclassDevice(id: Long,

    price: Double,

    acquisition: Date)

    classDevices extendsTable[Device](DEVICE ) {

    defid = column[Long](ID , O.PrimaryKey)

    defprice = column[String](PRICE )

    defacquisition = column[Date](ACQUISITION )

    def* = id ~ price ~ acquisition

    (Device.apply _, Device.unapply _)

    }

    valDevices = newDevices

  • 7/21/2019 2013_scaladays

    14/60

    Keep Your Data Model Clean

    classDevices extendsTable[(Long, String, Date)](DEVICE ) {

    defid = column[Long](ID , O.PrimaryKey)

    defprice = column[String](PRICE )

    defacquisition = column[Date](ACQUISITION )

    def* = id ~ price ~ acquisition

    }

    valDevices = newDevices

    666&* &7!5 !5

  • 7/21/2019 2013_scaladays

    15/60

    Keep Your Data Model Clean

    8/.5 9,,) !",'45: ,;)0!+!5

    caseclassDevice(id: Long,

    price: Double,

    acquisition: Date)

  • 7/21/2019 2013_scaladays

    16/60

    Custom Column Types

    caseclassDevice(id: DeviceId, )

    classDeviceId(valid: Long) extendsAnyVal

    implicitvaldeviceIdType= MappedTypeMapper.base

    [DeviceId, Long](_.id, newDeviceId(_))

    classDevices extendsTable[Device](DEVICE ) {

    defid = column[DeviceId](ID , O.PrimaryKey)

    }

  • 7/21/2019 2013_scaladays

    17/60

    Custom Functions

    defdayOfWeek(c: Column[Date]) =

    SimpleFunction[Int]("DAY_OF_WEEK").apply(Seq(c))

    valdows= Query(Devices).map { d =>

    (d.id, dayOfWeek(d.acquisition)) }.run

  • 7/21/2019 2013_scaladays

    18/60

    classDevices extendsTable[Device](DEVICE ) {

    defid = column[Long](ID , O.PrimaryKey)

    defprice = column[String](PRICE )

    defacquisition = column[Date](ACQUISITION )

    def* = id ~ price ~ acquisition

    (Device.apply _, Device.unapply _)

    }

    valDevices = newDevices

    Work With Any DB Schema

    You define the schema:

    3, 1': ?.'+4&'

  • 7/21/2019 2013_scaladays

    19/60

    4Explicit control over

    execution and transfer

  • 7/21/2019 2013_scaladays

    20/60

    Execution is always explicit

    ()*:;*#7 E ,$%Q

    & '( )*+,-*.

    !,&12#,-* 3 455515S -!.*/&19-:;,.,

  • 7/21/2019 2013_scaladays

    21/60

    Example Data Model

    '$("

    !"# %&'(

    '17,# @5*!'(

    !"#$%"

    !"# %&'(

    )*!+,# -&./0,

    1+2.!3!4&'# -15,

    3!5,A"# %&'(

    )*

  • 7/21/2019 2013_scaladays

    22/60

    Transferred data

    ORM()*&*+,-* E )*+,-*1 5-6/%4CUH6 7 9.(!+.

    ()*.,

  • 7/21/2019 2013_scaladays

    23/60

    5Predictable SQL

    structure

  • 7/21/2019 2013_scaladays

    24/60

    Predictable SQL structure

    >;*#7%)*+,-*.6

    1!,8

  • 7/21/2019 2013_scaladays

    25/60

    6

    Plain SQL support

  • 7/21/2019 2013_scaladays

    26/60

    Plain SQL support

    ()*2#,-* E 455515

    +98 *[2*=.,+*)*+,-*.K H,.

  • 7/21/2019 2013_scaladays

    27/60

    7

    Type Safety

    o

  • 7/21/2019 2013_scaladays

    28/60

    Enforce schema consistency

    Generate DDL from table objects

    Slick 2.0: Generate table objects and mapped

    classes from database

  • 7/21/2019 2013_scaladays

    29/60

    Compile-Time Safety

    Spelling mistake in column name?

    Wrong column type?

    Mapped to the wrong class?

    ,%-2-% ,"", $( -22>

  • 7/21/2019 2013_scaladays

    30/60

    Error messages can destroy the illusion

    Compile-Time Safety

  • 7/21/2019 2013_scaladays

    31/60

    (before we get to #8)

    Relationship Queries

  • 7/21/2019 2013_scaladays

    32/60

    Relationships

    ORM

    &*+,-*1N*

  • 7/21/2019 2013_scaladays

    33/60

    Joins

    ()*.,

  • 7/21/2019 2013_scaladays

    34/60

    Auto joins (1-n)

    !"#*!+!& /.,9;

  • 7/21/2019 2013_scaladays

    35/60

    Join types

    .,

  • 7/21/2019 2013_scaladays

    36/60

    Example Data Model

    '$("

    !"# %&'(

    '17,# @5*!'(

    !"#$%"

    !"# %&'(

    )*!+,# -&./0,

    1+2.!3!4&'# -15,

    3!5,A"# %&'(

    )*

    ?0.1;("9

    A"# %&'(

    B17,# @5*!'(

    +&7)1':A"# A'5

    ) *

  • 7/21/2019 2013_scaladays

    37/60

    Auto joins (n-n)

    !"#*!+!& /.,9;

  • 7/21/2019 2013_scaladays

    38/60

    Complex Auto Joins (n-n, etc.)

    !"#*!+!& /.,9;

  • 7/21/2019 2013_scaladays

    39/60

    Modifying relationships

    query for what you want to modify

    insert / update that query

    ()*&*+,-* E >;*#,*.%)*+,-*.61D7Z&% 4CUH6

    ()*.,

  • 7/21/2019 2013_scaladays

    40/60

    What about Inheritance?

  • 7/21/2019 2013_scaladays

    41/60

    Example Data Model

    '$("

    !"# %&'(

    '17,# @5*!'(

    @","-9%7'$("

    !"# %&'(

    3!C,# @!C,

    A905;%B0*'$("

    !"# %&'(

    D&0.7,# A'5

  • 7/21/2019 2013_scaladays

    42/60

    Inheritance

    Relational does not support inheritance

    Use relationships instead, you wont loose

    (think has role instead of is a)

  • 7/21/2019 2013_scaladays

    43/60

    Example Data Model

    '$("

    !"# %&'(

    '17,# @5*!'(

    @","-9%7'$("

    !"# %&'(

    3!5,A"# %&'(

    3!C,# @!C,

    A905;%B0*'$("

    !"# %&'(

    3!5,A"# %&'(

    D&0.7,# A'5

    ) )

    **

  • 7/21/2019 2013_scaladays

    44/60

    Example Data Model

    ,@28,-,< &*! 9;

  • 7/21/2019 2013_scaladays

    45/60

    Joining all sub-classes

    a re-usable querythat joinsSites with ResearchSites and ProductionSites

    .,

  • 7/21/2019 2013_scaladays

    46/60

    You can do inheritance

    +*)33 P,

  • 7/21/2019 2013_scaladays

    47/60

    8composable /

    re-usable queries

  • 7/21/2019 2013_scaladays

    48/60

    Mental paradigm shi!

    The ORM Way: Executor APIs (DAOs)

    )*+,-*.)fX

    1,=g#,-*G9=N*% i5515M C55515 6

    K H,.;*#7_?M)*+,-*` 6

    1,=g#,-*G9=N*% i5515M C55515 6K >;*#7_?M)*+,-*`

    3&7, 35.E F!5= +*!5,*!1 2.,*!,3G /.5 @0!+9 ?&* ,D,*:5=!'( !'+0."!'( H&!'3G (*&.)I:

  • 7/21/2019 2013_scaladays

    49/60

    Write query libraries

  • 7/21/2019 2013_scaladays

    50/60

    Row functions

    +*)33P,

  • 7/21/2019 2013_scaladays

    51/60

    Row functions

    traitHasName{

    this:Table[_] =>

    defname = column( ... )

    ...

    defnameLike( pattern:Column[String] ) : Column[Boolean]

    = this.name.toLowerCase like pattern.toLowerCase

    }

    classSites extendsTable[Site] withHasName

    classComputers extendsTable[Computer] withHasName

  • 7/21/2019 2013_scaladays

    52/60

    Query functions

    /.,D7V9@*_\MT 'K T9D8*_\` A!&BB9.V9@*`

    % :K>;*#7_TM\`M 29

  • 7/21/2019 2013_scaladays

    53/60

    Refinements

    method extensions (implicit conversions)

    Option support using Slicks OptionMapper

  • 7/21/2019 2013_scaladays

    54/60

    Suggestedslick app architecture

  • 7/21/2019 2013_scaladays

    55/60

    NO"%;(09 PAM Q !PJ",? /:B17,J @5*!'( K # %!35L8M

    ",? /:A"J !"#%&'( K # @!5,

    R;"9= S$39-9=",? /:B17,J

    N.,*:L8MG

    O&0.7'L8M

    K # N.,*:L 8 M

    ",? /:A"J O&0.7'L8M K

    # N.,*:L 8 M

    8

    T-32" 034"%(,P13B17,Q

    ",? '17,%!9,J O&0.7'L8M K

    # O&0.7'L 8 M

    RG

    -,D!+,3G@!5,3

    8

    ?0*(9022"9!-(-3-," '",,$0*

    U$"V

    Suggested Slick app architecture

  • 7/21/2019 2013_scaladays

    56/60

    Outlook

  • 7/21/2019 2013_scaladays

    57/60

    Slick 2.0

    Coming Q3 / 2013

    Query scheduling

    Improved driver architecture

    BasicProfile >: RelationalProfile >: SqlProfile >:JdbcProfile

    Generate Slick code from database schemas

    Proper "type providers" need new Scala More to come

  • 7/21/2019 2013_scaladays

    58/60

    30!+965:),31?,6+&7S+D&(5

    S@5,?1'T,!(,*

    =U)#VV30!+965:),31?,6+&7V51093VWXYZ[3+101"1:3VWXYZ[3+101"1:36)"?

    =U)3#VV(!5=./6+&7V30!+9V)01:\30!+9V5*,,V3+101"1:3WXYZ

  • 7/21/2019 2013_scaladays

    59/60

    Extra slides

  • 7/21/2019 2013_scaladays

    60/60

    Join via foreign key