亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Groovy 的SQL模塊

2019-11-06 06:32:23
字體:
來源:轉載
供稿:網友

Groovy的SQL模塊提供了對JDBC的抽象,讓我們使用JDBC更簡單,相關類在groovy.sql包下。本文參考自Working with a relational database,一些代碼引用了官方文檔,需要了解詳細信息請參見原文。

連接數據庫

和原文一樣,為了簡單這里使用嵌入式數據庫HSQLDB,連接時在內存中創建一個數據庫。數據庫驅動可以使用Maven或Gradle導入,也可以使用Groovy自帶的Grape依賴管理器。不過在Intellij IDEA上,下面的代碼有時候無法編譯,說是找不到數據庫驅動。這時候可以使用Gradle等工具管理依賴。

Groovy SQL的所有操作都在Sql類中,我們調用Sql的newInstance方法,傳遞URL、用戶名、密碼等參數即可連接到數據庫。這種方式需要自己手動調用close方法關閉數據庫。如果希望Groovy自動關閉連接,可以使用withInstance方法,所有操作都在該方法的參數閉包中完成,之后會自動關閉連接。

@GrabResolver(name = 'aliyun', root = 'http://maven.aliyun.com/nexus/content/groups/public/')@GrabConfig(systemClassLoader = true)@Grab(group = 'org.hsqldb', module = 'hsqldb', version = '2.3.4')class SqlDatabase { static void main(String[] args) { def sql = setUpDatabase() } static Sql setUpDatabase() { def url = 'jdbc:hsqldb:mem:test' def user = 'sa' def passWord = '' def driver = 'org.hsqldb.jdbcDriver' def sql = Sql.newInstance(url, user, password, driver) return sql }

如果使用數據源創建連接??梢灾苯訉祿磦鬟f給Sql的構造方法,即可由數據源創建連接。

def dataSource = new JDBCDataSource( database: 'jdbc:hsqldb:mem:yourDB', user: 'sa', password: '')def sql = new Sql(dataSource)

創建數據表

我們可以使用Sql的execute方法執行SQL語句。這里創建了一個數據表。另外還有executeInsert和executeUpdate方法用于執行插入和更新操作。由于Groovy支持多行字符串,所以我們不用像java那么費勁。

static void setUpTables(Sql sql) { 增刪查改

插入數據

插入數據可以使用execute或executeInsert方法。它們的主要區別是executeInsert方法會返回一個列表,包含了插入數據對應的所有主鍵。這兩個方法都支持?占位符和額外的參數列表,這時候Groovy會使用PreparedStatement來執行SQL。它們也都支持GString和內插字符串。

下面的例子使用了占位符和參數列表執行插入操作。

static void insertRow(Sql sql) { println('插入數據') String stmt = 'insert into author(firstname,lastname) values(?,?)' def params = ['Yi', 'Tian'] def id = sql.executeInsert(stmt, params) assert id[0] == [0] params = ['Zhang', 'San'] id = sql.executeInsert(stmt, params) assert id[0] == [1] }

查詢數據

如果喜歡傳統方式,可以使用query方法,會返回一個JDBC結果集可供查詢。

def expected = ['Dierk Koenig', 'Jon Skeet', 'Guillaume Laforge']def rowNum = 0sql.query('SELECT firstname, lastname FROM Author') { resultSet -> while (resultSet.next()) { def first = resultSet.getString(1) def last = resultSet.getString('lastname') assert expected[rowNum++] == "$first $last" }}

Groovy也提供了幾個方便的方法來獲取數據。eachRow方法接受一個閉包參數,在閉包中,我們可以使用索引或成員訪問符來獲取每行的結果。

rowNum = 0sql.eachRow('SELECT firstname, lastname FROM Author') { row -> def first = row[0] def last = row.lastname assert expected[rowNum++] == "$first $last"}

如果結果只有一行,還可以使用firstRow方法,它會返回GroovyRowResult對象。我們可以使用該對象提供的方法獲取數據。

def first = sql.firstRow('SELECT lastname, firstname FROM Author')

Groovy還提供了rows方法,它會返回一個GroovyRowResult對象列表。

List authors = sql.rows('SELECT firstname, lastname FROM Author')assert authors.size() == 3

更新數據

更新數據也可以使用execute方法,或者使用executeUpdate方法。executeUpdate方法會返回受影響的行數。

static void updateAuthor(Sql sql) { def stmt = 'update author set firstname=?,lastname=? where id=?' def row = sql.executeUpdate(stmt, ['li', '4', 1]) assert row == 1 }

刪除數據

刪除數據使用execute方法。

static void updateAuthor(Sql sql) { def stmt = 'update author set firstname=?,lastname=? where id=?' def row = sql.executeUpdate(stmt, ['li', '4', 1]) assert row == 1 }

高級SQL操作

事務管理

事務管理使用Sql的withTransaction方法,在閉包中執行的語句會自動包括在事務中。如果某個操作發生異常,整個事務就會回滾。下面的例子中,第二個SQL語句故意寫錯了,整個事務會回滾,我們可以看到事務前后的數據數量是相同的。

static void sqlTransaction(Sql sql) { println '事務管理' def rowsBefore = sql.firstRow('SELECT count(*) AS num FROM author').num try { sql.withTransaction { //正確語句 sql.executeInsert("INSERT INTO author(firstname,lastname) VALUES('wang','5')") sql.executeInsert("INSERT INTO author() VALUES(4324,3423)") } } catch (ignore) { println(ignore.message) } def rowsAfter = sql.firstRow('SELECT count(*) AS num FROM author').num assert rowsBefore == rowsAfter }

批處理

Sql的withBatch方法提供了批處理功能。該方法的第一個參數是一次性批處理的數量。

sql.withBatch(3) { stmt -> stmt.addBatch "INSERT INTO Author (firstname, lastname) VALUES ('Dierk', 'Koenig')" stmt.addBatch "INSERT INTO Author (firstname, lastname) VALUES ('Paul', 'King')" stmt.addBatch "INSERT INTO Author (firstname, lastname) VALUES ('Guillaume', 'Laforge')" stmt.addBatch "INSERT INTO Author (firstname, lastname) VALUES ('Hamlet', 'D''Arcy')" stmt.addBatch "INSERT INTO Author (firstname, lastname) VALUES ('Cedric', 'Champeau')" stmt.addBatch "INSERT INTO Author (firstname, lastname) VALUES ('Erik', 'Pragt')" stmt.addBatch "INSERT INTO Author (firstname, lastname) VALUES ('Jon', 'Skeet')"}

還可以使用預處理語句進行批處理。使用預處理的優點是執行語句的速度更快,缺點是所有批處理都是同一類型的語句。如果需要處理多個表,需要多個批處理語句。

def qry = 'INSERT INTO Author (firstname, lastname) VALUES (?,?)'sql.withBatch(3, qry) { ps -> ps.addBatch('Dierk', 'Koenig') ps.addBatch('Paul', 'King') ps.addBatch('Guillaume', 'Laforge') ps.addBatch('Hamlet', "D'Arcy") ps.addBatch('Cedric', 'Champeau') ps.addBatch('Erik', 'Pragt') ps.addBatch('Jon', 'Skeet')}

分頁

Groovy提供了SQL數據庫的分頁功能。前面提到的很多方法都有分頁的版本,我們只要傳入起始索引和要獲取的數據量,即可得到相應的數據。

static void sqlPagination(Sql sql) { println('分頁') def stmt = 'select id,firstname,lastname from author' sql.rows(stmt, 1, 3).each { printRow(it) } println('----------------') sql.rows(stmt, 4, 3).each { printRow(it) } println('----------------') sql.rows(stmt, 7, 3).each { printRow(it) } println('----------------') }

元數據

Groovy也能方便的獲取數據庫的元數據。要獲取數據庫元數據的話,調用Sql的connection.metaData屬性即可。如果要獲取結果的元數據,最好的辦法就是定義一個元數據閉包,然后傳給相關方法,Groovy會保證元數據閉包只調用一次。當然也可以直接在結果閉包中調用結果的getMetaData()方法獲取元數據,不過這樣這些代碼可能隨著結果的迭代重復執行多次。

static void sqlMetaData(Sql sql) { println '元數據' def connection = sql.connection.metaData println("數據庫驅動名稱:${connection.driverName}") println("數據庫版本號:${connection.databaseMajorVersion}.${connection.databaseMinorVersion}") println("數據庫產品名:${connection.databaseProductName}") println('結果元數據') def metaClosure = { meta -> println("${meta.getColumnName(1)}/t${meta.getColumnName(2)}/t${meta.getColumnName(3)}") } def rowClosure = { row -> println "[id=${row[0]},first=${row[1]},last=${row[2]}" } sql.eachRow('SELECT id,firstname,lastname FROM author', metaClosure, rowClosure) }

命名參數和序號參數

SQL語句的參數不僅可以使用問號占位符,還可以使用命名參數和序號參數。命名參數很簡單,Hibernate等很多其他框架都支持。

sql.execute "INSERT INTO Author (firstname, lastname) VALUES (:first, :last)", first: 'Dierk', last: 'Koenig'

還可以使用問號形式的命名參數,和上面等價。

sql.execute "INSERT INTO Author (firstname, lastname) VALUES (?.first, ?.last)", first: 'Jon', last: 'Skeet'

如果傳遞的參數是Map或者對象形式的,還可以使用帶序號的命名參數形式。Groovy會自動解析合適的參數。

class Rockstar { String first, last }def pogo = new Rockstar(first: 'Paul', last: 'McCartney')def map = [lion: 'King']sql.execute "INSERT INTO Author (firstname, lastname) VALUES (?1.first, ?2.lion)", pogo, map
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品久久一区| 日韩av手机在线观看| 久久国产精品久久国产精品| 国产成人中文字幕| 国产精品69久久久久| 亚洲人成电影在线播放| 日韩一区二区av| 国产精品美女无圣光视频| 久久精品视频在线观看| 91久久精品久久国产性色也91| 不卡av在线播放| 日本亚洲精品在线观看| 欧美日韩美女在线| 国产91对白在线播放| 国产mv久久久| 久久中文久久字幕| 欧美夫妻性生活视频| 精品久久久久久电影| 亚洲精品小视频在线观看| 91久久久久久久久久| 亚洲一二在线观看| 91精品国产乱码久久久久久蜜臀| 免费不卡在线观看av| 久久在精品线影院精品国产| 国产精品444| 国产成人福利网站| 欧美日韩成人在线视频| 91欧美激情另类亚洲| 亚洲综合在线小说| 亚洲成人免费网站| 成人乱人伦精品视频在线观看| 国产一区二区色| 国产成人+综合亚洲+天堂| 国产主播精品在线| 岛国视频午夜一区免费在线观看| 国产91免费观看| 国产日韩欧美电影在线观看| 激情成人中文字幕| 欧美激情女人20p| 午夜精品一区二区三区在线| 日韩av免费看网站| 成人免费淫片视频软件| 久久久电影免费观看完整版| 最近中文字幕mv在线一区二区三区四区| 国内精品久久久久久久| 青青青国产精品一区二区| 欧美贵妇videos办公室| 欧美成人激情图片网| 中文字幕精品av| 亚洲人成电影网站色…| 日韩美女视频免费在线观看| 中文字幕亚洲一区二区三区| 亚洲大胆人体在线| 国产亚洲美女精品久久久| 日韩av中文字幕在线| 最好看的2019年中文视频| 成人两性免费视频| 亚洲已满18点击进入在线看片| 大伊人狠狠躁夜夜躁av一区| 国产成人精品久久二区二区| 日韩中文在线中文网三级| 4k岛国日韩精品**专区| 亚洲第一国产精品| 久久精品一本久久99精品| 久久久久在线观看| 97精品欧美一区二区三区| 国产精品精品国产| 亚洲人成毛片在线播放| 国产亚洲精品久久久久久777| 欧美性精品220| 欧美性xxxx18| 亚洲sss综合天堂久久| 国内免费久久久久久久久久久| 国产丝袜一区视频在线观看| 亚洲成av人片在线观看香蕉| 日韩成人中文电影| 国产成人精品免费久久久久| 97在线视频观看| 欧美在线视频a| 国产精品白嫩初高中害羞小美女| 丰满岳妇乱一区二区三区| 91精品国产91久久久久久久久| 日韩亚洲在线观看| 国产日韩欧美在线视频观看| 国产精品视频网址| 欧美午夜女人视频在线| 精品国产31久久久久久| 亚洲精品一区中文字幕乱码| 最近2019中文免费高清视频观看www99| 国产精品视频1区| 亚洲国产成人精品电影| 亚洲精品午夜精品| 国产成人精品优优av| 亚洲精品中文字幕有码专区| 久久精品亚洲94久久精品| 欧洲成人性视频| 九九综合九九综合| 精品福利免费观看| 欧美激情视频三区| 精品亚洲国产成av人片传媒| 亚洲最大福利视频网| 日本国产高清不卡| 中文字幕日韩在线观看| 久久精品国产免费观看| 亚洲精品国产精品国产自| 亚洲乱码国产乱码精品精| 性欧美视频videos6一9| 国产亚洲精品久久久优势| 欧美亚洲视频在线观看| 成人欧美一区二区三区在线| 91最新在线免费观看| 欧美www视频在线观看| 亚洲精品一区中文| 国产伦精品一区二区三区精品视频| 日本一区二区三区在线播放| 亚洲性69xxxbbb| 欧洲中文字幕国产精品| 欧美成年人视频网站| 午夜精品视频在线| 国产成人精品电影久久久| 青青久久aⅴ北条麻妃| 国产狼人综合免费视频| 91九色国产视频| 国内精品久久久久久久久| 一区二区三区久久精品| 欧美高清性猛交| 精品欧美一区二区三区| 91精品久久久久久久久久另类| 国产精品视频在线播放| 日本三级韩国三级久久| 亚洲男人天堂手机在线| 免费91麻豆精品国产自产在线观看| 欧美高跟鞋交xxxxxhd| 中文字幕最新精品| 国产精品久久久久久久久粉嫩av| 日本午夜人人精品| 成人激情视频小说免费下载| 亚洲永久免费观看| 成人在线一区二区| 成人综合国产精品| 欧美国产日韩视频| 久热精品视频在线观看一区| 国产精品综合不卡av| 午夜精品99久久免费| 欧美www视频在线观看| 亚洲精品成人久久电影| 亚洲xxxx视频| 国产久一一精品| 亚洲黄色在线观看| 黑人巨大精品欧美一区二区| 欧美激情视频网址| 中文字幕日韩综合av| 国产精品直播网红| 亚洲免费精彩视频| 黑人巨大精品欧美一区二区三区| 欧美视频在线观看免费网址| 91国产美女视频| 久久久久久噜噜噜久久久精品| 亚洲欧美综合图区| 国产精品久久久久免费a∨| 91探花福利精品国产自产在线| 8090成年在线看片午夜| 日韩av电影手机在线观看| 欧美人与物videos|