ScalaQuery

782 views

Published on

My presentation held at flatMap(Oslo)

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

  • Be the first to like this

No Downloads
Views
Total views
782
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
9
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
  • Herfra er det nesten bare kode - ROP ut om det er noe!!!\n
  • Herfra er det nesten bare kode - ROP ut om det er noe!!!\n
  • Herfra er det nesten bare kode - ROP ut om det er noe!!!\n
  • “min faste” modell jeg bruker når jeg tester nye systemer/teknologier etc\nhar laget også i mongo - fungerer strålende der også.\n
  • \n
  • \n
  • \n
  • settes typisk opp med cake/avhengigheter eller hvordan man ønsker\nLIFT: i boot\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • hva om jeg forteller ScalaQuery noe om databasen min?\n
  • \n
  • starte med å definere strukturen på tabellen\n
  • legge til kolonnenne som finnes\n
  • definere projeksjoner på kolonnene som finnes\n* MÅ definere STJERNE - denne brukes til og fra mapping som default\n
  • kan gjøres med caseklasser -> her er resten som tidligere\n<> kaller eg til-og-fra - og er laget for akkurat case-klasser\n
  • ENUMS i scala, kan gjøre tilsvarende med CASE OBJECTS\n
  • mapping til/fra immutable verdiobjekter\n
  • kaller insert på en projeksjon - med samme struktur som projeksjonen selv!\ngir kompileringsfeil ved feil struktur\ninsert er eager - gjøres med en gang mot databasen\n
  • \n
  • vanligste operatorer -> trigger databasen!\n
  • kan også skrives som...\n
  • Generator == tabell (eller en fremmednøkkel)\n
  • === mappes til = i basen\nlike\nupper, størreEnn, mindreEnn etc - alt som finnes i databasen\n
  • ingen av disse går mot basen før man faktisk kjører en list/first\n
  • spørring representerer WHERE-delen\nyield-delen det som skal oppdateres - og inputstruktur til .update-kallet\n
  • spørring representerer WHERE-delen\n
  • ForeignKeyQuery\n
  • \n
  • \n
  • kommer for scala 2.10, bruker makroer\n
  • \n
  • \n
  • ScalaQuery

    1. 1. ScalaQuery flatMap(Oslo)Trond Marius Øvstetun © Mesan AS
    2. 2. Trond Marius Øvstetun• Sjefskonsulentog fagleder i Mesan• Lidenskapelig utvikler, arkitekt, teamleder ++• Java, Scala, HTML/js• Alltid på jakt etter bedre, enklere måter © Mesan AS
    3. 3. Data• Vi har behov for å lagre data © Mesan AS
    4. 4. Data• Vi har behov for å lagre data• Ikke alle bruker eller kan bruke NoSQL © Mesan AS
    5. 5. Data• Vi har behov for å lagre data• Ikke alle bruker eller kan bruke NoSQL • konservativ it-avdeling? • legacy – eksisterende data • andre behov? © Mesan AS
    6. 6. Data• Vi har behov for å lagre data• Ikke alle bruker eller kan bruke NoSQL • konservativ it-avdeling? • legacy – eksisterende data • andre behov? • av og til er relasjonsmodellen riktig © Mesan AS
    7. 7. SQL• Hvordan jobber vi med RDBMS på best mulig måte? © Mesan AS
    8. 8. SQL• Hvordan jobber vi med RDBMS på best mulig måte?• JDBC? © Mesan AS
    9. 9. SQL• Hvordan jobber vi med RDBMS på best mulig måte?• JDBC?• ORM? © Mesan AS
    10. 10. SQL• Hvordan jobber vi med RDBMS på best mulig måte?• JDBC?• ORM? • Hibernate? © Mesan AS
    11. 11. SQL• Hvordan jobber vi med RDBMS på best mulig måte?• JDBC?• ORM? • Hibernate? • Anorm? Mapper? Record? © Mesan AS
    12. 12. ScalaQuery © Mesan AS
    13. 13. ScalaQueryA type-safe database API for Scala © Mesan AS
    14. 14. ScalaQueryA type-safe database API for Scala © Mesan AS
    15. 15. En enkel domenemodell «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
    16. 16. Koble til en database • Med javax.sql.DataSourcedef myDs : DataSource = {...}val db = Database.forDataSource(myDs) © Mesan AS
    17. 17. Koble til en database• Alternativt © Mesan AS
    18. 18. Koble til en database • AlternativtDatabase.forName("jdbc/my_ds") //JNDIDatabase.forURL("jdbc:h2:test") © Mesan AS
    19. 19. Gjøre noe med databasen val db = {...} db withSession { do_something() }import Database.threadLocalSession © Mesan AS
    20. 20. StaticQueryHåndkodet SQL mot databasen © Mesan AS
    21. 21. Spørringerval q = StaticQuery[Int] + "select count(id) from Artists"val count = q.first() © Mesan AS
    22. 22. Spørringerval q = StaticQuery[Int, (Int, String)] + "select id, name from Artists where id = ?"val (id,name) = q(1001).firstval artist : (Int, String) = q(1001).first © Mesan AS
    23. 23. Mapping av resultatcase class Artist(id:Int, name:String)val q = StaticQuery.query[Int, (Int, String)]( "select id, name from Artists where id = ?")val qMapped = q.mapResult[Artist]({ case (a, b) => Artist(a, b) })var a:Artist = qMapped(1001).first() © Mesan AS
    24. 24. Implisitt mapping avcase class Artist(id:Int, name:String)implicit val artMapper = GetResult( (r: PositionedResult) => new Artist(r<<, r<<))val q = StaticQuery.query[Int, Art]( "select id, name from Artists where id = ?")val a:Artist = q(1001).first © Mesan AS
    25. 25. Insert / Updateimport org.scalaquery.simple.StaticQuery._val q = query[(String, String), Int]( "insert into Artists(name, biography) "+ "values (?, ?)")val q2 = q("Seigmen", "")q2.execute() © Mesan AS
    26. 26. ScalaQuery © Mesan AS
    27. 27. ScalaQueryPå tide å få noe igjen? Hva om ... © Mesan AS
    28. 28. En enkel domenemodell «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
    29. 29. Mapping til en tabellobject Artists extends Table[ (Int, String, String, Genre.Genre, Date, Option[Date]) ]("ARTISTS") { ...} Artist name : String biography : Text mainGenre : Genre founded : Date © Mesan AS split : Option[Date]
    30. 30. Mapping til en tabellobject Artists extends Table (...) { def id = column[Int]("ID", O PrimaryKey) def name = column[String]("NAME") def biography = column[String]("BIOGRAPHY") def maingenre = column[Genre.Genre]("MAINGENRE") def founded = column[Date]("FOUNDED") def split = column[Option[Date]]("SPLIT")} Artist name : String biography : Text mainGenre : Genre founded : Date © Mesan AS split : Option[Date]
    31. 31. Mapping til en tabellobject Artists extends Table (...) { ... def * = id ~ name ~ biography ~ maingenre ~ founded ~ split def i = name ~ biography ~ maingenre ~ founded ~ split} Artist name : String biography : Text mainGenre : Genre founded : Date © Mesan AS split : Option[Date]
    32. 32. Mapping med case-klassecase class Artist( id:Int,name:String, bio:String, mainGenre:Genre.Genre, founded:Date, split:Option[Date])object Artists extends Table[Artist]("ARTISTS") { def * = id ~ .. ~ split <> (Artist, Artist.unapply _)} Artist name : String biography : Text mainGenre : Genre founded : Date © Mesan AS split : Option[Date]
    33. 33. Bruke egne typer column[Genre.Genre]("MAINGENRE") object Genre extends Enumeration { type Genre = Value «enumeration» Genre val Rock = Value(1) Rock Pop Classic ... Blues Rap HipHop Alternative val Alternative = Value(7) }implicit val genreMapper = MappedTypeMapper.base[Genre.Genre, Int]( _.id, Genre(_)) © Mesan AS
    34. 34. Bruke egne typer column[Duration]("DURATION")case class Duration(mins:Int, secs:Int)implicit object durationMapper extends MappedTypeMapper[Duration, Int] with BaseTypeMapper[Duration] with NumericTypeMapper { def map(dur: Duration) = dur.mins * 60 + dur.secs def comap(secs: Int) = Duration(secs / 60, secs % 60)} © Mesan AS
    35. 35. Inserts val i: Int = Artists.i.insert( ("Seigmen", "", Genre.Rock, date("1989-12-27"), Some(date("2008-06-22")))) // i is number of rows affectedval artists : List[(...)] = ...val i = Artists.i.insertAll(artists :_*)// i is Option[Int] - num affected © Mesan AS
    36. 36. Enkle spørringerdef findArtist(id:Int) : Option[(...)] = { val q = Artists.createFinderBy(_.id) q(id).firstOption} © Mesan AS
    37. 37. Enkle spørringerdef findArtist(id:Int) : Option[(...)] = { val q = Artists.createFinderBy(_.id) q(id).firstOption}def highRatedAlbums : List[...] = { val q = Albums.filter(_.rating === (Six:Rating)) q.list}def unRatedAlbums : List[...] = { val q = Albums.filter(_.rating isNull) q.list} © Mesan AS
    38. 38. Bruk av spørringerval resList = q.listval resOption = q.firstOptionval res = q.first © Mesan AS
    39. 39. Mer generelle spørringerval q1 = Artists.filter(_.maingenre === Genre.Rock) © Mesan AS
    40. 40. Mer generelle spørringerval q1 = Artists.filter(_.maingenre === Genre.Rock)val q = for { a <- Artists if a.maingenre === Genre.Rock} yield a © Mesan AS
    41. 41. Generell spørring val aQuery = for { x1 <- generator x2 <- generator ... xN <- generator guard } yield projection © Mesan AS
    42. 42. Parametrisertval qArtist = for { n <- Parameters[String] a <- Artists if a.name === n} yield a.id ~ a.name © Mesan AS
    43. 43. Parametrisertval qArtist = for { n <- Parameters[String] a <- Artists if a.name === n} yield a.id ~ a.nameval qTool = qArtist("Tool")val (id, name) = qTool.first © Mesan AS
    44. 44. Spørringer• Er lazy• Er immutable • Dele og gjenbruke • Byggeklosser © Mesan AS
    45. 45. Spørringer • Er lazy • Er immutable • Dele og gjenbruke • Byggeklosserval q1 = for (a <- Artists) yield aval q2 = for (a <- q1) yield a.id ~ a.nameval q3 = q2.take(10).drop(50) © Mesan AS
    46. 46. Updateval q = for { a <- Artists if a.id === 1001} yield a.nameq.update("updated") // num affected © Mesan AS
    47. 47. Deleteval q = for { a <- Albums if a.id === 1001} yield aq.delete © Mesan AS
    48. 48. Relasjoner /object Albums extends Table[(...)]("ALBUMS") { def artist_id = column[Int]("ARTIST_ID") def artist = foreignKey("albums_artists_fk", artist_id, Artists)(_.id) def * = id ~ name ~ release ~ rating ~ artist_id} Artist Album name : String 1 biography : Text name : String * mainGenre : Genre release : Date founded : Date rating : Option[Int] split : Option[Date] © Mesan AS
    49. 49. Joins Artist val q = for { Album name : String 1 biography : Text name : String * mainGenre : Genre release : Date al <- Albums founded : Date split : Option[Date] rating : Option[Int] a <- Artists if al.artist_id === a.id } yield a.name ~ al.name val q = for { al <- Albums a <- al.artist } yield a.name ~ al.nameval q = for { (al, a) <- Albums innerJoin Artists on (_.artist_id is _.id)} yield a.name ~ al.name © Mesan AS
    50. 50. Veien videre? ScalaQuery => SLICKScala Language Integrated © Mesan AS
    51. 51. SLICK• Generiskrammeverk for spørringer mot data• Ulike backends • SQL, NoSQL, json, WebServices, XML ...• Nærmere “vanlig” Scala-kode, backend som scala Collection © Mesan AS
    52. 52. Q&A© Mesan AS
    53. 53. Q&A© Mesan AS
    54. 54. takk for meg tmo@mesan.no @ovstetungithub.com/ovstetun/scala-persistence © Mesan AS

    ×