浅谈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 中 ...
随机推荐
- html中如何添加提示信息
提示:在标签中添加title属性 1.文本中如何添加提示信息? 1.1直接在标签中加title="值": 例如:<p title="爱笑,爱哭,爱生活"& ...
- 我的MYSQL学习心得(一) 简单语法
我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
- React在开发中的常用结构以及功能详解
一.React什么算法,什么虚拟DOM,什么核心内容网上一大堆,请自行google. 但是能把算法说清楚,虚拟DOM说清楚的聊聊无几.对开发又没卵用,还不如来点干货看看咋用. 二.结构如下: impo ...
- 第一个移动前端开源项目-dailog
你还在为手机上没有忙碌光标而发愁吗?你还在抱怨弹出框组件要依赖zepto/jqery吗?你还在纠结是否要自己写一套还是去网上寻找成现成的UI组件吗?YouA为你轻松解决所有烦恼.YouA是我为移动前端 ...
- SVD奇异值分解的基本原理和运用
SVD奇异值分解: SVD是一种可靠的正交矩阵分解法.可以把A矩阵分解成U,∑,VT三个矩阵相乘的形式.(Svd(A)=[U*∑*VT],A不必是方阵,U,VT必定是正交阵,S是对角阵<以奇异值 ...
- Smarty的基本使用与总结
含义: Smarty是PHP的一个引擎模板,可以更好的进行逻辑与显示的分离,即我们常说的MVC,这个引擎的作用就是将C分离出来. 环境需求:PHP5.2或者更高版本 我使用的环境是:PHP5.3,wi ...
- AI人工智能系列随笔
初探 AI人工智能系列随笔:syntaxnet 初探(1)
- duang~免费的学习视频来啦:学霸君之全栈测试
学霸君向童鞋们推荐一款 同名学霸学习 视频教程 重点是完全免费收看学习噢!!! 今天 学霸君推荐腾讯课堂的学霸君之全栈测试 复制下方链接至腾讯课堂中报名学习 https://ke.qq.com/cou ...
- Hibernate中事务声明
Hibernate中JDBC事务声明,在Hibernate配置文件中加入如下代码,不做声明Hibernate默认就是JDBC事务. 一个JDBC 不能跨越多个数据库. Hibernate中JTA事务声 ...
- javascript有用小功能总结(未完待续)
1)javascript让页面标题滚动效果 代码如下: <title>您好,欢迎访问我的博客</title> <script type="text/javasc ...