2013_scaladays
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