2014-09-24 4 views
1

스칼라 2.10.2와 슬릭 2.1.0을 사용하여 SQLite 데이터베이스 용 래퍼를 작성하고 있습니다. 테스트를 위해 메모리 내 데이터베이스를 만들고 테이블로 채우고 데이터를 삽입 한 다음 테스트 쿼리를 실행하는 기능을 원합니다. 내 데이터베이스의 장난감 상응하는 다음 작업 코드에 설명되어 있습니다 :스칼라 내부 메모리 데이터베이스 SQLite 해당 테이블 없음

import org.sqlite.JDBC 
import scala.slick.driver.SQLiteDriver.simple._ 

object MyDB 
{ 
    def testMemory() : Unit = MyDB.withMemoryTestDatabase(test) 

    def testFile() : Unit = MyDB.withFileTestDatabase(test) 

    val test : (MyDB) => Unit = 
    { 
     (mydb) => mydb.database.withSession{ implicit session => { 
      mydb.metadata.map(m => (m.key, m.value)).insert(("foo", "bar")) 
      assert(mydb.metadata("foo") == "bar") 
     } } 
    } 

    def withMemoryTestDatabase(testFunction : (MyDB) => Unit) : Unit = 
    { 
     val backend = new MyDB(Database.forURL("jdbc:sqlite::memory:", driver = "org.sqlite.JDBC")) 

     runTest(backend, testFunction) 
    } 

    def withFileTestDatabase(testFunction : (MyDB) => Unit) : Unit = 
    { 
     val backend = new MyDB(Database.forURL("jdbc:sqlite:test.sqlite", driver = "org.sqlite.JDBC")) 

     runTest(backend, testFunction) 

     val dbPath = new java.io.File("test.sqlite") 
     dbPath.delete 
    } 

    def runTest(backend : MyDB, testFunction : (MyDB) => Unit) : Unit = 
    { 
     backend.database.withSession{ implicit session => backend.metadata.ddl.create } 

     testFunction(backend) 
    } 
} 

class MyDB(val database : slick.driver.SQLiteDriver.backend.DatabaseDef) 
{ 
    class Metadata(tag : Tag) extends Table[(String,String)](tag, "Metadata") 
    { 
     def key = column[String]("key") 
     def value = column[String]("value") 

     def * = (key, value) 
    } 

    object metadata extends TableQuery(new Metadata(_)) 
    { 
     def apply(key : String) : String = database.withSession { implicit session => this.map(m => (m.key, m.value)).run.toMap.apply(key) } 
    }  
} 

I가 발생하고있어 문제는 그 코드, MyDB.testFile() 실행 완벽하다. 그러나 MyDB.testMemory()은 실패합니다. 메타 데이터 테이블이 존재하지 않습니다. 전체 오류 및 역 추적은 다음과 같습니다.

scala> MyDB.testFile 

scala> MyDB.testMemory 
java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (no such table: Metadata) 
    at org.sqlite.DB.newSQLException(DB.java:383) 
    at org.sqlite.DB.newSQLException(DB.java:387) 
    at org.sqlite.DB.throwex(DB.java:374) 
    at org.sqlite.NativeDB.prepare(Native Method) 
    at org.sqlite.DB.prepare(DB.java:123) 
    at org.sqlite.PrepStmt.<init>(PrepStmt.java:42) 
    at org.sqlite.Conn.prepareStatement(Conn.java:404) 
    at org.sqlite.Conn.prepareStatement(Conn.java:399) 
    at scala.slick.jdbc.JdbcBackend$SessionDef$class.prepareStatement(JdbcBackend.scala:152) 
    at scala.slick.jdbc.JdbcBackend$BaseSession.prepareStatement(JdbcBackend.scala:389) 
    at scala.slick.jdbc.JdbcBackend$SessionDef$class.withPreparedStatement(JdbcBackend.scala:190) 
    at scala.slick.jdbc.JdbcBackend$BaseSession.withPreparedStatement(JdbcBackend.scala:389) 
    at scala.slick.driver.JdbcInsertInvokerComponent$BaseInsertInvoker.preparedInsert(JdbcInsertInvokerComponent.scala:170) 
    at scala.slick.driver.JdbcInsertInvokerComponent$BaseInsertInvoker.internalInsert(JdbcInsertInvokerComponent.scala:180) 
    at scala.slick.driver.JdbcInsertInvokerComponent$BaseInsertInvoker.insert(JdbcInsertInvokerComponent.scala:175) 
    at MyDB$$anonfun$testMemory$1$$anonfun$apply$1.apply(MyDb.scala:9) 
    at MyDB$$anonfun$testMemory$1$$anonfun$apply$1.apply(MyDb.scala:8) 
    at scala.slick.backend.DatabaseComponent$DatabaseDef$class.withSession(DatabaseComponent.scala:34) 
    at scala.slick.jdbc.JdbcBackend$DatabaseFactoryDef$$anon$4.withSession(JdbcBackend.scala:61) 
    at MyDB$$anonfun$testMemory$1.apply(MyDb.scala:8) 
    at MyDB$$anonfun$testMemory$1.apply(MyDb.scala:8) 
    at MyDB$.withMemoryTestDatabase(MyDb.scala:28) 
    at MyDB$.testMemory(MyDb.scala:8) 
    at .<init>(<console>:8) 
    at .<clinit>(<console>) 
    at .<init>(<console>:7) 
    at .<clinit>(<console>) 
    at $print(<console>) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734) 
    at scala.tools.nsc.interpreter.IMain$Request.loadAndRun(IMain.scala:983) 
    at scala.tools.nsc.interpreter.IMain.loadAndRunReq$1(IMain.scala:573) 
    at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:604) 
    at scala.tools.nsc.interpreter.IMain.interpret(IMain.scala:568) 
    at scala.tools.nsc.interpreter.ILoop.reallyInterpret$1(ILoop.scala:745) 
    at scala.tools.nsc.interpreter.ILoop.interpretStartingWith(ILoop.scala:790) 
    at scala.tools.nsc.interpreter.ILoop.command(ILoop.scala:702) 
    at scala.tools.nsc.interpreter.ILoop.processLine$1(ILoop.scala:566) 
    at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:573) 
    at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:576) 
    at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply$mcZ$sp(ILoop.scala:867) 
    at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:822) 
    at scala.tools.nsc.interpreter.ILoop$$anonfun$process$1.apply(ILoop.scala:822) 
    at scala.tools.nsc.util.ScalaClassLoader$.savingContextLoader(ScalaClassLoader.scala:135) 
    at scala.tools.nsc.interpreter.ILoop.process(ILoop.scala:822) 
    at scala.tools.nsc.interpreter.ILoop.main(ILoop.scala:889) 
    at xsbt.ConsoleInterface.run(ConsoleInterface.scala:69) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at sbt.compiler.AnalyzingCompiler.call(AnalyzingCompiler.scala:102) 
    at sbt.compiler.AnalyzingCompiler.console(AnalyzingCompiler.scala:77) 
    at sbt.Console.sbt$Console$$console0$1(Console.scala:23) 
    at sbt.Console$$anonfun$apply$2$$anonfun$apply$1.apply$mcV$sp(Console.scala:24) 
    at sbt.TrapExit$.sbt$TrapExit$$executeMain$1(TrapExit.scala:33) 
    at sbt.TrapExit$$anon$1.run(TrapExit.scala:42) 

어디서 잘못 표시 될 수 있습니까?

N.B. JDBC 생성자에 대한 :memory: 인수가 작동하는 것 같습니다. 확실히 :memory: 파일을 생성하지는 않습니다.

def runTest(backend : MyDB, testFunction : (MyDB) => Unit) : Unit = 
{ 
    backend.database.withSession{ implicit session => 
     backend.metadata.ddl.create 
     testFunction(backend) 
    } 
} 
+1

확실하지 않지만 db에 둘 이상의 연결을 설정하면 데이터가 지속되지 않습니다. 여기를 참고하십시오 : http://www.sqlite.org/inmemorydb.html. jdbc uri의 끝에 '? cache = shared'를 추가해야 할 수도 있습니다. –

+1

소리가 들리 겠지만 'jdbc : sqlite :: memory :? cache = shared'라는 URL은': memory :? cache = shared'라는 파일을 생성합니다. – paulmdavies

+0

sqlite jdbc에 xerial 라이브러리를 사용하는 경우 다음이 도움이 될 수 있습니다. https://groups.google.com/forum/#!topic/xerial/gGeqCw3KzvU –

답변

0

한번에 추가 "; DB_CLOSE_DELAY = -1" 귀하의 DB URL의 끝에.

+0

처음에는 그렇게하기 위해 코드를 수정했습니다. 그런 다음'session'을'testFunction'에 명시 적으로 전달하고 테스트 함수에서 각 데이터베이스 호출에 명시 적으로 사용합니다. 그러나 여전히 작동하지 않습니다. 디버그 인쇄는 생성을 확인하고 테스트는 동일한 세션을 사용합니다. 나는 잃어 버렸다! – paulmdavies

+0

샘플 github 프로젝트를 설정하여 효과를 표시 할 수 있습니다. – cvogt

관련 문제