【问题标题】:Populate H2 in-mem db from .csv file using scala slick使用 scala slick 从 .csv 文件填充 H2 in-mem db
【发布时间】:2020-09-05 15:58:02
【问题描述】:

上下文

  • 鉴于以下 Slick 数据库架构
class Suppliers(tag: Tag)
  extends Table[(Int, String, String, String, String, String)](tag, "SUPPLIERS") {

  // This is the primary key column:
  def id: Rep[Int] = column[Int]("SUP_ID", O.PrimaryKey)
  def name: Rep[String] = column[String]("SUP_NAME")
  def street: Rep[String] = column[String]("STREET")
  def city: Rep[String] = column[String]("CITY")
  def state: Rep[String] = column[String]("STATE")
  def zip: Rep[String] = column[String]("ZIP")
  
  // Every table needs a * projection with the same type as the table's type parameter
  def * : ProvenShape[(Int, String, String, String, String, String)] =
    (id, name, street, city, state, zip)
}
  • 以下.csv 示例文件
101, "Acme, Inc.", "99 Market Street", "Groundsville", "CA", "95199"
49, "Superior Coffee", "1 Party Place", "Mendocino", "CA", "95460"
150, "The High Ground", "100 Coffee Lane", "Meadows", "CA", "93966"
  • 我设置并尝试加载.csv 文件(其路径作为系统属性接收
object HelloSlick extends App {

  val csvPath = System.getProperty("csvPath")

  val db = Database.forConfig("h2mem")
  try {

    val suppliers = TableQuery[Suppliers]

    val setup: DBIO[Unit] = DBIO.seq(
      suppliers.schema.create,
      sqlu"INSERT INTO SUPPLIERS SELECT * FROM CSVREAD($csvPath)"
    )
    
    val resultFuture = db.run(setup)

    Await.result(resultFuture, Duration.Inf)

  } finally db.close
}
  • 然后创建数据库并成功加载.csv数据

但是……

其实是这样的:

09:49:39.553 [DEBUG] s.j.J.statement - Preparing statement: INSERT INTO SUPPLIERS SELECT * FROM CSVREAD(?)
Exception in thread "main" org.h2.jdbc.JdbcSQLDataException: Parameter "fileName" is not set; SQL statement:
INSERT INTO SUPPLIERS SELECT * FROM CSVREAD(?) [90012-199]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:587)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:427)
    at org.h2.message.DbException.get(DbException.java:205)
    at org.h2.message.DbException.get(DbException.java:181)
    at org.h2.expression.function.Function.getValueForColumnList(Function.java:2702)
    at org.h2.table.FunctionTable.<init>(FunctionTable.java:60)
    at org.h2.command.Parser.readTableFunction(Parser.java:1945)
    at org.h2.command.Parser.readTableFilter(Parser.java:1892)
    at org.h2.command.Parser.parseSelectSimpleFromPart(Parser.java:2641)
    at org.h2.command.Parser.parseSelectSimple(Parser.java:2788)
    at org.h2.command.Parser.parseSelectSub(Parser.java:2636)
    at org.h2.command.Parser.parseSelectUnion(Parser.java:2469)
    at org.h2.command.Parser.parseSelect(Parser.java:2440)
    at org.h2.command.Parser.parseInsertGivenTable(Parser.java:1759)
    at org.h2.command.Parser.parseInsert(Parser.java:1684)
    at org.h2.command.Parser.parsePrepared(Parser.java:891)
    at org.h2.command.Parser.parse(Parser.java:788)
    at org.h2.command.Parser.parse(Parser.java:760)
    at org.h2.command.Parser.prepareCommand(Parser.java:683)
    at org.h2.engine.Session.prepareLocal(Session.java:627)
    at org.h2.engine.Session.prepareCommand(Session.java:565)
    at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1292)
    at org.h2.jdbc.JdbcPreparedStatement.<init>(JdbcPreparedStatement.java:77)
    at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:349)
    at slick.jdbc.JdbcBackend$SessionDef.prepareStatement(JdbcBackend.scala:375)
    at slick.jdbc.JdbcBackend$SessionDef.prepareStatement$(JdbcBackend.scala:365)
    at slick.jdbc.JdbcBackend$BaseSession.prepareStatement(JdbcBackend.scala:489)
    at slick.jdbc.StatementInvoker.results(StatementInvoker.scala:33)
    at slick.jdbc.StatementInvoker.iteratorTo(StatementInvoker.scala:22)
    at slick.jdbc.Invoker.first(Invoker.scala:30)
    at slick.jdbc.Invoker.first$(Invoker.scala:29)
    at slick.jdbc.StatementInvoker.first(StatementInvoker.scala:16)
    at slick.jdbc.StreamingInvokerAction$HeadAction.run(StreamingInvokerAction.scala:52)
    at slick.jdbc.StreamingInvokerAction$HeadAction.run(StreamingInvokerAction.scala:51)
    at slick.dbio.DBIOAction$$anon$4.$anonfun$run$3(DBIOAction.scala:239)
    at scala.collection.Iterator.foreach(Iterator.scala:941)
    at scala.collection.Iterator.foreach$(Iterator.scala:941)
    at scala.collection.AbstractIterator.foreach(Iterator.scala:1429)
    at scala.collection.IterableLike.foreach(IterableLike.scala:74)
    at scala.collection.IterableLike.foreach$(IterableLike.scala:73)
    at scala.collection.AbstractIterable.foreach(Iterable.scala:56)
    at slick.dbio.DBIOAction$$anon$4.run(DBIOAction.scala:239)
    at slick.dbio.DBIOAction$$anon$4.run(DBIOAction.scala:237)
    at slick.basic.BasicBackend$DatabaseDef$$anon$3.liftedTree1$1(BasicBackend.scala:276)
    at slick.basic.BasicBackend$DatabaseDef$$anon$3.run(BasicBackend.scala:276)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

问题

我该如何修复绕过解决方法这种行为,以便能够通过@987654328 @path 作为参数?

如果我直接将.csv 路径放在CSVREAD 字符串语句中,一切都会按预期进行。

sqlu"INSERT INTO SUPPLIERS SELECT * FROM CSVREAD('/home/foo/sample.csv')"

sqlu 插值起作用时会发生一些事情。

build.sbt

libraryDependencies ++= List(
  "com.typesafe.slick" %% "slick" % "3.3.2",
  "org.slf4j" % "slf4j-nop" % "1.7.10",
  "com.h2database" % "h2" % "1.4.199"
)

【问题讨论】:

    标签: scala csv h2 slick


    【解决方案1】:

    您需要将'$csvPath' 替换为普通的$csvPath。 JDBC 参数是值,不能包含在字符串文字中。

    【讨论】:

    • 谢谢,你是对的,引号不是必需的,但代码仍然不起作用。我刚刚更新了帖子,但得到了例外。有什么想法吗?
    • 看起来H2的表值函数不支持参数。所以你需要一个解决方法。试试'#$csvPath',它应该内联传递的参数。但是,如果 ' 字符在该字符串中是可能的,则您需要在 csvPath 中将 ' 替换为 ''(两个字符)。
    • 我在 H2 的 bugtracker 上填写了一个关于该问题的新问题:github.com/h2database/h2database/issues/2634
    猜你喜欢
    • 2020-06-01
    • 2013-10-16
    • 2022-01-24
    • 1970-01-01
    • 2012-02-15
    • 2012-12-10
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    相关资源
    最近更新 更多