看完Slick官方网站上关于Slick3.1.1技术文档后决定开始动手建一个项目来尝试一下Slick功能的具体使用方法。我把这个过程中的一些了解和想法记录下来和大家一起分享。首先我用IntelliJ-Idea创建了一个scala项目。下一步就是如何选择数据库了。Slick是集成jdbc的更高层的Query编程语言,可以通过jdbc的url、DataSource等来指定目标数据库类型及相关的参数。对应Slick中的具体函数有:

val db = Database.forConfig("mydb")
val db = Database.forURL("jdbc:h2:mem:test1;DB_CLOSE_DELAY=-1", driver="org.h2.Driver")
val db = Database.forDataSource(dataSource: slick.jdbc.DatabaseUrlDataSource)

在Slick的Database配置方面forConfig("confItem")是比较灵活、方便实用的。confItem是resources/application.conf文件里的一个配置项目。Slick是通过typesafe-config来解析配置文件的。forConfig函数用typesafe-config库里的函数载入application.conf文件解析confItem并获取项目里的数据库配置参数,下面是项目中resources/application.conf文件内容:

h2mem {
url = "jdbc:h2:mem:slickdemo"
driver = "org.h2.Driver"
connectionPool = disabled
keepAliveConnection = true
} h2 = {
url = "jdbc:h2:~/slickdemo;mv_store=false;MODE=MSSQLServer;DB_CLOSE_DELAY=-1;AUTO_SERVER=TRUE"
driver = org.h2.Driver
connectionPool = disabled
keepAliveConnection = true
} mysql {
driver = "slick.driver.MySQLDriver$"
db {
url = "jdbc:mysql://localhost/slickdemo"
driver = com.mysql.jdbc.Driver
keepAliveConnection = true
user="root"
password=""
numThreads=
maxConnections =
minConnections =
}
} mysqldb = {
dataSourceClass = "com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
properties {
user = "root"
password = ""
databaseName = "slickdemo"
serverName = "localhost"
}
numThreads =
maxConnections =
minConnections =
} postgres {
driver = "slick.driver.PostgresDriver$"
db {
url = "jdbc:postgresql://127.0.0.1/slickdemo"
driver = "org.postgresql.Driver"
connectionPool = HikariCP
user = "slick"
password = ""
numThreads =
maxConnections =
minConnections =
}
} postgressdb = {
dataSourceClass = "org.postgresql.ds.PGSimpleDataSource"
properties = {
databaseName = "slickdemo"
user = "slick"
password = ""
}
connectionPool = HikariCP
numThreads =
maxConnections =
minConnections =
} mssql {
driver = "com.typesafe.slick.driver.ms.SQLServerDriver$"
db {
url = "jdbc:sqlserver://host:port"
driver = com.microsoft.sqlserver.jdbc.SQLServerDriver
connectionTimeout = second
connectionPool = HikariCP
user = "slick"
password = ""
numThreads =
maxConnections =
minConnections =
keepAliveConnection = true
}
} tsql {
driver = "slick.driver.H2Driver$"
db = ${h2mem}
}

在我使用的application.conf文件中汇集了一些常用数据库的配置,我一并提供出来。除h2之外其它都没进行测试验证,具体配置参数和方法要参考数据库开发商提供的技术文档。我在这个示范里选用了h2配置:它会在我的用户根目录下创建一个slickdemo.h2.db数据库文件。
好了,选择了数据库,下面我们就来试试使用它。基本流程是这样的:首先在数据库里创建表,跟着写入一些数据,然后再读出显示。整个过程会涉及:表结构schema定义,数据插写Insert,数据读取Query及简单的Query运算方法和数据显示方法。

现在我们先设计表结构schema:

 package com.datatech.learn.slick101
import slick.driver.H2Driver.api._
object slick101 { /* ----- schema */
//表字段对应模版
case class AlbumModel (id: Long
,title: String
,year: Option[Int]
,artist: String
)
//表结构: 定义字段类型, * 代表结果集字段
class AlbumTable(tag: Tag) extends Table[AlbumModel](tag, "ALBUMS") {
def id = column[Long]("ID",O.AutoInc,O.PrimaryKey)
def title = column[String]("TITLE")
def year = column[Option[Int]]("YEAR")
def artist = column[String]("ARTIST",O.Default("Unknown"))
def * = (id,title,year,artist) <> (AlbumModel.tupled, AlbumModel.unapply)
}
//库表实例
val albums = TableQuery[AlbumTable]

在这个示范里我们确定使用H2数据库,所以需要import H2Driver.api。使用了case class AlbumModel作为库表字段对应模版。这样一是可以规范代码,再就是如果遇到一个宽表有很多列的话可以节省许多重复铺垫及避免无谓错误。

现在需要从库表实例albums产生它的schema,然后转换成一个DBIOAction:

  //创建表动作
val createTableAction = albums.schema.create

这个createTableAction就是个DBIOAction:一个效果描述。我们必须用具体的实现方式Database.run来运算产生实际效果:

   //数据库实例化
val db = Database.forConfig("h2")
def main(args: Array[String]): Unit = {
val res = db.run(createTableAction).andThen {
case Success(_) => println("table ALBUMS created.")
case Failure(e) => println(e.getMessage)
}
Await.result(res, seconds)
}

db.run返回Future类型。我们是用Future类型的andThen组件来显示运算结果的:

table ALBUMS created.

Process finished with exit code 

如果跟着再运算一次应该会产生重复重建错误:

Exception in thread "main" org.h2.jdbc.JdbcSQLException: Table "ALBUMS" already exists; SQL statement:
Table "ALBUMS" already exists; SQL statement: ...

下面是一个插入数据的动作:

 //插入数据动作
val insertAlbumsAction =
albums ++= Seq(
AlbumModel(, "Keyboard Cat", Some(), "Keyboard Cat's Greatest Hits"),
AlbumModel(, "Spice Girls", Some(), "Spice"),
AlbumModel(, "Rick Astley", Some(), "Whenever You Need Somebody"),
AlbumModel(, "Manowar", None,"The Triumph of Steel"),
AlbumModel(, "Justin Bieber", Some(),"Believe"))

运算及显示结果:

    val res2 = db.run(insertAlbumsAction).andThen {
case Success(_) => println("albums inserted.")
case Failure(e) => println(e.getMessage)
}
Await.result(res2, seconds)
---
table ALBUMS created.
albums inserted. Process finished with exit code

下面是抽取动作和数据显示函数。我们把新插入的数据再读出来验证插入情况:

//数据抽取动作
val selectAlbumsAction =
albums.result
def printResults[T](fut: Future[Iterable[T]]): Unit =
Await.result(fut, Duration.Inf).foreach(println) val res3 = db.run(selectAlbumsAction)
printResults(res3)

运算结果:

AlbumModel(,Keyboard Cat,Some(),Keyboard Cat's Greatest Hits)
AlbumModel(,Spice Girls,Some(),Spice)
AlbumModel(,Rick Astley,Some(),Whenever You Need Somebody)
AlbumModel(,Manowar,None,The Triumph of Steel)
AlbumModel(,Justin Bieber,Some(),Believe) Process finished with exit code

下面是完整的示范代码:

 package com.datatech.learn.slick101
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.util.{Success,Failure} import slick.driver.H2Driver.api._
object slick101 { /* ----- schema */
//表字段对应模版
case class AlbumModel(id: Long
, artist: String
, year: Option[Int]
, title: String
) //表结构: 定义字段类型, * 代表结果集字段
class AlbumTable(tag: Tag) extends Table[AlbumModel](tag, "ALBUMS") {
def id = column[Long]("ID", O.AutoInc, O.PrimaryKey) def title = column[String]("TITLE") def year = column[Option[Int]]("YEAR") def artist = column[String]("ARTIST", O.Default("Unknown")) def * = (id, artist, year, title) <> (AlbumModel.tupled, AlbumModel.unapply)
} //库表实例
val albums = TableQuery[AlbumTable] //创建表动作
val createTableAction = albums.schema.create //数据库实例化
val db = Database.forConfig("h2") //插入数据动作
val insertAlbumsAction =
albums ++= Seq(
AlbumModel(, "Keyboard Cat", Some(), "Keyboard Cat's Greatest Hits"),
AlbumModel(, "Spice Girls", Some(), "Spice"),
AlbumModel(, "Rick Astley", Some(), "Whenever You Need Somebody"),
AlbumModel(, "Manowar", None,"The Triumph of Steel"),
AlbumModel(, "Justin Bieber", Some(),"Believe")) //数据抽取动作
val selectAlbumsAction =
albums.result def printResults[T](fut: Future[Iterable[T]]): Unit =
Await.result(fut, Duration.Inf).foreach(println) def main(args: Array[String]): Unit = { val res = db.run(createTableAction).andThen {
case Success(_) => println("table ALBUMS created.")
case Failure(e) => println(e.getMessage)
}
Await.result(res, seconds) val res2 = db.run(insertAlbumsAction).andThen {
case Success(_) => println("albums inserted.")
case Failure(e) => println(e.getMessage)
}
Await.result(res2, seconds) val res3 = db.run(selectAlbumsAction)
printResults(res3)
}
}

浅谈Slick(2)- Slick101:第一个动手尝试的项目的更多相关文章

  1. 浅谈Slick(4)- Slick301:我的Slick开发项目设置

    前面几篇介绍里尝试了一些Slick的功能和使用方式,看来基本可以满足用scala语言进行数据库操作编程的要求,而且有些代码可以通过函数式编程模式来实现.我想,如果把Slick当作数据库操作编程主要方式 ...

  2. 浅谈Slick(3)- Slick201:从fp角度了解Slick

    我在上期讨论里已经成功的创建了一个简单的Slick项目,然后又尝试使用了一些最基本的功能.Slick是一个FRM(Functional Relational Mapper),是为fp编程提供的scal ...

  3. 浅谈Slick(1)- 基本功能描述

    Slick (Scala language-integrated connection kit)是scala的一个FRM(Functional Relational Mapper),即函数式的关系数据 ...

  4. 在net中json序列化与反序列化 面向对象六大原则 (第一篇) 一步一步带你了解linq to Object 10分钟浅谈泛型协变与逆变

    在net中json序列化与反序列化   准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则 ...

  5. python浅谈正则的常用方法

    python浅谈正则的常用方法覆盖范围70%以上 上一次很多朋友写文字屏蔽说到要用正则表达,其实不是我不想用(我正则用得不是很多,看过我之前爬虫的都知道,我直接用BeautifulSoup的网页标签去 ...

  6. 浅谈php生成静态页面

    一.引 言 在速度上,静态页面要比动态页面的比方php快很多,这是毫无疑问的,但是由于静态页面的灵活性较差,如果不借助数据库或其他的设备保存相关信息的话,整体的管理上比较繁琐,比方修改编辑.比方阅读权 ...

  7. 浅谈 PHP 神盾的解密过程

    原文:浅谈 PHP 神盾的解密过程 前些日子一个朋友丢了个shell给我,让我帮忙解密,打开源码看了下写着是 “神盾加密” , 牛逼闪闪的样子.百度下发现神盾是个很古老的东西,最后一次更新是在 201 ...

  8. 浅谈 cxx rope

    一般说的浅谈是永远不会短的 然后$qwq$本宝宝并不想讲实现原理 会用就行了呗 然后方便起见,本文规定数组$a$的第$1$位为$a[0]$ 并且本文的所有$debug$为了方便看到我们$rope$长度 ...

  9. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

随机推荐

  1. SSH实战 · 唯唯乐购项目(下)

    后台模块 一:后台用户模块 引入后台管理页面 创建adminuser表: CREATE TABLE `adminuser` (   `uid` int(11) NOT NULL AUTO_INCREM ...

  2. WinForm 天猫2013双11自动抢红包【源码下载】

    1. 正确获取红包流程 2. 软件介绍 2.1 效果图: 2.2 功能介绍 2.2.1 账号登录 页面开始时,会载入这个网站:https://login.taobao.com/member/login ...

  3. X86和X86_64和X64有什么区别?

    x86是指intel的开发的一种32位指令集,从386开始时代开始的,一直沿用至今,是一种cisc指令集,所有intel早期的cpu,amd早期的cpu都支持这种指令集,ntel官方文档里面称为&qu ...

  4. Go web开发初探

    2017年的第一篇博客,也是第一次写博客,写的不好,请各位见谅. 本人之前一直学习java.java web,最近开始学习Go语言,所以也想了解一下Go语言中web的开发方式以及运行机制. 在< ...

  5. 【用户交互】APP没有退出前台但改变系统属性如何实时更新UI?监听系统广播,让用户交互更舒心~

    前日,一小伙伴问我一个问题,说它解决了半天都没解决这个问题,截图如下: 大概楼主理解如下: 如果在应用中有一个判断wifi的开关和一个当前音量大小的seekbar以及一个获取当前电量多少的按钮,想知道 ...

  6. C# await和async

    基础阅读:http://www.cnblogs.com/jesse2013/p/async-and-await.html 答疑阅读:http://www.cnblogs.com/heyuquan/ar ...

  7. jquery学习(一)

    简单的jquery学习,首先在页面引入jquery <!-- 引入jquery --> <script src="js/jquery-1.8.3.js" type ...

  8. iOS -- CocoaPods

    CocoaPods 是什么? CocoaPods 是一个负责管理 iOS 项目中第三方开源库的工具.CocoaPods 的项目源码在 GitHub( https://github.com/CocoaP ...

  9. POJ1149 PIGS [最大流 建图]

    PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20662   Accepted: 9435 Description ...

  10. 搭建一套自己实用的.net架构(3)续 【ORM Dapper+DapperExtensions+Lambda】

    前言 继之前发的帖子[ORM-Dapper+DapperExtensions],对Dapper的扩展代码也进行了改进,同时加入Dapper 对Lambda表达式的支持. 由于之前缺乏对Lambda的知 ...