我想在groovy中编写一个DB util类,它接受一些强制和可选的db参数,并将结果作为映射列表返回。
Groovy类
class DBUtil {
private final String ORACLE="oracle"
private final String DB2="db2"
private final String SYBASE="sybase"
private final String SQLSERVER="sqlserver"
private final String MSSQLSERVER="mssqlserver"
private final String ORACLE_DRIVER="jdbc:agra:oracle"
private final String DB2_DRIVER="jdbc:agra:db2"
private final String SQLSERVER_DRIVER="jdbc:agra:sqlserver"
private final String SYBASE_DRIVER="jdbc:agra:sybase"
private final String ORACLE_DRIVER_CLASS="com.agra.jdbc.oracle.OracleDriver"
private final String DB2_DRIVER_CLASS="com.agra.jdbc.db2.DB2Driver"
private final String SQLSERVER_DRIVER_CLASS="com.agra.jdbc.sqlserver.SQLServerDriver"
private final String SYBASE_DRIVER_CLASS="com.agra.jdbc.sybase.SybaseDriver"
private HashMap<String,String> dbparams
private HashMap<String,String> sqlStatements
private String url
private String username
private String password
private String driver
private String driverClass
public void setDbParams(HashMap<String,String> dbparams) {
this.dbparams=dbparams
}
DBUtil(dbparams, sqlStatements) {
this.dbparams=dbparams
this.sqlStatements=sqlStatements
}
private void validateDBParams() {
if (dbparams != null) {
try {
if (dbparams?.containsKey("driver")) {
driver=dbparams?.get("driver")
driverClass=dbparams?.get("driverClass")
}
username=dbparams?.get("username")
password=dbparams?.get("password")
switch(dbparams?.get("dbtype")) {
case ORACLE:
if (!dbparams?.containsKey("driver")) {
driver=ORACLE_DRIVER
driverClass=ORACLE_DRIVER_CLASS
}
break
case DB2:
if (!dbparams?.containsKey("driver")) {
driver=DB2_DRIVER
driverClass=DB2_DRIVER_CLASS
}
break
case SYBASE:
if (!dbparams?.containsKey("driver")) {
driver=SYBASE_DRIVER
driverClass=SYBASE_DRIVER_CLASS
}
break
case SQLSERVER:
case MSSQLSERVER:
if (!dbparams?.containsKey("driver")) {
driver=SQLSERVER_DRIVER
driverClass=SQLSERVER_DRIVER_CLASS
}
break
}
url=driver+"://"+dbparams?.get("connectstring")
} catch (Exception e) {
e.printStackTrace()
}
}
}
public List<Map> execute() {
List<Map> resultSet;
def sql
try {
if (dbparams != null && sqlStatements != null) {
validateDBParams()
//println "$url, $username, $password, $driverClass"
sql = Sql.newInstance(url, username, password, driverClass)
sqlStatements.each {key, value->
List<Map> sqlResult = new ArrayList<Map>()
sql.eachRow(value) { row->
println row
}
//resultSet.add(sqlResult)
//println sqlResult
}
}
}
catch(SQLException se) {
println "Exception encountered in DBUtil execute() $se"
}
return resultSet
}
static main(args) {
HashMap<String,String> dbparams = ["dbtype":"oracle", "username":"johnkc", "password":"johnc", "connectstring":"apple:1521;SID=ORCL;",
"driver":"jdbc:agra:oracle","driverClass":"com.agra.jdbc.oracle.OracleDriver"]
HashMap<String,String> sqlStatements = ["sql1":"select name, value from v\$parameter",
"sql2":"select POO_NAME, POO_VALUE from PO_OPTION"]
DBUtil db = new DBUtil(dbparams, sqlStatements)
db.execute()
}
}
执行后,它会给我以下结果(键可以超过2)
[NAME:lock_name_space, VALUE:[null]]
[NAME:processes, VALUE:1000]
[NAME:sessions, VALUE:1105]
[POO_NAME:username, POO_VALUE:com.agra.jdbc.base.BaseClob@256ef705]
[POO_NAME:jdbcurl, POO_VALUE:com.agra.jdbc.base.BaseClob@181b7c76]
[POO_NAME:dbType, POO_VALUE:com.agra.jdbc.base.BaseClob@34883357]
[POO_NAME:ConnectionString, POO_VALUE:com.agra.jdbc.base.BaseClob@59e2afb2]
如何以上面的格式(地图列表)放置上面的输出?
[ "sql1": [ {row1}, {row2}... ],
"sql2": [ {row1}, {row2}... ],
...
]
其中row1 ... = {column1:value1,column2:value2,column3:value3 ...}
更新
sqlStatements.each
中的代码段下方为我提供了每个
def tableColumns=[:]
sql.rows(value, {meta ->
def columns=[]
int colCount=meta.columnCount
(1..colCount).each{
columns.add(meta.getColumnName(it))
}
tableColumns.put(key, columns)
})
使用我的解决方案进行更新
public List<Map> execute() {
List<Map<String,Object>> resultSet=new ArrayList<HashMap<String,Object>>()
def sql
try {
if (dbparams != null && sqlStatements != null) {
boolean validParams=validateDBParams()
if (validParams) {
sql = Sql.newInstance(url, username, password, driverClass)
sqlStatements.each {key, value->
def sqlResultMap=[:]
def tableColumns=[:]
sql.rows(value, {meta ->
def columns=[]
int colCount=meta.columnCount
(1..colCount).each{
columns.add(meta.getColumnName(it))
}
tableColumns.put(key, columns)
})
def rows=[]
sql.eachRow(value) {row->
def dbrow=[:]
tableColumns.get(key).each{ columnname->
dbrow.put(columnname, row."$columnname")
}
rows.add(dbrow)
}
sqlResultMap.put(key, rows)
resultSet.add(sqlResultMap)
}
}
}
}
catch(SQLException se) {
println "Exception encountered in DBUtil execute() $se"
}
return resultSet
}
它提供了地图列表。
答案 0 :(得分:2)
我现在无法测试,但IIRC你可以这样做:
Map<String, List> resultSets = [:]
...
sqlStatements.each { queryAlias, query ->
def columns=[]
sql.eachRow(query) { row ->
if (columns.isEmpty()) {
int colCount = row.columnCount
columns = (1..colCount).collect { row.getColumnName it }
}
resultSets[queryAlias] = columns.collect { column ->
row.getColumn(column)
}
}
}
更新:我几乎可以确定您只需row as Map
即可从结果列表中获取地图而无需提取每个列名称。
不相关,但我想就该课程建模提出一些建议:
execute()
可以接收它应该执行的SQL,因此您无需设置sqlStatements
属性来执行另一组查询。这非常粗糙,因为我没有数据库来测试它,但它可能是这样的:
abstract class Database {
enum Type { ORACLE, POSTGRES }
String url
String username
String password
abstract def getJdbc()
abstract def getDriver()
static Database create(Database.Type type, Map params) {
def db = [
(Type.ORACLE) : OracleDatabase,
(Type.POSTGRES) : PostgresDatabase
][type].newInstance()
assert (db.username = params.username), "No username given"
assert (db.password = params.password), "No password given"
assert (db.url = params.url), "No database URL given"
return db
}
Map<String, List> execute(sqlStatements) {
try {
Map<String, List> resultSets = [:]
assert sqlStatements != null
def sql = groovy.sql.Sql.newInstance(url, username, password, driver)
sqlStatements.each { queryAlias, query ->
def columns=[]
sql.eachRow(query) { row ->
if (columns.isEmpty()) {
int colCount = row.columnCount
columns = (1..colCount).collect { row.getColumnName it }
}
resultSets[queryAlias] = columns.collect { column -> row.getColumn(column) }
}
}
return resultSet
}
catch(se) {
println "Exception encountered in DBUtil execute() $se"
throw se
}
}
}
class OracleDatabase extends Database {
def getJdbc() { "jdbc:agra:oracle" }
def getDriver() { "com.agra.jdbc.oracle.OracleDriver" }
}
class PostgresDatabase extends Database {
def getJdbc() { "jdbc:agra:mysql" }
def getDriver() { "org.postgresql.Driver" }
}
def dbparams = [
"username":"johnkc",
"password":"johnc",
"url":"apple:1521;SID=ORCL;"
]
def sqlStatements = [
"sql1":"select name, value from v\$parameter",
"sql2":"select POO_NAME, POO_VALUE from PO_OPTION"
]
def db = Database.create(Database.Type.ORACLE, dbparams)
def result = db.execute(sqlStatements)
assert result instanceof Map
assert result.keySet().size() == 2
assert result.each { key, value -> value instanceof List }