DatabaseMetaData類
DatabaseMetaData類是java.sql包中的類,利用它可以擷取我們連接配接到的資料庫的結構、存儲等很多資訊。如:
1、資料庫與使用者,資料庫辨別符以及函數與存儲過程。
2、資料庫限制。
3、資料庫支援不支援的功能。
4、架構、編目、表、列和視圖等。
通過調用DatabaseMetaData的各種方法,程式可以動态的了解一個資料庫。由于這個類中的方法非常的多那麼就介紹幾個常用的方法來給大家參考。
(1) DatabaseMetaData執行個體的擷取
Connection conn = DriverManager.getConnection(……);
DatabaseMetaData dbmd = Conn.getMetaData();
建立了這個執行個體,就可以使用它的方法來擷取資料庫得資訊。主要使用如下的方法:
(2) 獲得目前資料庫以及驅動的資訊
dbmd.getDatabaseProductName():用以獲得目前資料庫是什麼資料庫。比如oracle,access等。傳回的是字元串。
dbmd.getDatabaseProductVersion():獲得資料庫的版本。傳回的字元串。
dbmd.getDriverVersion():獲得驅動程式的版本。傳回字元串。
dbmd.getTypeInfo() :獲得目前資料庫的類型資訊
(3) 獲得目前資料庫中表的資訊
dbmd.getTables(String catalog,String schema,String tableName,String[] types),
這個方法帶有四個參數,它們表示的含義如下:
String catalog:要獲得表所在的編目。"“”"意味着沒有任何編目,Null表示所有編目。
String schema:要獲得表所在的模式。"“”"意味着沒有任何模式,Null表示所有模式。
String tableName:指出要傳回表名與該參數比對的那些表,
String types:一個指出傳回何種表的數組。
可能的數組項是:"TABLE"、"VIEW"、"SYSTEM TABLE", "GLOBAL TEMPORARY","LOCAL TEMPORARY","ALIAS","SYSNONYM"。
通過getTables()方法傳回的結果集中的每個表都有下面是10字段的描述資訊,而且隻有10個。通常我們用到的也就是标紅的幾個字段。而且在結果集中直接使用下面字段前面的序号即可擷取字段值。
1.TABLE_CAT (String) => 表所在的編目(可能為空)
2.TABLE_SCHEM (String) => 表所在的模式(可能為空)
3.TABLE_NAME (String) => 表的名稱
4.TABLE_TYPE (String) => 表的類型。
典型的有 "TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
5.REMARKS (String) => 解釋性的備注
6.TYPE_CAT (String) =>編目類型(may be null)
7.TYPE_SCHEM (String) => 模式類型(may be null)
8.TYPE_NAME (String) => 類型名稱(may be null)
9.SELF_REFERENCING_COL_NAME (String) => name of the designated "identifier" column of a typed table (may be null)
10.REF_GENERATION (String) => specifies how values in SELF_REFERENCING_COL_NAME are created.
它的值有:"SYSTEM"、"USER"、"DERIVED",也可能為空。
(4)獲得某個表的列資訊
dbmd.getColumns(String catalog,String schama,String tablename,String columnPattern,
通過getColumns()方法傳回的結果集中的每一列都有下面是23個字段段的描述資訊,而且隻有23個。通常我們用到的也就是标紅的字段。而且在結果集中直接使用下面字段前面的序号即可擷取字段值。
1.TABLE_CAT String => table catalog (may be null)
2.TABLE_SCHEM String => table schema (may be null)
3.TABLE_NAME String => table name (表名稱)
4.COLUMN_NAME String => column name(列名)
5.DATA_TYPE int => SQL type from java.sql.Types(列的資料類型)
6.TYPE_NAME String => Data source dependent type name, for a UDT the type name is fully qualified
7.COLUMN_SIZE int => column size.
8.BUFFER_LENGTH is not used.
9.DECIMAL_DIGITS int => the number of fractional digits. Null is returned for data types where DECIMAL_DIGITS is not applicable.
10.NUM_PREC_RADIX int => Radix (typically either 10 or 2)
11.NULLABLE int => is NULL allowed.
12.REMARKS String => comment describing column (may be null)
13.COLUMN_DEF String => default value for the column, (may be null)
14.SQL_DATA_TYPE int => unused
15.SQL_DATETIME_SUB int => unused
16.CHAR_OCTET_LENGTH int => for char types the maximum number of bytes in the column
17.ORDINAL_POSITION int => index of column in table (starting at 1)
18.IS_NULLABLE String => ISO rules are used to determine the nullability for a column.
19.SCOPE_CATLOG String => catalog of table that is the scope of a reference attribute (null if DATA_TYPE isn't REF)
20.SCOPE_SCHEMA String => schema of table that is the scope of a reference attribute (null if the DATA_TYPE isn't REF)
21.SCOPE_TABLE String => table name that this the scope of a reference attribure (null if the DATA_TYPE isn't REF)
22.SOURCE_DATA_TYPE short => source type of a distinct type or user-generated Ref type, SQL type from java.sql.Types
23.IS_AUTOINCREMENT String => Indicates whether this column is auto incremented
(5)獲得表的關鍵字資訊
dbmd.getPrimaryKeys(String catalog, String schema, String table),
通過getPrimaryKeys方法傳回的結果集中的每一列都有下面是6個字段段的描述資訊,而且隻有6個。通常我們用到的也就是标紅的字段。而且在結果集中直接使用下面字段前面的序号即可擷取字段值。
1.TABLE_CAT String => table catalog (may be null)
2.TABLE_SCHEM String => table schema (may be null)
3.TABLE_NAME String => table name
4.COLUMN_NAME String => column name
5.KEY_SEQ short => sequence number within primary key
6.PK_NAME String => primary key name (may be null)
這兩個方法中的參數的含義和上面的介紹的是相同的。凡是pattern的都是可以用通配符比對的。getColums()傳回的是結果集,這個結果集包括了列的所有資訊,類型,名稱,可否為空等。getPrimaryKey()則是傳回了某個表的關鍵字的結果集。
(6)擷取指定表的外鍵資訊
dbmd.getExportedKeys(String catalog, String schema, String table)
通過getPrimaryKeys方法傳回的結果集中的每一列都有下面是11個字段段的描述資訊,而且隻有11個。通常我們用到的也就是标紅的字段。而且在結果集中直接使用下面字段前面的序号即可擷取字段值。
1.PKTABLE_CAT String => primary key table catalog (may be null)
2.PKTABLE_SCHEM String => primary key table schema (may be null)
3.PKTABLE_NAME String => primary key table name
4.PKCOLUMN_NAME String => primary key column name
5.FKTABLE_CAT String => foreign key table catalog (may be null) being exported (may be null)
6.FKTABLE_SCHEM String => foreign key table schema (may be null) being exported (may be null)
7.FKTABLE_NAME String => foreign key table name being exported
8.FKCOLUMN_NAME String => foreign key column name being exported
9.KEY_SEQ short => sequence number within foreign key
10.UPDATE_RULE short => What happens to foreign key when primary is updated:
11.DELETE_RULE short => What happens to the foreign key when primary is deleted.
(7)反向設計表
通過getTables(),getColumns(),getPrimaryKeys()就可以完成表的反向設計了。主要步驟如下:
1、通過getTables()獲得資料庫中表的資訊。
2、對于每個表使用,getColumns(),getPrimaryKeys()獲得相應的列名,類型,限制條件,關鍵字等。
3、通過1,2獲得資訊可以生成相應的建表的SQL語句。
通過上述三步完成反向設計表的過程。
(8)代碼示例
下面我做了一個将DataBaseMetaData與Dom4j相結合的例子來實作資料庫中的表轉換成xml檔案,代碼已認證測試
首先借助jdk 6.x自帶的的Derby資料庫建立一個名為DerByDB的資料庫
package com.bjsxt.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JavaDBTest {
public static void main(String[] args) {
try {
// load the driver
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
System.out.println("Load the driver");
Connection conn = null;
Properties props = new Properties();
props.put("user", "user1"); props.put("password", "user1");
//create and connect the database named helloDB
conn=DriverManager.getConnection("jdbc:derby:DerByDB;create=true", props);
System.out.println("create and connect to DerByDB");
conn.setAutoCommit(false);
//建立一個學生表(student),并插入兩條記錄
Statement sm = conn.createStatement();
sm.execute("create table student(name varchar(40) primary key, score int)");
System.out.println("Created table student");
sm.execute("insert into student values('jack', 86)");
sm.execute("insert into student values('kice', 92)");
//建立一個教師表(teacher),并插入兩條記錄
sm.execute("create table teacher(name varchar(40), age int)");
System.out.println("Created table teacher");
sm.execute("insert into teacher values('wang li', 47)");
sm.execute("insert into teacher values('liu hua', 52)");
// list the two records from student
ResultSet rs1 = sm.executeQuery("SELECT name, score FROM student ORDER BY score");
System.out.println("==============");
System.out.println("name\tscore");
while(rs1.next()) {
StringBuilder builder = new StringBuilder(rs1.getString(1));
builder.append("\t");
builder.append(rs1.getInt(2));
System.out.println(builder.toString());
}
rs1.close();
// list the two records from teacher
ResultSet rs2 = sm.executeQuery("SELECT name, age FROM teacher ORDER BY age");
System.out.println("==============");
System.out.println("name\tage");
while(rs2.next()) {
StringBuilder builder = new StringBuilder(rs2.getString(1));
builder.append("\t");
builder.append(rs2.getInt(2));
System.out.println(builder.toString());
}
System.out.println("==============");
rs2.close();
sm.close();
System.out.println("Closed resultset and statement");
conn.commit();
conn.close();
System.out.println("Committed transaction and closed connection");
try { // perform a clean shutdown
DriverManager.getConnection("jdbc:derby:;shutdown=true");
} catch (SQLException se) {
System.out.println("Database shut down normally");
}
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("SimpleApp finished");
}
}
然後利用DataBaseMetaData與Dom4j 實作Derby資料庫中的表轉換成xml檔案,代碼如下:
package com.bjsxt.jdbc;
import java.io.File;
import java.io.FileWriter;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
public class DatabaseMetaDataTest {
public static void main(String[] args) throws Exception {
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
System.out.println("Load the driver");
Connection conn = null;
Properties props = new Properties();
props.put("user", "user1"); props.put("password", "user1");
conn=DriverManager.getConnection("jdbc:derby:DerByDB;create=false", props);
System.out.println("connect to DerByDB");
DatabaseMetaData dbmd = conn.getMetaData();
System.out.println("====getTables()方法====");
ResultSet rs1 = dbmd.getTables(null, null, "STUDENT", new String[]{"TABLE"});
while(rs1.next()) { //其實結果集中隻有一項,那就是TEACHER這個表。
String tname=rs1.getString(3); //擷取表名
String ttype=rs1.getString(4); //擷取表類型
Document document = DocumentHelper.createDocument(); //建立document對象
Element databaseElement = document.addElement("database");
Element stuElement=databaseElement.addElement(tname);
stuElement.addAttribute("表類型",ttype);
try{
OutputFormat opf=OutputFormat.createPrettyPrint(); //美化格式
//解決中文亂碼問題,在生成的xml文檔聲明中可以看到設定的編碼。
opf.setEncoding("gbk");
// 将document中的内容寫入檔案中
XMLWriter writer = new XMLWriter(new FileWriter(new File("student.xml")),opf);
writer.write(document);
writer.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
System.out.println("getTables is over");
System.out.println("====getColumns()方法====");
//最後一個null表示取出所有的列
ResultSet rs2 = dbmd.getColumns(null, null, "STUDENT", null);
while(rs2.next()) {
String colName=rs2.getString(4); //列名稱
int dataType = rs2.getInt("DATA_TYPE"); //資料類型
String dt=null;
if(dataType==Types.VARCHAR) {
dt="varchar";
}else if (dataType==Types.INTEGER) {
dt="int";
}
try {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("student.xml");
Node node = document.selectSingleNode("//STUDENT");
Element studentElement = (Element)node;
studentElement.addElement(colName).setText(dt);
//美化格式,此時的xml文檔多行書寫
OutputFormat opf=OutputFormat.createPrettyPrint();
//解決中文亂碼問題,在生成的xml文檔聲明中可以看到設定的編碼。
opf.setEncoding("gbk");
//将document中的内容寫入檔案中
XMLWriter writer = new XMLWriter(new FileWriter("student.xml"),opf);
writer.write(document);
writer.close();
}catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("getColumns is over");
System.out.println("====getPrimaryKeys()方法====");
ResultSet rs3 =dbmd.getPrimaryKeys(null, null, "STUDENT");
while(rs3.next()) {
String pname=rs3.getString(4); //列名稱
System.out.println(pname);
try {
SAXReader saxReader = new SAXReader();
Document document = saxReader.read("student.xml");
List<Node> list = document.selectNodes("//STUDENT");
Iterator<Node> iter=list.iterator();
while(iter.hasNext()){
Element studentElement = (Element)iter.next();
studentElement.addAttribute("primary", pname);
}
// Node node = document.selectSingleNode("//STUDENT");
// Element studentElement = (Element)node;
// studentElement.addAttribute("primary", pname);
// Node node = document.selectSingleNode("//STUDENT/@表類型");
// Attribute stype = (Attribute)node;
// stype.setValue("table");
// Element studentElement = (Element)node;
//美化格式,此時的xml文檔多行書寫
OutputFormat opf=OutputFormat.createPrettyPrint();
//解決中文亂碼問題,在生成的xml文檔聲明中可以看到設定的編碼。
opf.setEncoding("gbk");
//将document中的内容寫入檔案中
XMLWriter writer = new XMLWriter(new FileWriter("student.xml"),opf);
writer.write(document);
writer.close();
}catch (Exception e) {
e.printStackTrace();
}
}
rs1.close();
rs2.close();
rs3.close();
conn.close();
try {
DriverManager.getConnection("jdbc:derby:;shutdown=true");
} catch (SQLException se) {
System.out.println("Database shut down normally");
}
}
}