版权声明:本文为博主原创文章,未经博主允许不得转载

slick是scala的一个FRM(Functional Relational Mapper)框架,即函数式的关系数据库编程工具库。使用slick不同于使用java的hibernate或者是mybatis,对其进行迭代开发非常方便,因为其对表的映射基于函数式的编程方式。

使用slick对数据库表映射比较方便。

比如有一个表

CREATE TABLE Persons
(
id int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)

那么slick可以有两种方式进行映射,一种是使用scala的数据结构Tuple,一种是使用csse class,先看第一种

//使用Tuple
class TagsTree(tag: Tag) extends Table[(Int, String, String, String,String)](tag, "Persons") {
def id= column[Int]("id")
def LastName= column[String]("LastName")
def FirstName= column[String]("FirstName")
def Address= column[String]("Address")
def City= column[String]("City")
def * = (id,LastName,FirstName,Address,City);
}

再看第二种case class的方式:

case class Person(id:Int,lastName:String,firstName:String,Address:String,city:String);
class TagsTree(tag: Tag) extends Table[Person](tag, "Persons") {
def id= column[Int]("id")
def LastName= column[String]("LastName")
def FirstName= column[String]("FirstName")
def Address= column[String]("Address")
def City= column[String]("City")
def * = (id,LastName,FirstName,Address,City) <> (Person.tupled(), Person.unapply())
);
}

这里要说明一下,<>操作符可以看作某种映射,tupled()会将接受case class本身同样的参数然后生成一个Tuple。unapply是scala的一个语法糖,会返回一个Option[Int,String....]。这便是使用case class的方法了。

但当遇到表中的字段超过22个的时候就有问题了,因为scala规定构造参数不能超过22个,那这个时候怎么办呢,有两个办法,一个是使用slick提供的HList。

使用HList

import slick.collection.heterogeneous.{ HList, HCons, HNil } 

type hList =
String :: String :: Option[String] :: Option[String] :: Option[String] :: Option[String] ::
String :: String :: String :: String :: String :: Int :: Int :: String :: String :: String ::
Int :: Int :: Int :: Int :: Int :: Int :: Int :: Int :: Int ::
HNil;
//需要以HNil结尾
class Table(tag: Tag) extends Table[hList](tag, "myTableName") {
def name1 = column[String]("name1")
def name2 = column[String]("name2")
def name3 = column[Option[String]]("name3")
def name4 = column[Option[String]]("name4")
def name5 = column[Option[String]]("name5")
def name6 = column[Option[String]]("name6")
def name7 = column[String]("name7")
def name8 = column[String]("name8")
def name9 = column[String]("name9")
def name10 = column[String]("name10")
def name11 = column[String]("name11")
def name12 = column[Int]("name12")
def name13 = column[Int]("name13")
def name14 = column[String]("name14")
def name15 = column[String]("name15")
def name16 = column[String]("name16")
def name17 = column[Int]("name17")
def name18= column[Int]("name18")
def name19 = column[Int]("name19")
def name20 = column[Int]("name20")
def name21 = column[Int]("name21")
def name22 = column[Int]("name22")
def name23 = column[Int]("name23")
def name24 = column[Int]("name24")
def name25 = column[Int]("name25")
def * = name1 :: name2 :: name3 :: name4 :: name5 :: name6 ::
name7 :: name8 :: name8 :: name9 :: name10 ::
name11 :: name12 :: name13 :: name14 :: name15 ::
name16 :: name17 :: name18 :: name19 :: name20 :: name21 ::
name22 :: name23 :: name24 :: name25 ::
HNil
//需要以HNil结尾
}

不过这种有个缺点,那就是当表中某些属性可能为空,这时需要使用Option[String]()这种数据类型来存放属性。但HList查询出来的时候只会像一个字符串一样的Some("value")。

另一个方法是思路比较简单,既然一个case class放不下,那就拆呗

//代码出处 https://github.com/slick/slick/blob/2.1.0-RC1/slick-testkit/src/main/scala/com/typesafe/slick/testkit/tests/JdbcMapperTest.scala#L106

def testWideMappedEntity {
case class Part(i1: Int, i2: Int, i3: Int, i4: Int, i5: Int, i6: Int)
case class Whole(id: Int, p1: Part, p2: Part, p3: Part, p4: Part) class T(tag: Tag) extends Table[Whole](tag, "t_wide") {
def id = column[Int]("id", O.PrimaryKey)
def p1i1 = column[Int]("p1i1")
def p1i2 = column[Int]("p1i2")
def p1i3 = column[Int]("p1i3")
def p1i4 = column[Int]("p1i4")
def p1i5 = column[Int]("p1i5")
def p1i6 = column[Int]("p1i6")
def p2i1 = column[Int]("p2i1")
def p2i2 = column[Int]("p2i2")
def p2i3 = column[Int]("p2i3")
def p2i4 = column[Int]("p2i4")
def p2i5 = column[Int]("p2i5")
def p2i6 = column[Int]("p2i6")
def p3i1 = column[Int]("p3i1")
def p3i2 = column[Int]("p3i2")
def p3i3 = column[Int]("p3i3")
def p3i4 = column[Int]("p3i4")
def p3i5 = column[Int]("p3i5")
def p3i6 = column[Int]("p3i6")
def p4i1 = column[Int]("p4i1")
def p4i2 = column[Int]("p4i2")
def p4i3 = column[Int]("p4i3")
def p4i4 = column[Int]("p4i4")
def p4i5 = column[Int]("p4i5")
def p4i6 = column[Int]("p4i6")
def * = (
id,
(p1i1, p1i2, p1i3, p1i4, p1i5, p1i6),
(p2i1, p2i2, p2i3, p2i4, p2i5, p2i6),
(p3i1, p3i2, p3i3, p3i4, p3i5, p3i6),
(p4i1, p4i2, p4i3, p4i4, p4i5, p4i6)
).shaped <> ({ case (id, p1, p2, p3, p4) =>
// We could do this without .shaped but then we'd have to write a type annotation for the parameters
Whole(id, Part.tupled.apply(p1), Part.tupled.apply(p2), Part.tupled.apply(p3), Part.tupled.apply(p4))
}, { w: Whole =>
def f(p: Part) = Part.unapply(p).get
Some((w.id, f(w.p1), f(w.p2), f(w.p3), f(w.p4)))
})
}
val ts = TableQuery[T] val oData = Whole(0,
Part(11, 12, 13, 14, 15, 16),
Part(21, 22, 23, 24, 25, 26),
Part(31, 32, 33, 34, 35, 36),
Part(41, 42, 43, 44, 45, 46)
) ts.ddl.create
ts.insert(oData) assertEquals(oData, ts.first)
}

这里再那个.shaped是可以省略的,<>操作符后面看似很复杂,其实同样它后面有两个参数,一个Tuple和一个unapply方法,仅此而已。同时这里将映射写在一个方法里,这也是为什么slick称之为FRM。

 

slick对超过22个属性的表进行映射的两种办法的更多相关文章

  1. oracle多表关联删除的两种方法

    oracle多表关联删除的两种方法 第一种使用exists方法 delete from tableA where exits ( select 1 from tableB Where tableA.i ...

  2. jquery ajax提交表单数据的两种方式

    http://www.kwstu.com/ArticleView/kwstu_201331316441313 貌似AJAX越来越火了,作为一个WEB程序开发者要是不会这个感觉就要落伍,甚至有可能在求职 ...

  3. js阻止表单提交的两种方法

    下面直接看代码. <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  4. HTML中禁用表中控件的两种方法与区别

    在网页的制作过程中,我们会经常使用到表单.但是有时候我们会希望表单上的控件是不可修改的,比如在修改密码的网页中,显示用户名的文本框就应该是不可修改状态的. 在html中有两种禁用的方法,他们分别是: ...

  5. Mybatis中实体类属性和数据列之间映射的四种办法

    http://blog.csdn.net/lmy86263/article/details/53150091 Mybatis不像hibernate中那么自动化,通过@Column注解或者直接使用实体类 ...

  6. KingbaseES 两表关联Update的两种写法与性能

    熟悉oracle 的人都知道,对于两表的关联更新,其执行计划主要有 Filter 和 Outer Join 两种方式.对于大批量数据的update,Join方式明显是更优的选择.KingbaseES ...

  7. 32 ArcToolBox学习系列之数据管理工具箱——属性域(Domains)的两种创建及使用方式

    属性域分为两类,一种是范围域,一种是编码的值,下面将两个一起介绍,其中涉及到的编码,名称,只是试验,并非真实情况. 一.首先新建一个文件型地理数据库,将数据导入或者是新建要素类都可以 二.打开ArcT ...

  8. flask表单提交的两种方式

    一.通用方式 通用方式就是使用ajax或者$.post来提交. 前端html <form method="post" action="/mockservice&qu ...

  9. js方式清空表单数据的两种方式

    方法1:遍历页面元素 /* 清空FORM表单内容  id:表单ID*/  function ClearForm(id) {     var objId = document.getElementByI ...

随机推荐

  1. UINavigationController 返回手势与 leftBarButtonItem

    UINavigationController 返回手势与 leftBarButtonItem UINavigationController 自带从屏幕左侧边缘向右滑动的返回手势,可以通过这个手势实现 ...

  2. CountDownLatch源码解析

    一.CountDownLatch介绍 CountDownLatch是在jdk1.5被引入的,它主要是通过一个计数器来实现的,当在初始化该类的构造函数时,会事先传入一个状态值,之后在执行await方法后 ...

  3. JavaScript中常用的正则表达式日常整理(全)

    //校验是否全由数字组成 ? 1 2 3 4 5 6 function isDigit(s) { var patrn=/^[0-9]{1,20}$/; if (!patrn.exec(s)) retu ...

  4. Vijos P1785 同学排序【模拟】

    同学排序 描述 现有m位同学,第1位同学为1号,第2位同学为2号,依次第m位同学为m号.要求双号的学生站出来,然后余下的重新组合,组合完后,再次让双号的学生站出来,重复n次,问这时有多少同学出来站着? ...

  5. [bzoj1705] [Usaco2007 Nov]Telephone Wire 架设电话线

    正常DP.. f[i][j]表示前i个电线杆,把第i个电线杆高度改为j的最少总费用.设原来电线杆高度为h[] f[i][j]=min{ f[i-1][k]+C*|j-k|+(j-h[i])^2,(k& ...

  6. C语言中%d,%p,%u,%lu等都有什么用处

    %d 有符号10进制整数(%ld 长整型,%hd短整型 )%hu 无符号短整形(%u无符号整形,%lu无符号长整形)%i 有符号10进制整数 (%i 和%d 没有区别,%i 是老式写法,都是整型格式) ...

  7. Spring框架学习笔记(9)——Spring对JDBC的支持

    一.使用JdbcTemplate和JdbcDaoSupport 1.配置并连接数据库 ①创建项目并添加jar包,要比之前Spring项目多添加两个jar包c3p0-0.9.1.2.jar和mysql- ...

  8. [国嵌攻略][155][I2C用户态驱动设计]

    用户态驱动模型 用户态驱动模型首先是一个应用程序,其次是在这个用户程序中通过内核调用来驱动设备. IIC通用驱动代码 IIC通用驱动程序的代码在/drivers/i2c/i2c-dev.c中.一次读操 ...

  9. 【干货】平安打卡神器E行销刷脸考勤破解,是怎么做到的?

    很多人好奇平安E行销打卡到底是怎么破解的,为什么明明需要连接公司职场WiFi才可以参会,才可以刷脸打卡.为什么不用去公司,在家里,或者外面只要有4G或WiFi的地方都可以.今天我就来给大家解密.把原理 ...

  10. 从#65279字符看dede模板页面编码问题

    今天一位朋友让帮忙给解决一个dede模板的问题,问题主要是:模板文件生成html文件之后会在body开头处加入一个可见的控制符&#65279,导致页面头部会出现一个空白行. 接到"& ...