Iré con la opción B. No estoy muy familiarizado con BatchSql
desde la última vez que lo revisé, solo ejecuta una gran cantidad de consultas en secuencia, lo cual es terriblemente lento. Recomiendo agregar todo en una sola consulta. Es un poco más tedioso, pero mucho más rápido ejecutar una sola consulta con mil inserciones que con mil inserciones individuales.
Para mayor comodidad, digamos que tiene Seq
de
case class Test(val1: Int, val2: Option[Long], val3: Option[String])
Entonces podría construir su consulta de esta manera:
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()
Notas:
Tendrás que comprobar que values
no está vacío antes de continuar, ya que generaría una instrucción SQL no válida si lo estuviera.
Dependiendo de cuántas filas y columnas esté insertando, eventualmente los analizadores de tokens que crearon la declaración preparada se ralentizarán debido a la gran cantidad de tokens para analizar (y el tamaño de la cadena). Me di cuenta de esto después de unos cientos de filas con varias columnas. Esto se puede mitigar un poco. Gracias a que Scala es un lenguaje fuertemente tipado, Int
y Long
no representan una amenaza para la inyección de SQL. Puede preparar sus declaraciones SQL usando la interpolación/concatenación de cadenas solo para esas columnas y vincular las columnas no seguras con NamedParameter
normalmente. Eso reduciría la cantidad de tokens que deben analizarse.