Scala 各种数据库访问框架简介
2015-11-07 16:26
429 查看
目前有关 Scala libraries 和框架相当多
有一些非ORM的数据库库,也有ORM的,下面列出一些:
ScalaQuery
The first one is ScalaQuery. It is the most mature one, and it tries to make queries use the same for-comprehension as Scala collections do. As an example of syntax style (which might be slightly out of date):
在试用了一下后,发现对MS SERVER 支持地不太好
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
import java.lang.Integer
import com.novocode.squery._
import com.novocode.squery.Implicit._
import com.novocode.squery.session._
import com.novocode.squery.session.SessionFactory._
// Define table:
object Users extends Table[(Integer, String, String)]("users") {
def id = intColumn("id", O.AutoInc, O.NotNull)
def first = stringColumn("first")
def last = stringColumn("last")
def * = id ~ first ~ last
}
// Basic usage
val sf = new DriverManagerSessionFactory("org.h2.Driver", "jdbc:h2:mem:test1")
sf withSession {
// Prepare a simple query
val q1 = for(u <- Users) yield u
// Print SQL statement to be executed:
println(q1.selectStatement) // displays SELECT t1.id,t1.first,t1.last FROM users t1
// Print query result:
for(t <- q1) println("User tuple: "+t)
// Query statements can also be used with updates:
val q = for(u <- Users if u.id is 42) yield u.first ~ u.last
q.update("foo", "bar")
}
Querulous
The second one is Querulous, which is a open source project from Twitter. This one gives you direct access to SQL, while dealing with a bunch of jdbc annoyances. Here's a simple example:
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
import com.twitter.querulous.evaluator.QueryEvaluator
val queryEvaluator = QueryEvaluator("host", "username", "password")
val users = queryEvaluator.select("SELECT * FROM users WHERE id IN (?) OR name = ?", List(1,2,3), "Jacques") { row =>
new User(row.getInt("id"), row.getString("name"))
}
queryEvaluator.execute("INSERT INTO users VALUES (?, ?)", 1, "Jacques")
queryEvaluator.transaction { transaction =>
transaction.select("SELECT ... FOR UPDATE", ...)
transaction.execute("INSERT INTO users VALUES (?, ?)", 1, "Jacques")
transaction.execute("INSERT INTO users VALUES (?, ?)", 2, "Luc")
}
Squeryl
The third one is Squeryl. Style-wise, it sits midway between ScalaQuery -- which hides SQL behind Scala comprehensions as much as possible -- and Querulous -- which uses SQL strings directly.
Squeryl provides a SQL-like DSL, which gives you type safety and give you a strong likelyhood that the statements won't fail at run-time if they compile at all. Again, a simple example:
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
// Defining tables and a schema:
import org.squeryl.PrimitiveTypeMode._
class Author(var id: Long,
var firstName: String,
var lastName: String)
class Book(var id: Long,
var title: String,
@Column("AUTHOR_ID") // the default 'exact match' policy can be overriden
var authorId: Long,
var coAuthorId: Option[Long]) {
def this() = this(0,"",0,Some(0L))
}
object Library extends Schema {
//When the table name doesn't match the class name, it is specified here :
val authors = table[Author]("AUTHORS")
val books = table[Book]
}
// Basic usage
Class.forName("org.postgresql.Driver");
val session = Session.create(
java.sql.DriverManager.getConnection("jdbc:postgresql://localhost:5432/squeryl", "squeryl", "squeryl"),
new PostgreSqlAdapter
)
//Squeryl database interaction must be done with a using block :
import Library._
using(session) {
books.insert(new Author(1, "Michel","Folco"))
val a = from(authors)(a=> where(a.lastName === "Folco") select(a))
}
O/R Broker
http://code.google.com/p/orbroker/
The fourth is O/R Broker, which, despite the name, is not an ORM. Classes can be designed in any way desired. No interfaces/traits to implement, no conventions to uphold, no annotations needed.
可以快速开发,灵活性较高
case class Song(id: Option[Long], title: String, seconds: Short)
case class Album(id: Option[Long], title: String, year: Short, songs: IndexedSeq[Song])
case class Artist(id: Option[Long], name: String, albums: Set[Album])
Extractors are declarative, written in Scala. Can be reused in other queries that fit the expectation of the extractor.
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
object SongExtractor extends JoinExtractor[Song] {
val key = Set("SONG_ID")
def extract(row: Row, join: Join) = {
new Song(
row.bigInt("SONG_ID"),
row.string("TITLE").get,
row.smallInt("DURATION_SECONDS").get
)
}
}
object AlbumExtractor extends JoinExtractor[Album] {
val key = Set("ALBUM_ID")
def extract(row: Row, join: Join) = {
new Album(
row.bigInt("ALBUM_ID"),
row.string("TITLE").get,
row.smallInt("YEAR_ISSUED").get,
join.extractSeq(SongExtractor, Map("TITLE"->"SONG_TITLE"))
)
}
}
object ArtistExtractor extends JoinExtractor[Artist] {
val key = Set("ARTIST_ID")
def extract(row: Row, join: Join) = {
new Artist(
row.bigInt("ARTIST_ID"),
row.string("NAME"),
join.extractSeq(AlbumExtractor)
)
}
}
One could then use that like this:
val ds: javax.sql.DataSource = ...
val builder = new SQLFileBuilder(ds, new java.io.File("sql/"))
val broker = builder.build()
// Print all artists with their albums (if any)
val artists = broker.readOnly() { session =>
session.selectAll[Artist]('selectArtist) // ' I wish they could fix the Scala Symbol formatting
}
for (ar <- artists) {
println(a.name)
if (ar.albums.isEmpty)
println("\t<No albums>")
else for (al <- ar.albums) {
println("\t" + al.title)
for (s <- al.songs) {
println("\t\t" + (al.songs.indexOf(s)+1) + ". " + s.title)
}
}
}
Anorm
来自于Play框架,it ditches mappings and DSL completely, giving you direct access to SQL. 实例:
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
// Create an SQL query
val selectCountries = SQL("Select * from Country")
// Transform the resulting Stream[Row] as a List[(String,String)]
val countries = selectCountries().map(row =>
row[String]("code") -> row[String]("name")
).toList
It also supports pattern matching for row extraction:
val countries = SQL("Select name,population from Country")().collect {
case Row("France", _) => France()
case Row(name:String, pop:Int) if(pop > 1000000) => BigCountry(name)
case Row(name:String, _) => SmallCountry(name)
}
Binding variables in queries uses this syntax:
SQL(
"""
select * from Country c
join CountryLanguage l on l.CountryCode = c.Code
where c.code = {countryCode};
"""
).on("countryCode" -> "FRA")
And it also has support for use of parse combinators to translate queries or even table schemas into data structures. You can either define the parser yourself, or use some default conventions (like a case class mapping field names to column names) and let
it do the work for you.
Circumflex ORM
网站上有例子如下:
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
class Category extends Record[Category] {
val id = field(Category.id)
val name = field(Category.name)
val books = oneToMany(Book.category) // allows navigating between associations transparently
}
object Category extends Table[Category] with LongIdPK[Category] {
val name = stringColumn("name") // creates a column
.notNull // creates NOT NULL constraint
.unique // creates UNIQUE constraint
.validateNotEmpty // adds NotEmpty validation
.validatePattern("^[a-zA-Z]{1,8}$") // adds Pattern validation
}
class Book extends Record[Book] {
val id = field(Book.id)
val title = field(Book.title)
val category = manyToOne(Book.category)
}
object Book extends Table[Book] with LongIdPK[Book] {
val title = stringColumn("title")
.notNull
.validateNotEmpty
val category = longColumn("category_id")
.references(Category) // creates an association with Category
.onDeleteSetNull // specifies a foreign-key action
.onUpdateCascade
}
new DDLExport(Category, Book).create // creates database schema
// find category by id
val c = Category.get(2l)
// find all books
val allBooks = Book.all
// find books for category
val cBooks = c.get.books
// find books by title
Book.criteria.add("title" like "a%").list
select()
.from(Category as "c" join (Book as "b"), Category as "c1")
.where("c1.name" like "a%")
.addOrder(asc("c.name"))
.list
select(count("b.id"), "c.name").from(Category as "c" join (Book as "b")).list
以上资料摘至
http://stackoverflow.com/questions/1362748/wanted-good-examples-of-scala-database-persistence
有一些非ORM的数据库库,也有ORM的,下面列出一些:
ScalaQuery
The first one is ScalaQuery. It is the most mature one, and it tries to make queries use the same for-comprehension as Scala collections do. As an example of syntax style (which might be slightly out of date):
在试用了一下后,发现对MS SERVER 支持地不太好
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
import java.lang.Integer
import com.novocode.squery._
import com.novocode.squery.Implicit._
import com.novocode.squery.session._
import com.novocode.squery.session.SessionFactory._
// Define table:
object Users extends Table[(Integer, String, String)]("users") {
def id = intColumn("id", O.AutoInc, O.NotNull)
def first = stringColumn("first")
def last = stringColumn("last")
def * = id ~ first ~ last
}
// Basic usage
val sf = new DriverManagerSessionFactory("org.h2.Driver", "jdbc:h2:mem:test1")
sf withSession {
// Prepare a simple query
val q1 = for(u <- Users) yield u
// Print SQL statement to be executed:
println(q1.selectStatement) // displays SELECT t1.id,t1.first,t1.last FROM users t1
// Print query result:
for(t <- q1) println("User tuple: "+t)
// Query statements can also be used with updates:
val q = for(u <- Users if u.id is 42) yield u.first ~ u.last
q.update("foo", "bar")
}
Querulous
The second one is Querulous, which is a open source project from Twitter. This one gives you direct access to SQL, while dealing with a bunch of jdbc annoyances. Here's a simple example:
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
import com.twitter.querulous.evaluator.QueryEvaluator
val queryEvaluator = QueryEvaluator("host", "username", "password")
val users = queryEvaluator.select("SELECT * FROM users WHERE id IN (?) OR name = ?", List(1,2,3), "Jacques") { row =>
new User(row.getInt("id"), row.getString("name"))
}
queryEvaluator.execute("INSERT INTO users VALUES (?, ?)", 1, "Jacques")
queryEvaluator.transaction { transaction =>
transaction.select("SELECT ... FOR UPDATE", ...)
transaction.execute("INSERT INTO users VALUES (?, ?)", 1, "Jacques")
transaction.execute("INSERT INTO users VALUES (?, ?)", 2, "Luc")
}
Squeryl
The third one is Squeryl. Style-wise, it sits midway between ScalaQuery -- which hides SQL behind Scala comprehensions as much as possible -- and Querulous -- which uses SQL strings directly.
Squeryl provides a SQL-like DSL, which gives you type safety and give you a strong likelyhood that the statements won't fail at run-time if they compile at all. Again, a simple example:
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
// Defining tables and a schema:
import org.squeryl.PrimitiveTypeMode._
class Author(var id: Long,
var firstName: String,
var lastName: String)
class Book(var id: Long,
var title: String,
@Column("AUTHOR_ID") // the default 'exact match' policy can be overriden
var authorId: Long,
var coAuthorId: Option[Long]) {
def this() = this(0,"",0,Some(0L))
}
object Library extends Schema {
//When the table name doesn't match the class name, it is specified here :
val authors = table[Author]("AUTHORS")
val books = table[Book]
}
// Basic usage
Class.forName("org.postgresql.Driver");
val session = Session.create(
java.sql.DriverManager.getConnection("jdbc:postgresql://localhost:5432/squeryl", "squeryl", "squeryl"),
new PostgreSqlAdapter
)
//Squeryl database interaction must be done with a using block :
import Library._
using(session) {
books.insert(new Author(1, "Michel","Folco"))
val a = from(authors)(a=> where(a.lastName === "Folco") select(a))
}
O/R Broker
http://code.google.com/p/orbroker/
The fourth is O/R Broker, which, despite the name, is not an ORM. Classes can be designed in any way desired. No interfaces/traits to implement, no conventions to uphold, no annotations needed.
可以快速开发,灵活性较高
case class Song(id: Option[Long], title: String, seconds: Short)
case class Album(id: Option[Long], title: String, year: Short, songs: IndexedSeq[Song])
case class Artist(id: Option[Long], name: String, albums: Set[Album])
Extractors are declarative, written in Scala. Can be reused in other queries that fit the expectation of the extractor.
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
object SongExtractor extends JoinExtractor[Song] {
val key = Set("SONG_ID")
def extract(row: Row, join: Join) = {
new Song(
row.bigInt("SONG_ID"),
row.string("TITLE").get,
row.smallInt("DURATION_SECONDS").get
)
}
}
object AlbumExtractor extends JoinExtractor[Album] {
val key = Set("ALBUM_ID")
def extract(row: Row, join: Join) = {
new Album(
row.bigInt("ALBUM_ID"),
row.string("TITLE").get,
row.smallInt("YEAR_ISSUED").get,
join.extractSeq(SongExtractor, Map("TITLE"->"SONG_TITLE"))
)
}
}
object ArtistExtractor extends JoinExtractor[Artist] {
val key = Set("ARTIST_ID")
def extract(row: Row, join: Join) = {
new Artist(
row.bigInt("ARTIST_ID"),
row.string("NAME"),
join.extractSeq(AlbumExtractor)
)
}
}
One could then use that like this:
val ds: javax.sql.DataSource = ...
val builder = new SQLFileBuilder(ds, new java.io.File("sql/"))
val broker = builder.build()
// Print all artists with their albums (if any)
val artists = broker.readOnly() { session =>
session.selectAll[Artist]('selectArtist) // ' I wish they could fix the Scala Symbol formatting
}
for (ar <- artists) {
println(a.name)
if (ar.albums.isEmpty)
println("\t<No albums>")
else for (al <- ar.albums) {
println("\t" + al.title)
for (s <- al.songs) {
println("\t\t" + (al.songs.indexOf(s)+1) + ". " + s.title)
}
}
}
Anorm
来自于Play框架,it ditches mappings and DSL completely, giving you direct access to SQL. 实例:
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
// Create an SQL query
val selectCountries = SQL("Select * from Country")
// Transform the resulting Stream[Row] as a List[(String,String)]
val countries = selectCountries().map(row =>
row[String]("code") -> row[String]("name")
).toList
It also supports pattern matching for row extraction:
val countries = SQL("Select name,population from Country")().collect {
case Row("France", _) => France()
case Row(name:String, pop:Int) if(pop > 1000000) => BigCountry(name)
case Row(name:String, _) => SmallCountry(name)
}
Binding variables in queries uses this syntax:
SQL(
"""
select * from Country c
join CountryLanguage l on l.CountryCode = c.Code
where c.code = {countryCode};
"""
).on("countryCode" -> "FRA")
And it also has support for use of parse combinators to translate queries or even table schemas into data structures. You can either define the parser yourself, or use some default conventions (like a case class mapping field names to column names) and let
it do the work for you.
Circumflex ORM
网站上有例子如下:
Java代码
![](http://zeallf.iteye.com/images/icon_star.png)
class Category extends Record[Category] {
val id = field(Category.id)
val name = field(Category.name)
val books = oneToMany(Book.category) // allows navigating between associations transparently
}
object Category extends Table[Category] with LongIdPK[Category] {
val name = stringColumn("name") // creates a column
.notNull // creates NOT NULL constraint
.unique // creates UNIQUE constraint
.validateNotEmpty // adds NotEmpty validation
.validatePattern("^[a-zA-Z]{1,8}$") // adds Pattern validation
}
class Book extends Record[Book] {
val id = field(Book.id)
val title = field(Book.title)
val category = manyToOne(Book.category)
}
object Book extends Table[Book] with LongIdPK[Book] {
val title = stringColumn("title")
.notNull
.validateNotEmpty
val category = longColumn("category_id")
.references(Category) // creates an association with Category
.onDeleteSetNull // specifies a foreign-key action
.onUpdateCascade
}
new DDLExport(Category, Book).create // creates database schema
// find category by id
val c = Category.get(2l)
// find all books
val allBooks = Book.all
// find books for category
val cBooks = c.get.books
// find books by title
Book.criteria.add("title" like "a%").list
select()
.from(Category as "c" join (Book as "b"), Category as "c1")
.where("c1.name" like "a%")
.addOrder(asc("c.name"))
.list
select(count("b.id"), "c.name").from(Category as "c" join (Book as "b")).list
以上资料摘至
http://stackoverflow.com/questions/1362748/wanted-good-examples-of-scala-database-persistence
相关文章推荐
- centos6.5环境下redis3.0集群搭建和配置
- MySQL忘记密码怎么办
- 修改mysql DataDir方式
- Linux 下安装Redis教程
- 基于MySQL5.7MHA的配置
- PHP-Redis扩展使用手册(三)
- 【回顾整理】暴走的SQL语句练习!!!
- Windows下Mysql解压缩版配置安装与卸载
- sql子句的执行顺序
- 在LiftWeb下配置PostgreSQL数据库
- 如何给web项目添加redis服务 JAVA几种缓存技术 ehcache和redis哪个更好
- jsp程序向调用mysql语句操作数据库传中文出现乱码
- mysql中的关键字
- 通过innobackupex实现对MySQL的完整热备份
- 在ionic 项目中 使用sqlite 代替local storage
- SQL Server 2008 R2——以特定符号出现的次数来判断当前内容所在的层次
- Oracle安装图解
- 常用SQL语句
- mysql处理中文乱码的问题
- mysql学习笔记(1)