2011-03-26 2 views
9

ScalaQuery를 시도하고 있습니다. 정말 훌륭합니다. Scala 클래스를 사용하여 데이터베이스 테이블을 정의하고 쉽게 쿼리 할 수 ​​있습니다.ScalaQuery에 데이터베이스 테이블이 있는지 어떻게 알 수 있습니까?

하지만 다음 코드에서 테이블이 존재하는지 어떻게 확인할 수 있는지 알고 싶습니다. 그래서 'Table.ddl.create'를 두 번 호출하지 않고이 프로그램을 두 번 실행하면 예외가 발생합니다 ?

object Users extends Table[(Int, String, String)]("Users") { 
    def id = column[Int]("id") 
    def first = column[String]("first") 
    def last = column[String]("last") 
    def * = id ~ first ~ last 
} 

object Main 
{ 
    val database = Database.forURL("jdbc:sqlite:sample.db", driver = "org.sqlite.JDBC") 

    def main(args: Array[String]) { 
     database withSession { 
      // How could I know table Users is alrady in the DB? 
      if (???) { 
       Users.ddl.create 
      } 
     } 
    } 
} 

답변

7

ScalaQuery 버전 0.9.4이 같은 MTable로 org.scalaquery.meta 패키지에 도움이 SQL 메타 데이터 래퍼 클래스의 수를 포함 ScalaQuery에 대한 테스트 코드에서

http://scalaquery.org/doc/api/scalaquery-0.9.4/#org.scalaquery.meta.MTable

을 우리는 볼 수 있습니다 이러한 클래스의 예가 사용됩니다. 특히 org.scalaquery.test.MetaTest를 참조하십시오.

필자는이 작은 기능을 사용하여 알려진 모든 테이블의 맵을 테이블 이름으로 지정했습니다. 내가 SQL 테이블을 작성하기 전에, 내가 확인하실 수 있습니다 그래서 지금

import org.scalaquery.meta.{MTable} 
def makeTableMap(dbsess: Session) : Map[String, MTable] = { 
    val tableList = MTable.getTables.list()(dbsess); 
    val tableMap = tableList.map{t => (t.name.name, t)}.toMap; 
    tableMap; 
} 

, "경우 (! tableMap.contains (TABLENAME))".

+0

이 게시물 주셔서 감사합니다! 이것은 비동기 부트 스트랩을 만드는 훌륭한 방법입니다! 프레임 워크 (http://www.playframework.org/documentation/1.2.4/jobs). 건배, – egbutter

1

java.sql.DatabaseMetaData (인터페이스). 데이터베이스에 따라 더 많거나 적은 함수가 구현 될 수 있습니다.

+0

그래서 내가 할 수있는 ScalaQuery 방법이 없다고 생각합니까? –

+0

나는 아무것도 찾지 못했고, 내가 발견 한 것으로부터 (User 확장 테이블 [(튜플 유형)]), 나는 궁극적 인 타이핑을 사용하는 것이 목표라고 생각한다.동적으로 정의 된 테이블을 어떻게 원활하게 통합 할 수 있는지는 알 수 없지만 자주 반사를 사용하지 않았습니다. 따라서 방법이있을 수 있습니다. 단지 볼 수 없습니다. 설명서는 조금 기울다. 몇 가지'meta'-class가 있지만 위키 나 블로그에서 어떻게 사용하는지 예제를 찾지 못했습니다. :) –

+0

나는 아무것도 찾지 못한다. 그래서 이것이 답이라고 생각합니다. 그리고 단지 메모, 세션 # metaData는 현재 데이터베이스 세션의 java.sq.DatabaseMetaData를 얻을 수 있습니다. –

2

다음은이 스레드는 좀 오래 PlayFramework

import globals.DBGlobal 
import models.UsersTable 
import org.scalaquery.meta.MTable 
import org.scalaquery.session.Session 

import play.api.GlobalSettings 
import play.api.Application 

object Global extends GlobalSettings { 

    override def onStart(app: Application) { 

     DBGlobal.db.withSession { session : Session => 
      import org.scalaquery.session.Database.threadLocalSession 
      import org.scalaquery.ql.extended.PostgresDriver.Implicit._ 
      if (!makeTableMap(session).contains("tableName")) { 
       UsersTable.ddl.create(session) 
      } 
     } 
    } 

    def makeTableMap(dbsess: Session): Map[String, MTable] = { 
     val tableList = MTable.getTables.list()(dbsess) 
     val tableMap = tableList.map { 
     t => (t.name.name, t) 
    }.toMap 
     tableMap 
    } 
} 
7

에 대한 PostgreSQL의 DB를 사용하기 시작 응용 프로그램을 확인하는 전체 솔루션입니다,하지만 어쩌면 다른 사람이 유용하게 찾을 수 있습니다. 나는 개인적으로 hezamu의 제안을 선호 DRY를 유지하기 위해 다음과 같이 확장

def create = db withSession { 
    if (!MTable.getTables.list.exists(_.name.name == MyTable.tableName)) 
     MyTable.ddl.create 
} 
+0

감사합니다. Slick 2.1.x와 호환됩니다. – Gavin

0

See also the related discussion here. : 내 모든 DAO는이 포함

다음
def createIfNotExists(tables: TableQuery[_ <: Table[_]]*)(implicit session: Session) { 
    tables foreach {table => if(MTable.getTables(table.baseTableRow.tableName).list.isEmpty) table.ddl.create} 
} 

그냥 암시 세션 테이블을 만들 수 있습니다

db withSession { 
    implicit session => 
    createIfNotExists(table1, table2, ..., tablen) 
} 
0

당신은 DAO impl에 정의 된 테이블이 있는지에 따라 참 거짓 값을주는 다음 메서드 (Slick MTable.getTables always fails with Unexpected exception[JdbcSQLException: Invalid value 7 for parameter columnIndex [90008-60]]에서)를 정의 할 수 있습니다.

def checkTable() : Boolean = { 
     val action = MTable.getTables 
     val future = db.run(action) 
     val retVal = future map {result => 
      result map {x => x} 
     } 

     val x = Await.result(retVal, Duration.Inf) 

     if (x.length > 0) { 
      true 
     } else { 
      false 
     } 
     } 

또는 일부 "GIVENTABLENAME"또는 뭔가에 println 방법이있는 경우 당신이 확인할 수 있습니다 : 당신의 DB에

 def printTable() ={ 
      val q = db.run(MTable.getTables) 
      println(Await.result(q, Duration.Inf).toList(0)) //prints first MTable element 
      println(Await.result(q, Duration.Inf).toList(1))//prints second MTable element 
      println(Await.result(q, Duration.Inf).toList.toString.contains("MTable(MQName(public.GIVENTABLENAME_pkey),INDEX,null,None,None,None)")) 
     } 

잊지 마세요 는

import slick.jdbc.meta._ 

그런 다음 호출 추가 일반적인 @Inject()를 사용하여 어디에서나 메서드를 사용할 수 있습니다. 을 사용하여 2.4 및 play-slick 1.0.0을 재생하십시오.

건배,