數據庫元數據獲取工具


 

1.  簡介

源碼地址:https://github.com/wukenaihe/db-meta

郵箱:541931314@qq.com

有任何bug可以直接發送郵件告知承諾會馬上進行修改,如果需要添加功能或者改進也希望告知,會及時進行改進。希望能夠點贊(\(^o^)/~)

 

數據庫的元數據庫獲取到現在為止並沒有太好用的開源框架,最有名氣的可能是schemacrawler。不過這個軟件實在是太大太大了,不僅包括元數據的獲取,還包括表、列等信息的顯示。同時它的性能存在巨大弊端,基本上oracle數據庫他就不太能用,會把oracle里面的許多臨時表、垃圾表等都一股腦兒拉出來,非常可怕。它的接口相對比較簡單,getDatabase只有這么一個獲取方法,如果你要獲取一張表,你也得用這個方法。

如果,不用開源框架,你可以選擇用jdbc標准DatabaseMeta接口。使用不方便,需要處理大量的SQLException同時,他也不能獲取觸發器、存儲過程、函數等定義內容。

如果,直接從數據庫里面獲取數據庫元數據,相當復雜。

1.1. 設計目標

  • l  簡單,易用
  • l  易用擴展
  • l  線程安全
  • l  高性能

簡單,易用:數據庫之間的元數據相差非常大,且均不遵守SQL標准。所以,我們把元數據進行了抽象。根據SQL標准及常用內容,組成了一個類樹。

易擴展:允許添加別的數據庫實現方式,允許方便的重寫現有方法。

高性能:輕量,能獲取小部分的元數據。

2.  例子

https://github.com/wukenaihe/db-meta-example

Maven

<repositories>

      <repository>

         <id>clojars</id>

         <name>Clojars repository</name>

         <url>https://clojars.org/repo</url>

      </repository>

</repositories>

<dependencies>
        <dependency>
            <groupId>org.clojars.xumh</groupId>
            <artifactId>db-meta</artifactId>
            <version>0.0.1-Release</version>
        </dependency>
<dependencies>

在中國很有可能下載不下來,可以用開源中國上面的maven。不過去缺少依賴logback,需要自己添加下。

<dependency>
  <groupId>com.cgs.dbMeta</groupId>
  <artifactId>db-meta</artifactId>
  <version>0.0.1-Release</version>
</dependency>

<dependency>
   <groupId>ch.qos.logback</groupId>
   <artifactId>logback-classic</artifactId>
   <version>1.0.9</version>
</dependency>

 

http://maven.oschina.net/index.html#nexus-search;quick~db-meta

如何使用maven,大家可以參照:http://maven.oschina.net/help.html

public static void main(String[] args) {

      MysqlDataSource datasource = new MysqlDataSource();

      datasource.setServerName("localhost");

      datasource.setPort(3306);

      datasource.setDatabaseName("dctest");

      datasource.setUser("root");

      datasource.setPassword("123456");  

      MetaLoader metaLoader=new MetaLoaderImpl(datasource);

      Set<String> tableNames=metaLoader.getTableNames();

      System.out.print("數據庫中擁有表:");

      System.out.println(tableNames);
     
      Table table=metaLoader.getTable("des");

      PrintUtils.printTable(table);

       Map<String, Procedure> procedures=metaLoader.getProcedures();

//    System.out.println(procedures);

    }

3.  程序結構

3.1. 元數據結構

 

  • Database:數據庫,擁有多個Schema
  • Schema:數據集,這個數據庫與SQL中的數據集略微不同(Oracle:schema,mySql:catalog,SqlServer:catalog.schema)。這是因為,不同數據庫對schema的解釋不同造成的。
  • Table:擁有列、主鍵、外鍵、約束、觸發器、索引和權限。
  • Column:名稱、注釋、是否為null、類型(java.sql.Types)、類型(數據庫類型名稱)、精度、小數位數、默認值。
  • 主鍵:主鍵名,列名(按照定義的順序)
  • 外鍵:外鍵引用關系、外鍵刪除規則、外鍵更新規則
  • 索引:名稱、唯一性、索引類型(JDBC定義)、頁數、定義和列名
  • 約束:名稱、約束類型、約束定義(如”D1 Is not null”)
  • 觸發器:名稱、所屬表、定義
  • 權限:授予者、被授予者、權限、是否有授予權限
  • 存儲過程:名稱、定義(大量信息被壓縮在定義中)
  • 函數:名稱、定義(大量信息被壓縮在定義中)

3.2. API

通過等級來進行控制,這樣能夠避免讀取不必要的信息而影響性能。

 

標准

驅動信息(JDBC

Yes  Yes  Yes 

數據庫信息

 Yes Yes   Yes

 Yes Yes  Yes 

主鍵

 Yes  Yes Yes 

約束

 No

Yes  Yes 

視圖(視為表)

  No

  No

Yes 

索引

  No

 Yes Yes 

外鍵

  No

Yes  Yes 

權限

  No

  No

 Yes

觸發器

  No

  No

Yes 

 Yse   Yes
Yes 

 

MetaLoader接口

方法

說明

Set<String> getTableNames()

獲取表名(當前Schema)

Table getTable(String tableName)

獲取表(標准級別)

Table getTable(String tableName,SchemaInfoLevel schemaLevel)

如上

Table getTable(String tableName,SchemaInfo schemaInfo)

獲取指定Schema下的,特定表

Set<SchemaInfo> getSchemaInfos()

獲取數據下的Schema信息

Schema getSchema()

獲取當前schema

Schema getSchema(SchemaInfo schemaInfo)

獲取指定的schema元數據

Set<String> getProcedureNames()

獲取當前schema存儲過程名稱

Procedure getProcedure(String procedureName)

獲取存儲過程

Map<String,Procedure> getProcedures()

獲取當前schema存儲過程集合

Set<String> getTriggerNames()

獲取當前schema觸發器名稱

Trigger getTrigger(String triggerName)

獲取指定的觸發器

Map<String, Trigger> getTriggers()

獲取當前schema觸發器集合

Set<String> getFunctionNames()

獲取當前函數名稱

Function getFunction(String name)

獲取指定的函數

Map<String, Function> getFunctions()

獲取當前schema函數集合

Database getDatabase()

獲取數據庫元數據(標准)

Database getDatabase(SchemaInfoLevel level)

獲取指定級別的數據庫元數據

 

4.  設計過程

不同的數據庫,獲取元數據的方式必然不同,從這一點來看,我們需要一個策略模式。策略模式也方便進行擴展。

數據庫決定之后,實際上也已經決定會使用哪個具體實現。所以,在程序中實現方式的建立將交由一個工程,根據數據庫類型自動建立。

我們的數據庫要求是線程安全的,所以要求不具有狀態,每一個方法都具有獲取連接、關閉連接等步驟,所以我們在這里使用了一個模板模式。MetaLoader的方法還是比較復雜的。所以,我們抽象除了一個MetaCrawler接口,進行細化,MetaLoader的方法實現可以通過MetaCrawler的組合實現。

部分實現,我們使用的是DatabaseMeta,任何數據庫都是一樣的。但是部分信息如觸發器、存儲過程、函數等信息,DatabaseMeta是獲取不到的,又要分開實現。所以,毫無疑問,我們這里也使用了模板模式。

 

JDBC的異常為SQLException異常,拋出的異常都必須接住,會讓代碼結構非常混亂。同時,在close的方法拋出的異常,通常交給開發人員是無法進行任何處理的。所以,我們選擇catch這類無法處理的異常,然后進行日志輸出。

4.1. 線程安全

public Procedure getProcedure(String procedureName) {

      Connection con = JDBCUtils.getConnection(dataSource);

      MetaCrawler metaCrawler=null;

      Procedure p;

      try{

         metaCrawler=factory.newInstance(con);

         p=metaCrawler.getProcedure(procedureName);

         return p;

      }catch(DataAccessException e){

         logger.debug(e.getMessage(),e);

         throw new DatabaseMetaGetMetaException("Get tables error!", e);

      }finally{

         JDBCUtils.closeConnection(con);

      }

}

 

在方法的開始位置會獲取一個連接,然后通過工廠創建一個實例。在方法的末尾關閉連接。整個過程都是無狀態的,所以是線程安全的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM