浅谈Slick(2)- Slick101:第一个动手尝试的项目
看完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:第一个动手尝试的项目的更多相关文章
- 浅谈Slick(4)- Slick301:我的Slick开发项目设置
前面几篇介绍里尝试了一些Slick的功能和使用方式,看来基本可以满足用scala语言进行数据库操作编程的要求,而且有些代码可以通过函数式编程模式来实现.我想,如果把Slick当作数据库操作编程主要方式 ...
- 浅谈Slick(3)- Slick201:从fp角度了解Slick
我在上期讨论里已经成功的创建了一个简单的Slick项目,然后又尝试使用了一些最基本的功能.Slick是一个FRM(Functional Relational Mapper),是为fp编程提供的scal ...
- 浅谈Slick(1)- 基本功能描述
Slick (Scala language-integrated connection kit)是scala的一个FRM(Functional Relational Mapper),即函数式的关系数据 ...
- 在net中json序列化与反序列化 面向对象六大原则 (第一篇) 一步一步带你了解linq to Object 10分钟浅谈泛型协变与逆变
在net中json序列化与反序列化 准备好饮料,我们一起来玩玩JSON,什么是Json:一种数据表示形式,JSON:JavaScript Object Notation对象表示法 Json语法规则 ...
- python浅谈正则的常用方法
python浅谈正则的常用方法覆盖范围70%以上 上一次很多朋友写文字屏蔽说到要用正则表达,其实不是我不想用(我正则用得不是很多,看过我之前爬虫的都知道,我直接用BeautifulSoup的网页标签去 ...
- 浅谈php生成静态页面
一.引 言 在速度上,静态页面要比动态页面的比方php快很多,这是毫无疑问的,但是由于静态页面的灵活性较差,如果不借助数据库或其他的设备保存相关信息的话,整体的管理上比较繁琐,比方修改编辑.比方阅读权 ...
- 浅谈 PHP 神盾的解密过程
原文:浅谈 PHP 神盾的解密过程 前些日子一个朋友丢了个shell给我,让我帮忙解密,打开源码看了下写着是 “神盾加密” , 牛逼闪闪的样子.百度下发现神盾是个很古老的东西,最后一次更新是在 201 ...
- 浅谈 cxx rope
一般说的浅谈是永远不会短的 然后$qwq$本宝宝并不想讲实现原理 会用就行了呗 然后方便起见,本文规定数组$a$的第$1$位为$a[0]$ 并且本文的所有$debug$为了方便看到我们$rope$长度 ...
- 浅谈 Fragment 生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...
随机推荐
- 【初学python】使用python连接mysql数据查询结果并显示
因为测试工作经常需要与后台数据库进行数据比较和统计,所以采用python编写连接数据库脚本方便测试,提高工作效率,脚本如下(python连接mysql需要引入第三方库MySQLdb,百度下载安装) # ...
- FragmentTabHost的基本用法
开通博客以来已经约莫1个月了.几次想提笔写写东西,但总是由于各种各样的原因并没有开始.现在,年假刚结束,项目也还没有开始,但最终促使我写这篇博客的是,看了一篇博友写的新年计划,说是要在新的一年中写50 ...
- Velocity笔记--使用Velocity获取动态Web项目名的问题
以前使用jsp开发的时候,可以通过request很轻松的获取到根项目名,现在换到使用velocity渲染视图,因为已经不依赖servlet,request等一些类的环境,而Web项目的根项目名又不是写 ...
- 安装angular-cli
最近在学习angular2,并尝试用这个框架来做公司的一个新项目. 终于要开始开发了,等了1个多月. 因为第一次用这个新框架做项目,不太熟悉,就找了angular-cli这个脚手架来搭建项目. 安装了 ...
- 【夯实PHP基础】nginx php-fpm 输出php错误日志
本文地址 原文地址 分享提纲: 1.概述 2.解决办法(解决nginx下php-fpm不记录php错误日志) 1. 概述 nginx是一个web服务器,因此nginx的access日志只有对访问页面的 ...
- angular2之前端篇—1(node服务器分支)
上一篇.net core和angular2之前端篇-1 使用的是dotnet模板.之所以用它,因为想用他写webapi,但是写道下一篇的时候遇到点问题,所以先写个分支测试一下.这次是用Node作为服务 ...
- Android中Fragment与Activity之间的交互(两种实现方式)
(未给Fragment的布局设置BackGound) 之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文<Android中Fragment的两种创建方式>,就如 ...
- 驱动01.LED
1.写出leds_open,leds_write函数2.1告诉内核这几个函数的存在?定义一个结构体file_operations2.2把这个结构体告诉内核?用register_chrdev(major ...
- 在VMware上安装CentOS -7
1.下载好VMware 2.准备好CentOS的镜像文件 3.打开VMware创建新的虚拟机 选择自定义高级后按下一步 继续下一步 选择稍后安装操作系统 客户机操作系统选择Linux,版本选择Cent ...
- Linux实战教学笔记07:Linux系统目录结构介绍
第七节 Linux系统目录结构介绍 标签(空格分隔):Linux实战教学笔记 第1章 前言 windows目录结构 C:\windows D:\Program Files E:\你懂的\精品 F:\你 ...