Persistens i Scala         JavaZone
X    Trond
Marius
Øvstetun           ©
Mesan
AS
Agenda•   Sette
fokus
på
persistens‐laget•   Det
finnes
mange
alternativer!•   En
liten
introduksjon                       ...
Agenda•   Sette
fokus
på
persistens‐laget•   Det
finnes
mange
alternativer!•   En
liten
introduksjon•   Tenke
seg
om
i
de
v...
Trond Marius Øvstetun•   Seniorkonsulent
og
    fagleder
i
Mesan•   Lidenskapelig
utvikler,
    arkitekt,
teamleder
++•   ...
Mesan            ...
når
standardsystemer
ikke
er
nok•   Systemutvikling
–
skreddersøm•   Løsningsfokus•   “Store”
systeme...
Mesan             ...
når
standardsystemer
ikke
er
nok•   Systemutvikling
–
skreddersøm•   Løsningsfokus•   “Store”
system...
Levetid  ©
Mesan
AS
Systemer i endring     V1   V2     V3    V4   V5   V6                DB               ©
Mesan
AS
Systemer i endring               Forretningsprosesser     V1   V2        V3     V4         V5   V6                  DB    ...
Systemer i endring               Forretningsprosesser    V1    V2    V3     V4      V5     V6   V7         T1    T2     T3...
Systemer i endring                         Forretningsprosesser              V1    V2    V3      V4     V5     V6   V7    ...
Systemer i endring                             Forretningsprosesser   V1        V2         V3        V4        V5    V6   ...
Java -> Scala            Teknologien
driver
ossHva
man
sitter
igjen
med
etter
introduksjonen...                    ©
Mesan...
•   De
fleste
som
prøver
Scala
har
bakgrunn
fra
Java•   Innarbeidede
rutiner,
forventninger,
perferanser,
    tankesett,
ra...
Person             firstname : String             lastname : String             birthDate : Date             gender : Gende...
public class Person {    private String firstname;    private String lastname;    private Date birthDate;    private Gende...
public class Person {    private String firstname;    private String lastname;    private Date birthDate;    private Gende...
null? Nei takk•   Option[T]    •   Some
–
innhold    •   None                         ©
Mesan
AS
null? Nei takk•   Option[T]    •   Some
–
innhold   class Person(var firstname:String, var lastname:String,               ...
null? Nei takk      •   Option[T]          •   Some
–
innhold                   class Person(var firstname:String, var las...
null? Nei takk      •   Option[T]          •   Some
–
innhold                   class Person(var firstname:String, var las...
Statisk, men “dynamisk”•   Scala
er
utvidbart                                       "(d)*".r => Regex                     ...
Statisk, men “dynamisk”•   Scala
er
utvidbart                                       "(d)*".r => Regex                     ...
Avanserte strukturer        val persons = List(Person("Per"), Person("Pål"), Person("Espen"))        val (lucky, unlucky) ...
Avanserte strukturer                            val persons = List(Person("Per"), Person("Pål"), Person("Espen"))         ...
Avanserte strukturer                            val persons = List(Person("Per"), Person("Pål"), Person("Espen"))         ...
Avanserte strukturer                            val persons = List(Person("Per"), Person("Pål"), Person("Espen"))         ...
Objekter? Funksjoner?•   Høyereordens
funksjoner
–
gjenbruk
og
abstraksjon•   Immutable
datastrukturer
–
sikkerhet•   case...
The selling point “Slapp
av
–
Alle
java‐biblioteker
og
APIer           fungerer
med
Scala!”                  ©
Mesan
AS
The selling point “Slapp
av
–
Alle
java‐biblioteker
og
APIer           fungerer
med
Scala!”          Men
er
det
så
enkelt?...
En typisk applikasjon        Brukergrensesnitt         Visningslogikk        Forretningslogikk          Data aksess       ...
En typisk applikasjon                 Brukergrensesnitt                  Visningslogikk     Domene      Forretningslogikk ...
En typisk java-               HTML / Javascript                 Spring MVC                 @Controller  @Entity   JPA     ...
En enkel datamodell    «enumeration»                           Artist      Genre                                          ...
JPA   «enumeration»                          Artist     Genre                                               Album         ...
Vi mapper en sang   «enumeration»                          Artist     Genre                                               ...
Vi mapper en sang                                                   class Song(var id:Int, var name:String, var duration:I...
Vi mapper en sang                                                   class Song(var id:Int, var name:String, var duration:I...
Vi mapper en sang                                                   class Song(var id:Int, var name:String, var duration:I...
Vi mapper en sang                                                   class Song(var id:Int, var name:String, var duration:I...
Et album                                                                         @Entity                                  ...
Et album                                                                         @Entity                                  ...
Artister                                                                         @Entity                                  ...
@Entity                                                                             Artisterclass Artist {    @Id    @Gene...
@Entity                                                                                  Artisterclass Artist {           ...
@Entity                                                                                  Artisterclass Artist {           ...
@Entity                                                                                             Artisterclass Artist {...
Artister med personer                                                                         @Entity                     ...
Artister med personer@Entityclass Artist {                                                                                ...
Artister med personer@Entityclass Artist {                                                                                ...
Artister med personer@Entityclass Artist {                                                                                ...
Opplevelsen så langt•   java
collections•   ikkeno
Option‐støtte•   Plagsom
Enum•   Mer
klønete
bruk
av
annoteringer      ...
Opplevelsen så langt•   java
collections•   ikkeno
Option‐støtte•   Plagsom
Enum•   Mer
klønete
bruk
av
annoteringer•   Fø...
Opplevelsen så langt•   java
collections•   ikkeno
Option‐støtte•   Plagsom
Enum•   Mer
klønete
bruk
av
annoteringer•   Fø...
Insertdef createArtist(em:EntityManager) {  val a = new Artist  a.name = "Pink Floyd"  a.biography = "bla bla bla"  a.foun...
Insert                                               def createAlbum(em:EntityManager) {def createArtist(em:EntityManager)...
Selectsdef findArtist(em:EntityManager) = {  val tool:Artist = em.find(classOf[Artist], 1001)  tool}def findArtistByName(e...
Update                                                 def updateRating(em:EntityManager) {                               ...
Hva kan vi forbedre?   «enumeration»                          Artist     Genre                                            ...
Hva kan vi forbedre?                                                                          trait WithID {              ...
Hva kan vi forbedre?                                                                          trait WithID {              ...
ScalaEntityManager•   Wrapper
rundt
EntityManager•   I
samme
stil
som
RichInt,
StringOps
etc                           ©
M...
ScalaEntityManager         •   Wrapper
rundt
EntityManager         •   I
samme
stil
som
RichInt,
StringOps
etcpublic inter...
Deler av veien, men...         ©
Mesan
AS
Deler av veien, men...•   Føler
at
noe
ikke
stemmer
her                          ©
Mesan
AS
Deler av veien, men...•   Føler
at
noe
ikke
stemmer
her•   Får
ikke
utnyttet
mulighetene
i
språket                        ...
Deler av veien, men...•   Føler
at
noe
ikke
stemmer
her•   Får
ikke
utnyttet
mulighetene
i
språket•   Hvorfor
bruke
Scala
...
Uklarheter•   Tung
mental
modell                                                                                 Id   Name...
•   Trainwrecks
/
lasting
av
“hele”
basen•   Traversering
av
objektmodell    



vs                                       ...
Alternativer    ©
Mesan
AS
JDBC                                                                                Rykk
tilbake
til
start!               ...
JDBC•   Direkte
integrasjon
mot
databasen•   Ingen
avhengigheter,
fundamentalt
i
Java
SE•   Grunnlaget
for
alle
abstraksjo...
Modell                    •          Frie
tøyler!                   import Genre._                   class Artist(val name...
Insertdef con: Connectiondef insertArtist {  val in = "INSERT INTO ARTISTS(name, biography, founded, maingenre) VALUES (?,...
Insertdef con: Connectiondef insertArtist {  val in = "INSERT INTO ARTISTS(name, biography, founded, maingenre) VALUES (?,...
Updatedef updateArtist {  val ps = con.prepareStatement("UPDATE ARTISTS SET name = ? WHERE id = ?")  ps.setString(1, "upda...
Updatedef updateArtist {  val ps = con.prepareStatement("UPDATE ARTISTS SET name = ? WHERE id = ?")  ps.setString(1, "upda...
Finn én (eller ingen)def findArtist : Option[Artist] = {  st = conn.prepareStatement(    "SELECT id, name, biography, foun...
Finn mangedef findAllArtists : List[Artist] = {  var res = List[Artist]()    val st = con.prepareStatement(      "SELECT i...
Finn album med sangerdef findAlbum() = {  val q =    "    SELECT a.id, a.name, a.release, a.rating, s.name, s.duration, s....
Oppsiden•   Full
kontroll
på
all
SQL    •   Hvilken
SQL
som
kjøres    •   Når
den
kjøres•   Full
valgfrihet
i
modellering
...
What´s the catch?       ©
Mesan
AS
What´s the catch?•   boilerplate                  ©
Mesan
AS
What´s the catch?                                                    var conn : Connection = null•   boilerplate          ...
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Persistens i scala
Upcoming SlideShare
Loading in...5
×

Persistens i scala

393

Published on

My presentation "Persitens i Scala" given at JavaZone 2011.

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
393
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
7
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • av og til er data bare data uten oppførsel\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • enum Genre\nDuration - int-wrapper\n\n
  • enum Genre\nDuration - int-wrapper\n\n
  • enum Genre\nDuration - int-wrapper\n\n
  • enum Genre\nDuration - int-wrapper\n\n
  • enum Genre\nDuration - int-wrapper\n\n
  • enum Genre\nDuration - int-wrapper\n\n
  • enum Genre\nDuration - int-wrapper\n\n
  • enum Genre\nDuration - int-wrapper\n\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Genre - enum mappes automatisk :)\ntabeller defineres som verdier/objekter/singletons i schema\nkunne brukt case-klasser\nKeyedEntity[Int] - bare convenience, ikke et krav, men om man bruker genererte nøkler så får man ekstra\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Persistens i scala

    1. 1. Persistens i Scala JavaZone
X Trond
Marius
Øvstetun ©
Mesan
AS
    2. 2. Agenda• Sette
fokus
på
persistens‐laget• Det
finnes
mange
alternativer!• En
liten
introduksjon ©
Mesan
AS
    3. 3. Agenda• Sette
fokus
på
persistens‐laget• Det
finnes
mange
alternativer!• En
liten
introduksjon• Tenke
seg
om
i
de
valgene
man
gjør ©
Mesan
AS
    4. 4. Trond Marius Øvstetun• Seniorkonsulent
og
 fagleder
i
Mesan• Lidenskapelig
utvikler,
 arkitekt,
teamleder
++• Java,
Scala,
HTML/js• Alltid
på
jakt
etter
bedre,
 enklere
måter ©
Mesan
AS
    5. 5. Mesan ...
når
standardsystemer
ikke
er
nok• Systemutvikling
–
skreddersøm• Løsningsfokus• “Store”
systemer• Transaksjonssystemer ©
Mesan
AS
    6. 6. Mesan ...
når
standardsystemer
ikke
er
nok• Systemutvikling
–
skreddersøm• Løsningsfokus• “Store”
systemer• Transaksjonssystemer• Lang
levetid
–
langsiktighet ©
Mesan
AS
    7. 7. Levetid ©
Mesan
AS
    8. 8. Systemer i endring V1 V2 V3 V4 V5 V6 DB ©
Mesan
AS
    9. 9. Systemer i endring Forretningsprosesser V1 V2 V3 V4 V5 V6 DB ©
Mesan
AS
    10. 10. Systemer i endring Forretningsprosesser V1 V2 V3 V4 V5 V6 V7 T1 T2 T3 T4 T5 T6 DB ©
Mesan
AS
    11. 11. Systemer i endring Forretningsprosesser V1 V2 V3 V4 V5 V6 V7 T1 T2 T3 T4 T5 T6 Teknologi DB ©
Mesan
AS
    12. 12. Systemer i endring Forretningsprosesser V1 V2 V3 V4 V5 V6 V7 V8 V9 F1 F2 F3 F4 F5 F6 F7 T1 T2 T3 T4 T5 T6 DB ©
Mesan
AS
    13. 13. Java -> Scala Teknologien
driver
ossHva
man
sitter
igjen
med
etter
introduksjonen... ©
Mesan
AS
    14. 14. • De
fleste
som
prøver
Scala
har
bakgrunn
fra
Java• Innarbeidede
rutiner,
forventninger,
perferanser,
 tankesett,
rammeverk
etc • Objektorientert? • Transaksjonsskript? ©
Mesan
AS
    15. 15. Person firstname : String lastname : String birthDate : Date gender : Gender©
Mesan
AS
    16. 16. public class Person { private String firstname; private String lastname; private Date birthDate; private Gender gender; public Person(String firstname, String lastname, Gender gender, Date birthDate) { this.firstname = firstname; this.lastname = lastname; this.gender = gender; this.birthDate = birthDate; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public Date getBirthDate() { Person return birthDate; } firstname : String public void setBirthDate(Date birthDate) { lastname : String this.birthDate = birthDate; } birthDate : Date gender : Gender public Gender getGender() { return gender; } public void setGender(Gender gender) { this.gender = gender; }} ©
Mesan
AS
    17. 17. public class Person { private String firstname; private String lastname; private Date birthDate; private Gender gender; public Person(String firstname, String lastname, Gender gender, Date birthDate) { this.firstname = firstname; this.lastname = lastname; this.gender = gender; this.birthDate = birthDate; } public String getFirstname() { return firstname; } class Person(var firstname:String, var lastname:String, public void setFirstname(String firstname) { this.firstname = firstname; var gender:Gender, var birthdate:Date) } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public Date getBirthDate() { Person return birthDate; } firstname : String public void setBirthDate(Date birthDate) { lastname : String this.birthDate = birthDate; } birthDate : Date gender : Gender public Gender getGender() { return gender; } public void setGender(Gender gender) { this.gender = gender; }} ©
Mesan
AS
    18. 18. null? Nei takk• Option[T] • Some
–
innhold • None ©
Mesan
AS
    19. 19. null? Nei takk• Option[T] • Some
–
innhold class Person(var firstname:String, var lastname:String, var gender:Gender, var birthdate:Option[Date] = None) • None ©
Mesan
AS
    20. 20. null? Nei takk • Option[T] • Some
–
innhold class Person(var firstname:String, var lastname:String, var gender:Gender, var birthdate:Option[Date] = None) • Noneinterface PersonRepository { /** * @return A person if found, <code>null</code> otherwise. */ Person findById(int id);}PersonRepository repo;Person person = repo.findById(1);if (person != null) { person.updateThySelf();}PersonRepository repo;Person person = repo.findById(1);if (person != null) { return person.firstname + " " + person.lastname;} else { return "John Doe"} ©
Mesan
AS
    21. 21. null? Nei takk • Option[T] • Some
–
innhold class Person(var firstname:String, var lastname:String, var gender:Gender, var birthdate:Option[Date] = None) • Noneinterface PersonRepository { /** * @return A person if found, <code>null</code> otherwise. trait PersonRepository { */ def findById(id:Int) : Option[Person] Person findById(int id); }}PersonRepository repo;Person person = repo.findById(1); val repo:PersonRepositoryif (person != null) { val p = repo.findById(1) person.updateThySelf(); for (person <- p) {} person.updateThySelf() }PersonRepository repo;Person person = repo.findById(1); val repo:PersonRepositoryif (person != null) { val p = repo.findById(1) return person.firstname + " " + person.lastname; p.map(person =>} else { person.firstname + " " + person.lastname) return "John Doe" .getOrElse("John Doe")} ©
Mesan
AS
    22. 22. Statisk, men “dynamisk”• Scala
er
utvidbart "(d)*".r => Regex "123".toInt => Int(123) • “Pimp
My
Library” "hello %s".format("world") => String("hello world") "hello".capitalize => "Hello"• Utvider
vanlige
klasser
 med
metoder 1 to 10 => Range(1, 10) 1 until 10 => Range(1, 9)• Mye
i
vanlige
bibliotek ©
Mesan
AS
    23. 23. Statisk, men “dynamisk”• Scala
er
utvidbart "(d)*".r => Regex "123".toInt => Int(123) • “Pimp
My
Library” "hello %s".format("world") => String("hello world") "hello".capitalize => "Hello"• Utvider
vanlige
klasser
 med
metoder 1 to 10 => Range(1, 10) 1 until 10 => Range(1, 9)• Mye
i
vanlige
bibliotek implicit def strToFoo(in:String) : Foo = new Foo(in) class Foo(f:String) { def bar = f + "bar"• Roll
your
own! } "foo".bar => "foobar" ©
Mesan
AS
    24. 24. Avanserte strukturer val persons = List(Person("Per"), Person("Pål"), Person("Espen")) val (lucky, unlucky) = persons.partition(_.name == "Espen") val fullnames = persons.map(_.name + " Askeladd") for (n <- fullnames) { println(n) } ©
Mesan
AS
    25. 25. Avanserte strukturer val persons = List(Person("Per"), Person("Pål"), Person("Espen")) val (lucky, unlucky) = persons.partition(_.name == "Espen")• Scala
collections
er
 val fullnames = persons.map(_.name + " Askeladd") kraftig
kost for (n <- fullnames) { println(n) } ©
Mesan
AS
    26. 26. Avanserte strukturer val persons = List(Person("Per"), Person("Pål"), Person("Espen")) val (lucky, unlucky) = persons.partition(_.name == "Espen")• Scala
collections
er
 val fullnames = persons.map(_.name + " Askeladd") kraftig
kost for (n <- fullnames) { println(n) }• Tuppler val navn = ("Trond Marius", "Øvstetun") ©
Mesan
AS
    27. 27. Avanserte strukturer val persons = List(Person("Per"), Person("Pål"), Person("Espen")) val (lucky, unlucky) = persons.partition(_.name == "Espen")• Scala
collections
er
 val fullnames = persons.map(_.name + " Askeladd") kraftig
kost for (n <- fullnames) { println(n) }• Tuppler val navn = ("Trond Marius", "Øvstetun") case class MyVal(s:String) def myMatch(n:Any) : String = { n match {• Pattern
matching
 case 1 => "ONE" case n:Int if n < 10 => "low..." ruler! case n:Int if n > 10 => "high!" case p:Person => "a person: " + p.firstname case MyVal(s) => s } } ©
Mesan
AS
    28. 28. Objekter? Funksjoner?• Høyereordens
funksjoner
–
gjenbruk
og
abstraksjon• Immutable
datastrukturer
–
sikkerhet• case
class
‐>
copy(...)• Minimalisere
API
og
API‐bruk,
spesialisere
tjenester• Klar
og
konsistent
kode ©
Mesan
AS
    29. 29. The selling point “Slapp
av
–
Alle
java‐biblioteker
og
APIer fungerer
med
Scala!” ©
Mesan
AS
    30. 30. The selling point “Slapp
av
–
Alle
java‐biblioteker
og
APIer fungerer
med
Scala!” Men
er
det
så
enkelt? ©
Mesan
AS
    31. 31. En typisk applikasjon Brukergrensesnitt Visningslogikk Forretningslogikk Data aksess DB ©
Mesan
AS
    32. 32. En typisk applikasjon Brukergrensesnitt Visningslogikk Domene Forretningslogikk Data aksess DB ©
Mesan
AS
    33. 33. En typisk java- HTML / Javascript Spring MVC @Controller @Entity JPA Spring @Service Spring / JPA @Repository DB ©
Mesan
AS
    34. 34. En enkel datamodell «enumeration» Artist Genre Album name : String Rock 1 biography : Text name : String Pop * Classic mainGenre : Genre release : Date Blues founded : Date rating : Option[Int] Rap split : Option[Date] 1 HipHop Alternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    35. 35. JPA «enumeration» Artist Genre Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    36. 36. Vi mapper en sang «enumeration» Artist Genre Song Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * name : String duration : Int * * Song trackNumber : Int name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    37. 37. Vi mapper en sang class Song(var id:Int, var name:String, var duration:Int, var tracknumber:Int) «enumeration» Artist Genre Song Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * name : String duration : Int * * Song trackNumber : Int name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    38. 38. Vi mapper en sang class Song(var id:Int, var name:String, var duration:Int, var tracknumber:Int) @Entity class Song(var id:Int, var name:String, var duration:Int, var tracknumber:Int) «enumeration» Artist Genre Song Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * name : String duration : Int * * Song trackNumber : Int name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    39. 39. Vi mapper en sang class Song(var id:Int, var name:String, var duration:Int, var tracknumber:Int) @Entity class Song(var id:Int, var name:String, var duration:Int, var tracknumber:Int) @Entity class Song(@Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id:Int, var name:String, var duration:Int, var tracknumber:Int) «enumeration» Artist Genre Song Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * name : String duration : Int * * Song trackNumber : Int name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    40. 40. Vi mapper en sang class Song(var id:Int, var name:String, var duration:Int, var tracknumber:Int) @Entity class Song(var id:Int, var name:String, var duration:Int, var tracknumber:Int) @Entity class Song(@Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id:Int, var name:String, var duration:Int, var tracknumber:Int) @Entity class Song { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ var name : String = _ var duration : Int = _ var tracknumber : Int = _ } «enumeration» Artist Genre Song Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * name : String duration : Int * * Song trackNumber : Int name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    41. 41. Et album @Entity class Album { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ var name : String = _ @Temporal(value = TemporalType.DATE) var release : Date = _ var rating : Int = _ } Album name : String release : Date rating : Option[Int] 1 * «enumeration» Artist Genre Song Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * name : String duration : Int * * Song trackNumber : Int name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    42. 42. Et album @Entity class Album { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ var name : String = _ @Temporal(value = TemporalType.DATE) var release : Date = _ var rating : Int = _ } Album – med sanger name : String release : Date rating : Option[Int] 1 import java.util.{List => jList} @OneToMany(orphanRemoval = true) @JoinColumn(name = "album_id") @OrderBy("tracknumber") * «enumeration» Genre Artist var songs : jList[Song] = _ Song Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * name : String duration : Int * * Song trackNumber : Int name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    43. 43. Artister @Entity class Artist { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ var name : String = _ var biography : String = _ @Temporal(value = TemporalType.DATE) var founded : Date = _ } «enumeration» Artist Genre Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    44. 44. @Entity Artisterclass Artist { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ var name : String = _ var biography : String = _ @Temporal(value = TemporalType.DATE) var founded : Date = _} @OneToMany(orphanRemoval = true, cascade = Array(CascadeType.ALL)) @JoinColumn(name = "artist_id") var albums : jList[Album] = _ «enumeration» Artist Genre Album name : String Rock 1 biography : Text name : String Pop * Classic mainGenre : Genre release : Date Blues founded : Date rating : Option[Int] Rap split : Option[Date] 1 HipHop Alternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    45. 45. @Entity Artisterclass Artist { «enumeration» @Id Genre @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ Rock var name : String = _ Pop var biography : String = _ Classic @Temporal(value = TemporalType.DATE) Blues var founded : Date = _ Rap} HipHop Alternative @OneToMany(orphanRemoval = true, cascade = Array(CascadeType.ALL)) @JoinColumn(name = "artist_id") var albums : jList[Album] = _ object Genre extends Enumeration { type Genre = Value val Rock = Value(1) val Pop = Value(2) val Classic = Value(3) val Blues = Value(4) val Rap = Value(5) val HipHop = Value(6) val Alternative = Value(7) } «enumeration» Artist Genre Album name : String Rock 1 biography : Text name : String Pop * Classic mainGenre : Genre release : Date Blues founded : Date rating : Option[Int] Rap split : Option[Date] 1 HipHop Alternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    46. 46. @Entity Artisterclass Artist { «enumeration» @Id Genre @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ Rock var name : String = _ Pop var biography : String = _ Classic @Temporal(value = TemporalType.DATE) Blues var founded : Date = _ Rap} HipHop Alternative @OneToMany(orphanRemoval = true, cascade = Array(CascadeType.ALL)) @JoinColumn(name = "artist_id") var albums : jList[Album] = _ object Genre extends Enumeration { type Genre = Value @Enumerated var maingenre : Genre = Genre.Rock val Rock = Value(1) val Pop = Value(2) val Classic = Value(3) val Blues = Value(4) val Rap = Value(5) val HipHop = Value(6) val Alternative = Value(7) } «enumeration» Artist Genre Album name : String Rock 1 biography : Text name : String Pop * Classic mainGenre : Genre release : Date Blues founded : Date rating : Option[Int] Rap split : Option[Date] 1 HipHop Alternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    47. 47. @Entity Artisterclass Artist { «enumeration» @Id Genre @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ Rock var name : String = _ Pop var biography : String = _ Classic @Temporal(value = TemporalType.DATE) Blues var founded : Date = _ Rap} HipHop Alternative @OneToMany(orphanRemoval = true, cascade = Array(CascadeType.ALL)) @JoinColumn(name = "artist_id") var albums : jList[Album] = _ object Genre extends Enumeration { @Converter(name = "GenreConverter", type Genre = Value converterClass = classOf[GenreConverter]) @Convert("GenreConverter") val Rock = Value(1) var maingenre : Genre = Genre.Rock val Pop = Value(2) val Classic = Value(3) val Blues = Value(4) val Rap = Value(5) val HipHop = Value(6) val Alternative = Value(7) } «enumeration» Artist Genre Album name : String Rock 1 biography : Text name : String Pop * Classic mainGenre : Genre release : Date Blues founded : Date rating : Option[Int] Rap split : Option[Date] 1 HipHop Alternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    48. 48. Artister med personer @Entity class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ var firstname : String = _ var lastname : String = _ } «enumeration» Artist Genre Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    49. 49. Artister med personer@Entityclass Artist { @Entity @Id class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ var id : Int = _ var name : String = _ var firstname : String = _ var biography : String = _ var lastname : String = _ @Temporal(value = TemporalType.DATE) } var founded : Date = _} Artist Person name : String * biography : Text firstname : String * «enumeration» Genre Artist name : String Album mainGenre : Genre lastname : String Rock 1 Pop Classic biography : Text mainGenre : Genre founded : Date * name : String release : Date rating : Option[Int] founded : Date biography : Text Blues Rap HipHop Alternative split : Option[Date] * 1 split : Option[Date] * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    50. 50. Artister med personer@Entityclass Artist { @Entity @Id class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ var id : Int = _ var name : String = _ var firstname : String = _ var biography : String = _ var lastname : String = _ @Temporal(value = TemporalType.DATE) } var founded : Date = _} @ManyToMany @JoinTable(name = "person_artist", joinColumns = Array(new JoinColumn(name = "artist_id")), inverseJoinColumns = Array(new JoinColumn(name = "person_id"))) var persons : jList[Person] = _ Artist Person name : String * biography : Text firstname : String * «enumeration» Genre Artist name : String Album mainGenre : Genre lastname : String Rock 1 Pop Classic biography : Text mainGenre : Genre founded : Date * name : String release : Date rating : Option[Int] founded : Date biography : Text Blues Rap HipHop Alternative split : Option[Date] * 1 split : Option[Date] * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    51. 51. Artister med personer@Entityclass Artist { @Entity @Id class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ var id : Int = _ var name : String = _ var firstname : String = _ var biography : String = _ var lastname : String = _ @Temporal(value = TemporalType.DATE) } var founded : Date = _} @ManyToMany @JoinTable(name = "person_artist", @ManyToMany(mappedBy = "persons") joinColumns = Array(new JoinColumn(name = "artist_id")), inverseJoinColumns = Array(new JoinColumn(name = "person_id"))) var artists : jList[Artist] = _ var persons : jList[Person] = _ Artist Person name : String * biography : Text firstname : String * «enumeration» Genre Artist name : String Album mainGenre : Genre lastname : String Rock 1 Pop Classic biography : Text mainGenre : Genre founded : Date * name : String release : Date rating : Option[Int] founded : Date biography : Text Blues Rap HipHop Alternative split : Option[Date] * 1 split : Option[Date] * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    52. 52. Opplevelsen så langt• java
collections• ikkeno
Option‐støtte• Plagsom
Enum• Mer
klønete
bruk
av
annoteringer ©
Mesan
AS
    53. 53. Opplevelsen så langt• java
collections• ikkeno
Option‐støtte• Plagsom
Enum• Mer
klønete
bruk
av
annoteringer• Føles
ikke
veldig
“Scalash” ©
Mesan
AS
    54. 54. Opplevelsen så langt• java
collections• ikkeno
Option‐støtte• Plagsom
Enum• Mer
klønete
bruk
av
annoteringer• Føles
ikke
veldig
“Scalash”• Javel,
men
vi
prøver
videre
og
bruker
entitetene... ©
Mesan
AS
    55. 55. Insertdef createArtist(em:EntityManager) { val a = new Artist a.name = "Pink Floyd" a.biography = "bla bla bla" a.founded = "1965-01-20" a.maingenre = Genre.Alternative em.persist(a)} ©
Mesan
AS
    56. 56. Insert def createAlbum(em:EntityManager) {def createArtist(em:EntityManager) { val tool = em.find(classOf[Artist], 1001) val a = new Artist a.name = "Pink Floyd" val album = new Album a.biography = "bla bla bla" album.name = "New one" a.founded = "1965-01-20" album.release = new Date() a.maingenre = Genre.Alternative album.rating = 5 em.persist(a) tool.albums.add(album)} } ©
Mesan
AS
    57. 57. Selectsdef findArtist(em:EntityManager) = { val tool:Artist = em.find(classOf[Artist], 1001) tool}def findArtistByName(em:EntityManager) = { val q = em.createQuery("SELECT a FROM Artist a WHERE a.name = :name", classOf[Artist]) q.setParameter("name", "Tool") val artist = q.getSingleResult artist}def countArtists(em:EntityManager) = { val q = em.createQuery("SELECT COUNT(a) FROM Artist a", classOf[Long]) val artistCount = q.getSingleResult artistCount}def findArtists(em:EntityManager) = { val q = em.createQuery("SELECT a FROM Artist a WHERE size(a.albums) > 4", classOf[Artist]) q.getResultList} ©
Mesan
AS
    58. 58. Update def updateRating(em:EntityManager) { val tool = em.find(classOf[Artist], 1001)def updateArtist(em:EntityManager) { for (i <- 0 until tool.albums.size) { val tool = em.find(classOf[Artist], 1001) val album = tool.albums.get(0) tool.name = "Updated..." album.rating = 5} } } def updateRatingByQuery(em:EntityManager) { val q = em.createQuery(""" UPDATE Album a SET rating = 5 WHERE a.id in (SELECT album.id FROM Artist art JOIN art.albums album WHERE art.id = :id) """) q.setParameter("id", 1001) val up = q.executeUpdate() // up => 4 } ©
Mesan
AS
    59. 59. Hva kan vi forbedre? «enumeration» Artist Genre Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    60. 60. Hva kan vi forbedre? trait WithID { • Traits
FTW! @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ } @Entity class Song extends WithID { var name : String = _ var duration : Int = _ var tracknumber : Int = _ } «enumeration» Artist Genre Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    61. 61. Hva kan vi forbedre? trait WithID { • Traits
FTW! @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = _ } @Entity class Song extends WithID { var name : String = _ var duration : Int = _ var tracknumber : Int = _ } class Album extends WithID { var songs : jList[Song] = _ • Scala
Collections def duration : Int = { import scala.collection.JavaConversions._ songs.foldLeft(0)(_ + _.duration) } } «enumeration» Artist Genre Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    62. 62. ScalaEntityManager• Wrapper
rundt
EntityManager• I
samme
stil
som
RichInt,
StringOps
etc ©
Mesan
AS
    63. 63. ScalaEntityManager • Wrapper
rundt
EntityManager • I
samme
stil
som
RichInt,
StringOps
etcpublic interface EntityManager { public <T> T find(Class<T> entityClass, Object primaryKey); public Query createQuery(String qlString); trait ScalaEntityManager { public <T> TypedQuery<T> createQuery(String qlString, def find[A](clazz: Class[A], id: Any) : Option[A] Class<T> resultClass); def def createQuery[A](queryString: String) : ScalaQuery[A]} }public interface Query { class ScalaQuery[A] { public List getResultList(); def findAll : Seq[A] Object getSingleResult(); def getResultList() : Seq[A] Query setParameter(String name, Object value); def findOne : Option[A]} def setParams(params : Pair[String,Any]*)public interface TypedQuery<X> extends Query { } X getSingleResult(); java.util.List<X> getResultList();} ©
Mesan
AS
    64. 64. Deler av veien, men... ©
Mesan
AS
    65. 65. Deler av veien, men...• Føler
at
noe
ikke
stemmer
her ©
Mesan
AS
    66. 66. Deler av veien, men...• Føler
at
noe
ikke
stemmer
her• Får
ikke
utnyttet
mulighetene
i
språket ©
Mesan
AS
    67. 67. Deler av veien, men...• Føler
at
noe
ikke
stemmer
her• Får
ikke
utnyttet
mulighetene
i
språket• Hvorfor
bruke
Scala
i
det
hele
tatt? ©
Mesan
AS
    68. 68. Uklarheter• Tung
mental
modell Id Name Location • Object
Relational
Impedence
Mismatch 1 Mesan Oslo 2 NTNU Trondheim 3 NITH Oslo Company name : String 4 NFR Oslo location : String 5 Sintef Trondheim• Transaksjoner * Person firstname : String lastname : String Id 1 Firstname John Lastname Doe Company 1 2 Jane Doe 1 3 Peter Peterson 2 • Hva
endres?
Når
skrives
det
til
base? 4 Marky Mark 3 5 John Johnson 2• Database‐struktur
styrt
av
JPA?• Skjønner
man
datamodellen?
Eller
må
man
lese
JPA‐ koden
for
å
henge
med?• Velge
“eiende”
side
i
relasjoner ©
Mesan
AS
    69. 69. • Trainwrecks
/
lasting
av
“hele”
basen• Traversering
av
objektmodell 



vs Forretningsprosesser• Uthenting
av
små
datasett V1 V2 V3 V4 V5 V6 V7 V8 V9 F1 F2 F3 F4 F5 F6 F7 Artist Album name : String 1 biography : Text name : String mainGenre : Genre * release : Date T1 T2 T3 T4 T5 T6 founded : Date rating : Option[Int] split : Option[Date] 1 * * * Song DB name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    70. 70. Alternativer ©
Mesan
AS
    71. 71. JDBC Rykk
tilbake
til
start! Ingen
hindringer,
ingen
begrensinger All
makt «enumeration» Artist Genre Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    72. 72. JDBC• Direkte
integrasjon
mot
databasen• Ingen
avhengigheter,
fundamentalt
i
Java
SE• Grunnlaget
for
alle
abstraksjoner ©
Mesan
AS
    73. 73. Modell • Frie
tøyler! import Genre._ class Artist(val name: String, val biography: String, val founded: Date, val split: Option[Date], val mainGenre: Genre, val albums: List[Album] = Nil, val persons: List[Person] = Nil) class Album(val name: String, val release: Date, val rating: Int, val songs: List[Song] = Nil) class Song(val name: String, val duration: Int, val tracknumber: Int) class Person(val firstname: String, val lastname: String, val biography: String) «enumeration» Artist Genre Album name : StringRock 1 biography : Text name : StringPop *Classic mainGenre : Genre release : DateBlues founded : Date rating : Option[Int]Rap split : Option[Date] 1HipHopAlternative * * * Song name : String Person duration : Int firstname : String trackNumber : Int lastname : String biography : Text ©
Mesan
AS
    74. 74. Insertdef con: Connectiondef insertArtist { val in = "INSERT INTO ARTISTS(name, biography, founded, maingenre) VALUES (?,?,?,?)" val ps = con.prepareStatement(in) ps.setString(1, "Tool") ps.setString(2, "bla bla bla...") ps.setDate(3, Date.valueOf("1990-01-02")) ps.setInt(4, Genre.Rock.id) ps.executeUpdate()} Artist name : String biography : Text mainGenre : Genre founded : Date split : Option[Date] ©
Mesan
AS
    75. 75. Insertdef con: Connectiondef insertArtist { val in = "INSERT INTO ARTISTS(name, biography, founded, maingenre) VALUES (?,?,?,?)" val ps = con.prepareStatement(in) ps.setString(1, "Tool") ps.setString(2, "bla bla bla...") ps.setDate(3, Date.valueOf("1990-01-02")) ps.setInt(4, Genre.Rock.id) ps.executeUpdate()}def insertAlbum { val in = "INSERT INTO ALBUMS(name, release, rating, artist_id) VALUES (?,?,?,?)" val ps = con.prepareStatement(in) ps.setString(1, "New one") ps.setDate(2, Date.valueOf("2011-09-07")) ps.setInt(3, 3) ps.setInt(4, 1001) Artist ps.executeUpdate() name : String} biography : Text mainGenre : Genre founded : Date split : Option[Date] ©
Mesan
AS
    76. 76. Updatedef updateArtist { val ps = con.prepareStatement("UPDATE ARTISTS SET name = ? WHERE id = ?") ps.setString(1, "updated...") ps.setInt(2, 1001) ps.executeUpdate()} Artist name : String biography : Text mainGenre : Genre founded : Date split : Option[Date] ©
Mesan
AS
    77. 77. Updatedef updateArtist { val ps = con.prepareStatement("UPDATE ARTISTS SET name = ? WHERE id = ?") ps.setString(1, "updated...") ps.setInt(2, 1001) ps.executeUpdate()}def updateAlbums { val ps = con.prepareStatement("UPDATE ALBUMS SET rating = ? WHERE artist_id = ?") ps.setInt(1, 5) ps.setInt(2, 1001) ps.executeUpdate()} Artist name : String biography : Text mainGenre : Genre founded : Date split : Option[Date] ©
Mesan
AS
    78. 78. Finn én (eller ingen)def findArtist : Option[Artist] = { st = conn.prepareStatement( "SELECT id, name, biography, founded, split, maingenre FROM ARTISTS WHERE id=?") st.setInt(1, 1001) rs = st.executeQuery() if (rs.next()) { val id = rs.getInt(1) val name = rs.getString(2) val bio = rs.getString(3) val founded = rs.getDate(4) val split = rs.getDate(5) val splitO = if (split != null) Some(split) else None val gen = Genre(rs.getInt(6)) Some(new Artist(name, bio, founded, splitO, gen)) } else { None }} ©
Mesan
AS
    79. 79. Finn mangedef findAllArtists : List[Artist] = { var res = List[Artist]() val st = con.prepareStatement( "SELECT id, name, biography, founded, split, maingenre FROM ARTISTS") val rs = st.executeQuery() while (rs.next()) { val name = rs.getString(2) val bio = rs.getString(3) val founded = rs.getDate(4) val split = rs.getDate(5) val splitO = if (split != null) Some(split) else None val gen = Genre(rs.getInt(6)) val a = new Artist(name, bio, founded, splitO, gen) res ::= a } res.reverse} ©
Mesan
AS
    80. 80. Finn album med sangerdef findAlbum() = { val q = " SELECT a.id, a.name, a.release, a.rating, s.name, s.duration, s.tracknumber FROM Albums a JOIN Songs s ON s.album_id = a.id WHERE a.id = ? ORDER BY s.tracknumber ASC " val ps = con.prepareStatement(q) ps.setInt(1, 1001) val rs = ps.executeQuery() while (rs.next) { // extract song, add to list val s = new Song(name, duration, tracknumber) songs ::= a } // extract album from last row, add songs to artist new Album(name, release, rating, songs)} ©
Mesan
AS
    81. 81. Oppsiden• Full
kontroll
på
all
SQL • Hvilken
SQL
som
kjøres • Når
den
kjøres• Full
valgfrihet
i
modellering
av
data • class,
case
class,
Option[]
etc • Tilgang
til
alt
vi
ønsker
oss ©
Mesan
AS
    82. 82. What´s the catch? ©
Mesan
AS
    83. 83. What´s the catch?• boilerplate ©
Mesan
AS
    84. 84. What´s the catch? var conn : Connection = null• boilerplate var st : PreparedStatement = null try { conn = con st = conn.prepareStatement("SQL here") // do something SQLy } finally { st.close() conn.close() if (rs.next()) { } // do something with resultset } st.setInt(1, 1) while (rs.next()) { st.setXXX // do something with resultset } rs.getInt(1) rs.getString(2) rs.getXxx(3) ©
Mesan
AS
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×