2014-09-02 51 views
0

我想在groovy中編寫一個DB util類,它需要一些強制性和可選的db參數,並將結果作爲映射列表返回。如何在groovy中編寫通用數據庫util類?

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:[email protected]] 
[POO_NAME:jdbcurl, POO_VALUE:[email protected]] 
[POO_NAME:dbType, POO_VALUE:[email protected]] 
[POO_NAME:ConnectionString, POO_VALUE:[email protected]] 

我怎樣才能把上面的輸出以下格式(地圖列表)?

[ "sql1": [ {row1}, {row2}... ], 
    "sql2": [ {row1}, {row2}... ], 
    ... 
] 

其中ROW1 ... = {列1:值1,列2:值2,欄3:值3 ...}

更新

下面裏面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 
    } 

它給出了一張地圖列表。

回答

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,並從地圖結果列表而不提取每個列名稱。


非相關的,但我想給這個類的建模的一些建議:

  1. 所有這些常量在類中聲明是不相關的,提供了程序代碼,更好地重構每個它進入了自己的階級。每個子類都可以處理每個數據庫的特殊性,雖然這個例子沒有顯示任何(我也不記得任何)。
  2. 工廠方法很酷,也可以進行驗證;
  3. 處理每種數據庫類型的枚舉;
  4. ​​可能會收到它應該執行的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 } 
+0

謝謝您的回答和+1對再保建議。此外,我需要返回類型的地圖列表'列表' – abi1964 2014-09-03 03:34:39

相關問題