与Groovy的脚本特性相适应,Groovy JDBC 包含了一个精巧简单的GroovySql API,由于使用闭包和迭代器,GroovySql 把 JDBC 的资源管理职责从开发人员转移到 Groovy 框架内,从而消除了 JDBC 编程的繁琐,使得变成人员可以把注意力放在处理查询结果上。
GroovySql 简介
在 Java 中,我们是这样利用JDBC来打印
Music CD的样品:
package cc.ejb.groovy;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class CdList {
public static void main(String[] args) {
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try{
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/samples","root", "");
stmt = con.createStatement();
rs = stmt.executeQuery("select * from cdbean");
while (rs.next()) {
System.out.println("id:" + rs.getLong(1) + " artist:" + rs.getString(2) + " type:" + rs.getString(3));
}
}catch(SQLException e){
e.printStackTrace();
}catch(ClassNotFoundException e){
e.printStackTrace();
}finally{
try{
rs.close();
}catch(Exception e){}
try{
stmt.close();
}catch(Exception e){}
try{
con.close();
}catch(Exception e){}
}
}
}利用迭代器和闭包,我们只需要短短的几行:
import groovy.sql.Sqlsql = Sql.newInstance("jdbc:mysql://localhost:3306/samples", "root","", "com.mysql.jdbc.Driver")
sql.eachRow("select * from cdbean"){
println "id:${it.id} artist:${it.artist} type:${it.type}"
}在上面这段脚本中,你看不到try...catch,也不用捕获任何exception,甚至你不用关闭 Connection,也不用关闭 ResultSet,或者在 JDBC 编程中可以找到的任何其他熟悉的重要特性。
脚本中eachRow 方法可以当成查询结果上的迭代器。每个迭代都会执行传递进去的闭包,并在闭包中打印出每一次迭代的内容,id,artist,type等等。
为了运行上面的例子,必须将MySql JDBC Driver添加到classpath中。
执行更复杂的查询
Groovy 的 Sql 对象另外提供了 execute 和 executeUpdate 方法用于处理更复杂的数据操作(例如 insert、 update 和 delete )。
在下面的脚本中,您看到一个简单的 insert,它再次以 ${} 语法使用变量替换。这个代码只是向 cdbean 表插入一个新行。
id = 999
title ="Concept"
artist = "Nefarious"
type = "Blues"
sql.execute("insert into cdbean (id, title,artist, type, notes) values(${id},${title}, ${artist}, ${type},NULL)")Groovy 还提供 execute 方法的一个重载版本,它接收一列值,这些值与查询中发现的 ? 元素对应。下面的例子查询了刚插入 cdbean 表中的数据。在底层,GroovySql 创建了普通 Java 语言 java.sql.PreparedStatement 的一个实例。
val = sql.execute("select * from cdbean where id = ?", [999])更新的方式基本相同,也使用 executeUpdate 方法。executeUpdate 方法接收一列值,与查询中的 ? 元素对应。
id= 556
artist = "Nefarious"
sql.executeUpdate("update cdbean set id = ? where artist = ?", [id, artist])删除实际上与插入相同,当然,语法不同,如例 9 所示。
sql.execute("delete from cdbean where id = ?" , [556])
数据集(DataSet)
构建于 GroovySql 简单性的基础之上,GroovySql 支持 DataSet 类型的概念,这基本上是数据库表的对象表示。使用 DataSet,您可以在行中遍历,也可以添加新行。实际上,用数据集是方便地表示表格的公共数据集合的方式。
但是,目前 GroovySql DataSet 类型的不足之处是它们没有代表关系;它们只是与数据库表的一对一映射。
import groovy.sql.Sql
class CdDataSetExample{
static void main(args) {
def sql = Sql.newInstance("jdbc:mysql://localhost:3306/samples", "root", "", "com.mysql.jdbc.Driver")
def myCD = sql.dataSet("cdbean")
myCD.each{ cd -> println "${cd.id}+ ${cd.title}"}
myCD.add(id:"9999", title:"clerisy", artist:"Mary",type:"POP")
}
}GroovySql 的 DataSet 类型可以容易地用 each 方法对表的内容进行遍历,容易地用 add 方法添加新行,add 方法接受一个 map 表示需要的数据。
使用存储过程和负索引
存储过程调用和负索引(negative indexing)可能是数据操纵的重要方面。GroovySql 使存储过程调用简单得就像在 Sql 类上使用 call 方法一样。对于负索引, GroovySql 提供了自己增强的 ResultSet 类型,它工作起来非常像 Groovy 中的 collections。例如,如果您想获取结果集中的最后一个项目,您可以像例子 所示的那样做:
sql.eachRow("select * from cdbean where id=556"){ cd -> println "-1 = " + cd.getAt(-2)
//prints type
println "2 = " + cd.getAt(3)
//prints type
}
编写一个简单的报告应用程序
我们将利用 GroovySql 编写一个报告所需数据库统计信息的应用程序,您的目标数据库是 MySQL,它恰好支持用查询发现状态信息这一概念。以下是您有兴趣的状态信息:
- 运行时间。
- 处理的全部查询数量。
- 特定查询的比例,例如 insert、update 和 select。
用 GroovySql 从 MySQL 数据库得到这个信息太容易了。
import groovy.sql.Sql
class StatusReport{
static void main(args) {
def uptime,questions,insertnum,selectnum,updatenum
def sql = Sql.newInstance("jdbc:mysql://localhost:3306/samples", "root", "", "com.mysql.jdbc.Driver")
sql.eachRow("show status"){ status ->
if(status.variable_name == "Uptime"){
uptime = status[1]
}else if (status.variable_name == "Questions"){
questions = status[1]
}
}
println "Uptime for Database: " + uptime
println "Number of Queries: " + questions
println "Queries per Minute = " + Integer.valueOf(questions) / Integer.valueOf(uptime)
sql.eachRow("show status like 'Com_%'"){ status ->
if(status.variable_name == "Com_insert"){
insertnum = Integer.valueOf(status[1])
}else if (status.variable_name == "Com_select"){
selectnum = Integer.valueOf(status[1])
}else if (status.variable_name == "Com_update"){
updatenum = Integer.valueOf(status[1])
}
}
println "% Queries Inserts = " + 100 * (insertnum / Integer.valueOf(uptime))
println "% Queries Selects = " + 100 * (selectnum / Integer.valueOf(uptime))
println "% Queries Updates = " + 100 * (updatenum / Integer.valueOf(uptime))
}
}
结束语
GroovySql 这个干净漂亮的 API 把闭包和迭代器与 Groovy 轻松的语法结合在一起,有助于在 Java 平台上进行快速数据库应用程序开发。
上一篇 >>>
Groovy 4 集合