📄 jdbcdatasetschemareader.java
字号:
/*
* $Id: JDBCDataSetSchemaReader.java,v 1.1.2.2 2006/01/21 19:49:45 david_hall Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jdesktop.databuffer.io.schema;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jdesktop.databuffer.DataColumn;
import org.jdesktop.databuffer.DataRelation;
import org.jdesktop.databuffer.DataSet;
import org.jdesktop.databuffer.DataTable;
import org.jdesktop.databuffer.provider.sql.JDBCDataConnection;
import org.jdesktop.databuffer.provider.sql.SQLDataProvider;
/**
* An <CODE>JDBCDataSetSchemaReader</CODE> instantiates a {@link org.jdesktop.databuffer.DataSet} from
* a schema stored in an XML file; the schema is read from the JDBC metadata classes (see
* {@link java.sql.DatabaseMetaData} and {@link java.sql.ResultSetMetaData}), and the accuracy
* of the schema depends on the quality of the JDBC driver used.
* <P>Each instance of <CODE>JDBCDataSetSchemaReader</CODE> works against a single JDBCDataConnection
* connected to through a JDBC driver to a JDBC datasource (presumably a relational database).
* Once instantiated against that JDBCConnection, the reader
* methods (e.g. {@link #readDataSet()}) may be used to load the <CODE>DataSet</CODE>.
* <CODE>DataSetSchemaReader</CODE> classes do not load data, only the <CODE>DataSet</CODE> schema.
* Typical usage:
*
* <CODE>
* JDBCDataConnection jdbcConn = new JDBCDataConnection("org.apache.derby.jdbc.EmbeddedDriver", "jdbc:derby:testDB", "sa", "");
* JDBCDataSetSchemaReader reader = new JDBCDataSetSchemaReader(jdbcConn);
* DataSet dataSet = reader.readDataSet();
* </CODE>
*
* <P>You can also use the one-line methods in DataSetUtility, such as
* {@link org.jdesktop.databuffer.util.DataSetUtility#readDataSetFromJDBC(JDBCDataConnection)}.
*
* @author Adam Barclay
* @author Patrick Wright
*/
public class JDBCDataSetSchemaReader implements DataSetSchemaReader {
/** The JDBCDataConnection from which we read schema metadata. */
private JDBCDataConnection jdbcConn;
/** The catalog name from which we read schema data, if supplied, may be null. */
private String catalog;
/** The schema name from which we read schema data, if supplied, may be null. */
private String schema;
/**
* Instantiates a new <CODE>JDBCDataSetSchemaReader</CODE> for a JDBCDataConnection to a JDBC data source,
* presumably a relational database, using the default catalog and schema as understood by the JDBC driver (e.g. null).
* The data connection cannot be changed once the reader is instantiated. The connection
* will be opened as necessary to read the metadata, and returned to its orignal connection state after reading. As the JDBC
* connections are not necessarily thread-safe, calling classes should synchronize around the schema loading process.
* See class documentation for more details.
*
* @param jdbcConn A {@link org.jdesktop.databuffer.provider.sql.JDBCDataConnection}.
*/
public JDBCDataSetSchemaReader(JDBCDataConnection jdbcConn) {
this(jdbcConn, null, null);
}
/**
* Instantiates a new <CODE>JDBCDataSetSchemaReader</CODE>, for a JDBCDataConnection to a JDBC data source,
* presumably a relational database, for a given catalog and schema in that database.
* The data connection cannot be changed once the reader is instantiated. The connection
* will be opened as necessary to read the metadata, and returned to its orignal connection state after reading. As the JDBC
* connections are not necessarily thread-safe, calling classes should synchronize around the schema loading process.
* See class documentation for more details.
*
* @param catalog Name of the catalog to read the schema from. The meaning of "catalog" is RDBMS-dependent;
* consult the documentation for your data source and JDBC driver.
*
* @param schema Name of the schema to read the DataSet schema from. The meaning of "schema" is RDBMS-dependent;
* consult the documentation for your data source and JDBC driver.
*
* @param jdbcConn A {@link org.jdesktop.databuffer.provider.sql.JDBCDataConnection}.
*/
public JDBCDataSetSchemaReader(JDBCDataConnection jdbcConn, String catalog, String schema) {
this.jdbcConn = jdbcConn;
this.catalog = catalog;
this.schema = schema;
}
/**
* Instantiates a new {@link org.jdesktop.databuffer.DataSet} from the <CODE>JDBCDataConnection</CODE>
* specified in the constructor. If the schema contains multiple <CODE>DataTables</CODE>
* or <CODE>DataRelations</CODE>, all of them are loaded
* from the schema into the new <CODE>DataSet</CODE>. Relations are read for a table using the
* {@link java.sql.DatabaseMetaData#getImportedKeys(String catalog, String schema, String tableName)}. For a
* relational database, this would mean a foreign key constraint on the table. If such metadata does not exist
* for table relations, you will need to create them yourself after instantiating the <CODE>DataSet</CODE>.
* This method is probably not thread-safe for multiple threads accessing the same <CODE>JDBCDataConnection</CODE>
* and underlying <CODE>java.sql.Connection</CODE>.
*
* @return A new <CODE>DataSet</CODE> instantiated from the <CODE>JDBCDataConnection</CODE>
* specified for the implementing class, including all tables and relations in the schema.
*
* @throws org.jdesktop.databuffer.io.schema.SchemaReaderException If an error occurred while loading the schema.
*/
public DataSet readDataSet() throws SchemaReaderException {
boolean connectState = jdbcConn.isConnected();
if ( !connectState ) jdbcConn.setConnected(true);
DataSet dataSet = null;
try {
Connection conn = jdbcConn.getConnection();
DatabaseMetaData dbMetaData = conn.getMetaData();
String[] typeArray = {"TABLE"};
ResultSet tableResultSet = dbMetaData.getTables(null, null, "%", typeArray);
List<String> tables = DataSetIOUtility.extractColumn(tableResultSet, "TABLE_NAME");
tableResultSet.close();
String[] array = (String[])tables.toArray(new String[tables.size()]);
dataSet = readDataSet(array);
} catch (SchemaReaderException e) {
throw e;
} catch (Exception e) {
throw new SchemaReaderException("Could not read schemas to create DataSet", e);
} finally {
jdbcConn.setConnected(connectState);
}
return dataSet;
}
/**
* Instantiates a new {@link org.jdesktop.databuffer.DataSet} from the <CODE>JDBCDataConnection</CODE>
* specified in the constructor, for the tables and columns given in the <CODE>tableNames</CODE> parameter.
* from the schema into the new <CODE>DataSet</CODE>. Relations are read for a table using the
* {@link java.sql.DatabaseMetaData#getImportedKeys(String catalog, String schema, String tableName)}. For a
* relational database, this would mean a foreign key constraint on the table. If such metadata does not exist
* for table relations, you will need to create them yourself after instantiating the <CODE>DataSet</CODE>.
* This method is probably not thread-safe for multiple threads accessing the same <CODE>JDBCDataConnection</CODE>
* and underlying <CODE>java.sql.Connection</CODE>.
*
* @param tableNames One or more table names to load from the schema. Each name can be either a table, or a
* table and column, dot-separated. If no columns are specified, all columns in the table are
* read from the schema; if columns are listed, only those columns are loaded. <CODE>DataRelations</CODE>
* for those tables and columns loaded from the schema are also instantiated automatically through
* {@link #addRelations(org.jdesktop.databuffer.DataSet, String...)}.
*
* @return A new <CODE>DataSet</CODE> instantiated from the <CODE>JDBCDataConnection</CODE>
* specified for the implementing class, including only the tables and columns listed in the
* <CODE>tableNames</CODE> parameter.
*
* @throws org.jdesktop.databuffer.io.schema.SchemaReaderException If an error occurred while loading the schema.
*/
public DataSet readDataSet(String... tableNames) throws SchemaReaderException{
boolean connectState = jdbcConn.isConnected();
if ( !connectState ) jdbcConn.setConnected(true);
DataSet dataSet = new DataSet();
try {
addTables(dataSet, tableNames);
addRelations(dataSet, tableNames);
} catch (SchemaReaderException e) {
throw e;
} catch (Exception e) {
throw new SchemaReaderException("Could not read schemas to create DataTables", e);
} finally {
jdbcConn.setConnected(connectState);
}
return dataSet;
}
/**
* Appends one or more {@link org.jdesktop.databuffer.DataTable} to a {@link org.jdesktop.databuffer.DataSet}
* from the schema represented by this reader. If the table, by name, is found in the <CODE>DataSet</CODE>,
* the table is skipped; if you want to re-add a table (for example, to pick up changes in table structure),
* drop the table from the <CODE>DataSet</CODE> before calling this method.
*
* @return A <CODE>List</CODE> of the table names that were actually found. You can check this to
* verify that all tables requested were loaded.
*
* @param dataSet The <CODE>DataSet</CODE> to which to add the tables.
*
* @param tableNames One or more table names to load from the schema and add to the <CODE>DataSet</CODE>.
* Each name can be either a table, or a table and column, dot-separated.
* If no columns are specified, all columns in the table are read from the schema;
* if columns are listed, only those columns are loaded. <CODE>DataRelations</CODE>
* for those tables and columns are not loaded from the schema; to that end, use
* {@link #addRelations(DataSet, String...)}.
*
* @throws org.jdesktop.databuffer.io.schema.SchemaReaderException If an error occurred while loading the schema.
*/
public List<String> addTables(DataSet dataSet, String... tableNames) throws SchemaReaderException {
List<String> loadedTables = new ArrayList<String>(tableNames.length);
boolean connectState = jdbcConn.isConnected();
if ( !connectState ) jdbcConn.setConnected(true);
try {
Connection conn = jdbcConn.getConnection();
DatabaseMetaData dbMetaData = conn.getMetaData();
// Used to store the list of tables that are to be retrieved, along
// with the list of columns (or explictly null if all columns should
// be included)
Map<String, Set<String>> tables = new HashMap<String, Set<String>>(5);
for (String name : tableNames) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -