mysql asyn 示例
這篇文章摘自mysql asyn作者的博客,博客地址
開頭有一個簡單示例,然后是一個在play上的應用。例子我并沒有跑過,但是仍能學到不少東西。
object BasicExample {
def main(args: Array[String]) {
// 這個Parser我發現好像用不了。。
val configuration = URLParser.parse("")
val connection: Connection = new PostgreSQLConnection(configuration)
//阻塞等待連接
Await.result(connection.connect, 5 seconds)
//sendQuery直接就執行了,不像slick那樣,還要單獨的run
val future: Future[QueryResult] = connection.sendQuery("SELECT * FROM USERS")
val mapResult: Future[Any] = future.map(queryResult => queryResult.rows match {
case Some(resultSet) => {
val row: RowDat = resultSet.head
row(0)
}
//注意,這里的-1是Any而不是Future[Any]
case None => -1
})
val result = Await.result(mapResult, 5 seconds)
println(result)
//關閉數據庫鏈接
connection.disconnect
}
}
The basic usage pattern is quite simple, you ask for something, you get a future[_] back. The PostgreSQLConnection is a real connection to database. it implements the Connection trait and you should try to use the trait as much as possible.
When you create a connection handler, it's not connected to the db yet, you have to connect it yourself calling connect and waiting for the future to return or composing on the future to do something else.
下面是一個play app. 包括MVC模型。因為Controller牽扯了太多play的知識,我就暫時不抄了,只把持久化部分寫上。
這個持久化實現了ResultSet到case class的mapping,雖然是手動進行的,但是寫的非常好。如果能使用implicit寫mapping應該會更加優雅。
此外,一個play app應該選用connection pool而不是每次用到數據庫都重新建立連接。下面給出了用法。
// 需要提前創建好數據庫,id應該是自增的
case class Message(id: Option[Long], content: String: LocalDate = LocalDate.now())
object MessageRepository {
val Insert = "INSERT INTO messages (content, moment) VALUES(?, ?)"
val Update = "UPDATE messages SET content = ?, moment = ? WHERE id = ?"
val Select = "SELECT id, content, moment FROM messages ORDER BY id asc"
val SelectOne = "SELECT id, content, momment FROM messages WHERE id = ?"
}
// 這個有點dependency injection的意思
class MessageRepository(pool: Content) {
import MessageRepository._
def save(m: Message): Future[Message] = {
// queryResult => m 是什么意思
case Some(id) => pool.sendPreparedStatement(Update, Array(m.content, m.moment, id)).
map { queryResult => m }
case None => pool.sendPreparedStatement(Insert, Array(m.content, m.moment)).
map { queryResult => m }
}
def list: Future[IndexSeq[Message]] = {
pool.sendQuery(Select). map {
//rows 返回resultSet, get返回什么呢,返回的是 Iterator 類型的東西么
queryResult => queryResult.rows.get.map {
item => rowToMessage(item)
}
}
}
def find(id: Long): Future[Option[Message]] = {
//[Any] 非得加么
pool.sendPreparedStatement(SelectOne, Array[Any](id)).map {
queryResult =>
queryResult.rows match {
case Some(rows) =>
Some(rowToMessage(rows.apply(0)))
case None => None
}
}
}
private def rowToMessage(row: RowData): Message = {
new Message(
id = Some(row("id".asInstanceOf[Long]))
content = row("content").asInstanceOf[String]
moment = row("moment").asInstanceOf[LocalDate]
)
}
}
對于mysql的每一張表,都應該有一個這樣的插入語句,對于多表join的情況,可能要單獨處理吧。
上面實現了DAO,下面一小段代碼可以充當配置文件來用,相當于dependency injection
object Global extends GlobalSettings {
private val databaseConfiguration = System.getenv("DATABASE_URL") match {
case url: String => URLParser.parse(url)
case _ => new Configuration(
username = "postgres"
database = Some("databasename")
port = 5433
)
}
// factory 還有mysql專用版么
private val factory = new PostgreSQLFactory(databaseConfiguration)
private val pool = new ConnectionPool(factory, PoolConfiguration.Default)
val messageRepository = new MessageRepository( pool )
// play 的東西,普通的程序不曉得如何處理close問題
override def onStop(app: Application)
pool.close
}
對于一般的程序,用connectionPool要好一點,但是要注意,不能直接在connectionPool上應用transacation。當需要用到transacation時,從connectionPool中獲取一個connection,還要記得還回去。
總結
以上是生活随笔為你收集整理的mysql asyn 示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 消息称小米 14 Pro 手机 3D 曲
- 下一篇: 3DMAX怎么制作素雅温馨的卧室效果