數據庫元數據獲取工具

 

1.  簡介

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

郵箱:541931314@qq.comjava

有任何bug能夠直接發送郵件告知承諾會立刻進行修改,若是須要添加功能或者改進也但願告知,會及時進行改進。但願可以點贊(\(^o^)/~)git

 

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

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

若是,直接從數據庫裏面獲取數據庫元數據,至關複雜。數據庫

1.1. 設計目標

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

簡單,易用:數據庫之間的元數據相差很是大,且均不遵照SQL標準。因此,咱們把元數據進行了抽象。根據SQL標準及經常使用內容,組成了一個類樹。安全

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

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

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);

      }

}

 

在方法的開始位置會獲取一個鏈接,而後經過工廠建立一個實例。在方法的末尾關閉鏈接。整個過程都是無狀態的,因此是線程安全的。

相關文章
相關標籤/搜索