我正在尝试使用ScalaQuery,这真的太棒了。我可以使用Scala类定义数据库表,并轻松查询。
但是我想知道,在下面的代码中,我如何检查一个表是否存在,所以我不会两次调用'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
}
}
}
}
答案 0 :(得分:7)
ScalaQuery版本0.9.4在org.scalaquery.meta包中包含许多有用的SQL元数据包装类,例如MTable:
http://scalaquery.org/doc/api/scalaquery-0.9.4/#org.scalaquery.meta.MTable
在ScalaQuery的测试代码中,我们可以看到正在使用的这些类的示例。特别是,请参阅org.scalaquery.test.MetaTest。
我写了这个小函数给我一张所有已知表的地图,用表名键控。
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;
}
现在,在创建SQL表之前,我可以检查“if(!tableMap.contains(tableName))”。
答案 1 :(得分:7)
这个帖子有点旧,但也许有人会觉得这很有用。我的所有DAO都包括:
def create = db withSession {
if (!MTable.getTables.list.exists(_.name.name == MyTable.tableName))
MyTable.ddl.create
}
答案 2 :(得分:2)
这是一个完整的解决方案,用于检查应用程序启动时使用PostGreSQL DB进行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
}
}
答案 3 :(得分:1)
使用java.sql.DatabaseMetaData
(接口)。根据您的数据库,可能会实现更多或更少的功能。
答案 4 :(得分:0)
See also the related discussion here.我个人更喜欢hezamu的建议,并将其扩展如下以保持干爽:
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)
}
答案 5 :(得分:0)
您可以在DAO中定义以下方法(取自Slick MTable.getTables always fails with Unexpected exception[JdbcSQLException: Invalid value 7 for parameter columnIndex [90008-60]]),根据您的数据库中是否存在已定义的表,该方法将为您提供真假o:
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
}
}
或者,您可以使用println方法检查是否存在某些“GIVENTABLENAME”或其他内容:
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和播放光滑的1.0.0。
干杯,