J’ai essayer de comprendre quelques luisante et ce qu’elle exige.
Ici it un exemple :
Quelqu'un pourrait m’expliquer quel est le but de méthode ici, ce qui est
, pourquoi ? et quelle est la Projection - méthode
' retourne l’instance de `` ?
J’ai essayer de comprendre quelques luisante et ce qu’elle exige.
Ici it un exemple :
Quelqu'un pourrait m’expliquer quel est le but de méthode ici, ce qui est
, pourquoi ? et quelle est la Projection - méthode
' retourne l’instance de `` ?
[Mise à JOUR] - ajouté (encore un autre) explication sur for
des compréhensions
L' *
méthode:
Cette propriété renvoie la valeur par défaut de projection - qui est de savoir comment vous décrire:
"toutes les colonnes (ou des valeurs calculées) je suis généralement intéressées".
Votre table peut avoir plusieurs champs; vous avez seulement besoin d'un sous-ensemble de votre défaut de projection. La valeur par défaut de projection doit correspondre au type les paramètres de la table.
Nous allons les prendre un à la fois. Sans l' <>
trucs, juste l' *
:
// First take: Only the Table Defintion, no case class:
object Bars extends Table[(Int, String)]("bar") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def * = id ~ name // Note: Just a simple projection, not using .? etc
}
// Note that the case class 'Bar' is not to be found. This is
// an example without it (with only the table definition)
Juste la définition d'un tableau comme ça vous permettra de faire des requêtes comme:
implicit val session: Session = // ... a db session obtained from somewhere
// A simple select-all:
val result = Query(Bars).list // result is a List[(Int, String)]
la valeur par défaut de la projection de l' (Int, String)
conduit à une List[(Int, String)]
pour les requêtes simples comme ceux-ci.
// SELECT b.name, 1 FROM bars b WHERE b.id = 42;
val q =
for (b <- Bars if b.id === 42)
yield (b.name ~ 1)
// yield (b.name, 1) // this is also allowed:
// tuples are lifted to the equivalent projection.
Quel est le type d' q
? C'est un Query
avec la projection (String, Int)
.
Lorsqu'il est invoqué, il renvoie une List
de (String, Int)
n-uplets que par la projection.
val result: List[(String, Int)] = q.list
Dans ce cas, vous avez défini la projection que vous voulez dans l' yield
clause
de la for
de la compréhension.
Maintenant, à propos de <>
et Bar.unapply
.
Cela fournit ce qu'on appelle Mappé Projections.
Jusqu'à présent nous avons vu comment nappe permet de formuler des requêtes en Scala
que le retour d'une projection des colonnes (ou des valeurs calculées); de Sorte que lors de l'exécution de
ces requêtes que vous devez penser à la ligne de résultat d'une requête comme un Scala tuple.
Le type de la n-uplet va correspondre à la Projection, qui est défini par votre
for
de la compréhension comme dans l'exemple précédent, de par la valeur par défaut *
de la projection).
C'est pourquoi, field1 ~ field2
renvoie une projection de l' Projection2[A, B]
où
A
est le type d' field1
et B
est le type d' field2
.
q.list.map {
case (name, n) => // do something with name:String and n:Int
}
Queury(Bars).list.map {
case (id, name) => // do something with id:Int and name:String
}
Nous avons affaire à des tuples, ce qui peut être fastidieux, si nous avons trop de
les colonnes. Nous aimerions penser à des résultats non comme TupleN
plutôt qu'à une certaine
objet avec des champs nommés.
(id ~ name) // A projection
// Assuming you have a Bar case class:
case class Bar(id: Int, name: String) // For now, using a plain Int instead
// of Option[Int] - for simplicity
(id ~ name <> (Bar, Bar.unapply _)) // A MAPPED projection
// Which lets you do:
Query(Bars).list.map ( b.name )
// instead of
// Query(Bars).list.map { case (_, name) => name }
// Note that I use list.map instead of mapResult just for explanation's sake.
Comment cela fonctionne? <>
prend une projection Projection2[Int, String]
et
retourne un mappage de la projection sur le type Bar
. Les deux arguments Bar, Bar.unapply _
dire de la nappe de la façon dont cette (Int, String)
de projection doit être mappé à une classe de cas.
C'est dans les deux sens de cartographie, Bar
est le cas du constructeur de la classe, de sorte que la
les informations nécessaires pour aller d' (id: Int, name: String)
d'un Bar
. Et unapply
si vous l'avez deviné, est pour l'inverse.
Où est - unapply
proviennent de? C'est un standard de Scala méthode disponible pour
tout cas ordinaire de la classe juste la définition d' Bar
vous donne un Bar.unapply
qui
est un extracteur qui peut être utilisé pour récupérer l' id
et name
que le
Bar
a été construit avec:
val bar1 = Bar(1, "one")
// later
val Bar(id, name) = bar1 // id will be an Int bound to 1,
// name a String bound to "one"
// Or in pattern matching
val bars: List[Bar] = // gotten from somewhere
val barNames = bars.map {
case Bar(_, name) => name
}
val x = Bar.unapply(bar1) // x is an Option[(String, Int)]
Afin que votre défaut de projection peut être adressé à la classe de cas de vous la plupart s'attendent à utiliser:
object Bars extends Table[Bar]("bar") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def * = id ~ name <>(Bar, Bar.unapply _)
}
Ou vous pouvez même lui demander par requête:
case class Baz(name: String, num: Int)
// SELECT b.name, 1 FROM bars b WHERE b.id = 42;
val q1 =
for (b <- Bars if b.id === 42)
yield (b.name ~ 1 <> (Baz, Baz.unapply _))
Ici le type d' q1
est Query
avec un mappé projection d' Baz
.
Lorsqu'il est invoqué, il renvoie une List
de Baz
objets:
val result: List[Baz] = q1.list
Enfin, en aparté, l' .?
offre l'Option de Levage - la Scala façon de
traiter les valeurs que peut-être pas.
(id ~ name) // Projection2[Int, String] // this is just for illustration
(id.? ~ name) // Projection2[Option[Int], String]
Qui, enveloppant, fonctionnent bien avec votre définition originale de l' Bar
:
case class Bar(id: Option[Int] = None, name: String)
// SELECT b.id, b.name FROM bars b WHERE b.id = 42;
val q0 =
for (b <- Bars if b.id === 42)
yield (b.id.? ~ b.name <> (Bar, Bar.unapply _))
q0.list // returns a List[Bar]
En réponse à l'observation sur la façon dont Slick utilise for
des compréhensions:
En quelque sorte, les monades toujours gérer pour afficher et demande à faire partie de l'explication...
Pour les interprétations ne sont pas spécifiques aux collections. Elles peuvent être utilisées sur tout type de Monade, et les collections sont juste un des nombreux types de monade types disponibles en Scala.
Mais comme les collections sont familiers, ils font un bon début point pour une explication:
val ns = 1 to 100 toList; // Lists for familiarity
val result =
for { i <- ns if i*i % 2 == 0 }
yield (i*i)
// result is a List[Int], List(4, 16, 36, ...)
En Scala, un pour la compréhension est sucre syntaxique pour méthode (éventuellement imbriquées) les appels de méthode: Le code ci-dessus est (plus ou moins) ce qui équivaut à:
ns.filter(i => i*i % 2 == 0).map(i => i*i)
Fondamentalement, quelque chose avec filter
, map
, flatMap
méthodes (en d'autres termes, une Monade) peut être utilisé dans un
for
de la compréhension à la place de ns
. Un bon exemple
est l' Option monade. Voici l'exemple précédent
où la de même for
déclaration de travaux sur le
List
ainsi que Option
monades:
// (1)
val result =
for {
i <- ns // ns is a List monad
i2 <- Some(i*i) // Some(i*i) is Option
if i2 % 2 == 0 // filter
} yield i2
// Slightly more contrived example:
def evenSqr(n: Int) = { // return the square of a number
val sqr = n*n // only when the square is even
if (sqr % 2 == 0) Some (sqr)
else None
}
// (2)
result =
for {
i <- ns
i2 <- evenSqr(i) // i2 may/maynot be defined for i!
} yield i2
Dans le dernier exemple, la transformation ne serait peut-être regarder comme ceci:
// 1st example
val result =
ns.flatMap(i => Some(i*i)).filter(i2 => i2 %2 ==0)
// Or for the 2nd example
result =
ns.flatMap(i => evenSqr(i))
Dans la Nappe, les requêtes sont monadique - ils sont juste des objets avec
l' map
, flatMap
et filter
méthodes. Si l' for
compréhension
(illustré dans l'explication de l' *
méthode) se traduit par:
val q =
Query(Bars).filter(b => b.id === 42).map(b => b.name ~ 1)
// Type of q is Query[(String, Int)]
val r: List[(String, Int)] = q.list // Actually run the query
Comme vous pouvez le voir, flatMap
, map
et filter
sont utilisés pour
générer un Query
par la répétition de la transformation de l' Query(Bars)
avec chaque invocation d' filter
et map
. Dans le cas de
les collections de ces méthodes d'itération et le filtre de la collection
mais en Slick ils sont utilisés pour générer du SQL. Plus de détails ici:
Comment Scala de la Nappe de traduire Scala code JDBC?
Puisque personne n'a répondu, ceci pourrait aider à obtenir vous avez commencé. Je ne sais pas Lisse très bien.
À partir de la Nappe de la documentation:
Levée De L'Incorporation:
Chaque table nécessite un * méthode contatining un défaut de projection. Cette décrit ce que vous obtiendrez lorsque vous renvoyer les lignes (sous la forme d'un objet de la table) à partir d'une requête. Slick * projection n'a pas à correspondre à celui de la base de données. Vous pouvez ajouter de nouvelles colonnes (par exemple avec valeurs calculées) ou d'omettre certaines colonnes que vous le souhaitez. La non-levée de type correspondant à l' * projection est donnée comme un paramètre de type d' Table. Pour simple, non cartographié les tables, ce sera une seule colonne type ou un n-uplet de types de colonne.
En d'autres termes, slick a besoin de savoir comment traiter avec une ligne retournée à partir de la base de données. La méthode que vous avez défini utilise leurs analyseur combinator fonctions de combiner vos définitions de colonne en quelque chose qui peut être utilisé sur une ligne.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.