源碼地址:https://github.com/wukenaihe/db-metahtml
郵箱:541931314@qq.comjava
有任何bug能夠直接發送郵件告知承諾會立刻進行修改,若是須要添加功能或者改進也但願告知,會及時進行改進。但願可以點贊(\(^o^)/~)git
數據庫的元數據庫獲取到如今爲止並無太好用的開源框架,最有名氣的多是schemacrawler。不過這個軟件實在是太大太大了,不只包括元數據的獲取,還包括表、列等信息的顯示。同時它的性能存在巨大弊端,基本上oracle數據庫他就不太能用,會把oracle裏面的許多臨時表、垃圾表等都一古腦兒拉出來,很是可怕。它的接口相對比較簡單,getDatabase只有這麼一個獲取方法,若是你要獲取一張表,你也得用這個方法。github
若是,不用開源框架,你能夠選擇用jdbc標準DatabaseMeta接口。使用不方便,須要處理大量的SQLException同時,他也不能獲取觸發器、存儲過程、函數等定義內容。sql
若是,直接從數據庫裏面獲取數據庫元數據,至關複雜。數據庫
簡單,易用:數據庫之間的元數據相差很是大,且均不遵照SQL標準。因此,咱們把元數據進行了抽象。根據SQL標準及經常使用內容,組成了一個類樹。安全
易擴展:容許添加別的數據庫實現方式,容許方便的重寫現有方法。數據結構
高性能:輕量,能獲取小部分的元數據。oracle
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); }
經過等級來進行控制,這樣可以避免讀取沒必要要的信息而影響性能。
|
小 |
標準 |
大 |
驅動信息(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) |
獲取指定級別的數據庫元數據 |
不一樣的數據庫,獲取元數據的方式必然不一樣,從這一點來看,咱們須要一個策略模式。策略模式也方便進行擴展。
數據庫決定以後,實際上也已經決定會使用哪一個具體實現。因此,在程序中實現方式的創建將交由一個工程,根據數據庫類型自動創建。
咱們的數據庫要求是線程安全的,因此要求不具備狀態,每個方法都具備獲取鏈接、關閉鏈接等步驟,因此咱們在這裏使用了一個模板模式。MetaLoader的方法仍是比較複雜的。因此,咱們抽象除了一個MetaCrawler接口,進行細化,MetaLoader的方法實現能夠經過MetaCrawler的組合實現。
部分實現,咱們使用的是DatabaseMeta,任何數據庫都是同樣的。可是部分信息如觸發器、存儲過程、函數等信息,DatabaseMeta是獲取不到的,又要分開實現。因此,毫無疑問,咱們這裏也使用了模板模式。
JDBC的異常爲SQLException異常,拋出的異常都必須接住,會讓代碼結構很是混亂。同時,在close的方法拋出的異常,一般交給開發人員是沒法進行任何處理的。因此,咱們選擇catch這類沒法處理的異常,而後進行日誌輸出。
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); } }
在方法的開始位置會獲取一個鏈接,而後經過工廠建立一個實例。在方法的末尾關閉鏈接。整個過程都是無狀態的,因此是線程安全的。