Půjdu s možností B. Nejsem příliš obeznámen s BatchSql
od poslední kontroly, že to pouze provádí zatížení lodí v pořadí, což je strašně pomalé. Doporučuji vše shrnout do jednoho dotazu. Je to trochu zdlouhavější, ale mnohem rychlejší provést jeden dotaz s tisícem vložení než tisíc samostatných vložení.
Pro usnadnění řekněme, že máte Seq
z
case class Test(val1: Int, val2: Option[Long], val3: Option[String])
Pak byste mohli vytvořit svůj dotaz takto:
val values: Seq[Test] = Seq(....)
/* Index your sequence for later, to map to inserts and parameters alike */
val indexedValues = values.zipWithIndex
/* Create the portion of the insert statement with placeholders, each with a unique index */
val rows = indexValues.map{ case (value, i) =>
s"({val1_${i}}, {val2_${i}}, {val3_${i}})"
}.mkString(",")
/* Create the NamedParameters for each `value` in the sequence, each with their unique index in the token, and flatten them together */
val parameters = indexedValues.flatMap{ case(value, i) =>
Seq(
NamedParameter(s"val1_${i}" -> value.val1),
NamedParameter(s"val2_${i}" -> value.val2),
NamedParameter(s"val3_${i}" -> value.val3)
)
}
/* Execute the insert statement, applying the aggregated parameters */
SQL("INSERT INTO table1 (col1, col2, col3) VALUES " + rows)
.on(parameters: _ *)
.executeInsert()
Poznámky:
Budete muset zkontrolovat values
není před pokračováním prázdný, protože by vygeneroval neplatný příkaz SQL, pokud by byl.
V závislosti na tom, kolik řádků a sloupců vkládáte, se nakonec analyzátory tokenů, které vytvořily připravený příkaz, zpomalí z pouhého množství tokenů k analýze (a velikosti řetězce). Všiml jsem si toho po několika stovkách řádků s několika sloupci. To se dá trochu zmírnit. Díky tomu, že Scala je silně typovaný jazyk, Int
a Long
nepředstavují žádnou hrozbu pro SQL injection. Příkazy SQL byste mohli připravit pomocí interpolace/zřetězení řetězců pouze pro tyto sloupce a svázat nebezpečné sloupce pomocí NamedParameter
normálně. To by snížilo počet tokenů, které je třeba analyzovat.