📄 jdbcxydataset.java
字号:
/* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* 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 Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ------------------
* JDBCXYDataset.java
* ------------------
* (C) Copyright 2002-2008, by Bryan Scott and Contributors.
*
* Original Author: Bryan Scott;
* Contributor(s): David Gilbert (for Object Refinery Limited);
* Eric Alexander;
*
*
* Changes
* -------
* 14-Mar-2002 : Version 1 contributed by Bryan Scott (DG);
* 19-Apr-2002 : Updated executeQuery, to close cursors and to improve support
* for types.
* 26-Apr-2002 : Renamed JdbcXYDataset to better fit in with the existing data
* source conventions.
* 26-Apr-2002 : Changed to extend AbstractDataset.
* 13-Aug-2002 : Updated Javadoc comments and imports (DG);
* 18-Sep-2002 : Updated to support BIGINT (BS);
* 21-Jan-2003 : Renamed JdbcXYDataset --> JDBCXYDataset (DG);
* 01-Jul-2003 : Added support to query whether a timeseries (BS);
* 30-Jul-2003 : Added empty contructor and executeQuery(connection,string)
* method (BS);
* 24-Sep-2003 : Added a check to ensure at least two valid columns are
* returned by the query in executeQuery as suggest in online
* forum by anonymous (BS);
* 02-Dec-2003 : Throwing exceptions allows to handle errors, removed default
* constructor, as without a connection, a query can never be
* executed.
* 16-Mar-2004 : Added check for null values (EA);
* 05-May-2004 : Now extends AbstractXYDataset (DG);
* 21-May-2004 : Implemented TableXYDataset, added support for SMALLINT and
* fixed bug in code that determines the min and max values (see
* bug id 938138) (DG);
* 15-Jul-2004 : Switched getX() with getXValue() and getY() with
* getYValue() (DG);
* 18-Nov-2004 : Updated for changes in RangeInfo interface (DG);
* 11-Jan-2005 : Removed deprecated code in preparation for the 1.0.0
* release (DG);
* ------------- JFREECHART 1.0.x ---------------------------------------------
* 17-Oct-2006 : Deprecated unused methods - see bug 1578293 (DG);
*
*/
package org.jfree.data.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Date;
import org.jfree.data.Range;
import org.jfree.data.RangeInfo;
import org.jfree.data.general.Dataset;
import org.jfree.data.xy.AbstractXYDataset;
import org.jfree.data.xy.TableXYDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.util.Log;
/**
* This class provides an {@link XYDataset} implementation over a database
* JDBC result set. The dataset is populated via a call to executeQuery with
* the string sql query. The sql query must return at least two columns.
* The first column will be the x-axis and remaining columns y-axis values.
* executeQuery can be called a number of times.
*
* The database connection is read-only and no write back facility exists.
*/
public class JDBCXYDataset extends AbstractXYDataset
implements XYDataset, TableXYDataset, RangeInfo {
/** The database connection. */
private transient Connection connection;
/** Column names. */
private String[] columnNames = {};
/** Rows. */
private ArrayList rows;
/** The maximum y value of the returned result set */
private double maxValue = 0.0;
/** The minimum y value of the returned result set */
private double minValue = 0.0;
/** Is this dataset a timeseries ? */
private boolean isTimeSeries = false;
/**
* Creates a new JDBCXYDataset (initially empty) with no database
* connection.
*/
private JDBCXYDataset() {
this.rows = new ArrayList();
}
/**
* Creates a new dataset (initially empty) and establishes a new database
* connection.
*
* @param url URL of the database connection.
* @param driverName the database driver class name.
* @param user the database user.
* @param password the database user's password.
*
* @throws ClassNotFoundException if the driver cannot be found.
* @throws SQLException if there is a problem connecting to the database.
*/
public JDBCXYDataset(String url,
String driverName,
String user,
String password)
throws SQLException, ClassNotFoundException {
this();
Class.forName(driverName);
this.connection = DriverManager.getConnection(url, user, password);
}
/**
* Creates a new dataset (initially empty) using the specified database
* connection.
*
* @param con the database connection.
*
* @throws SQLException if there is a problem connecting to the database.
*/
public JDBCXYDataset(Connection con) throws SQLException {
this();
this.connection = con;
}
/**
* Creates a new dataset using the specified database connection, and
* populates it using data obtained with the supplied query.
*
* @param con the connection.
* @param query the SQL query.
*
* @throws SQLException if there is a problem executing the query.
*/
public JDBCXYDataset(Connection con, String query) throws SQLException {
this(con);
executeQuery(query);
}
/**
* Returns <code>true</code> if the dataset represents time series data,
* and <code>false</code> otherwise.
*
* @return A boolean.
*/
public boolean isTimeSeries() {
return this.isTimeSeries;
}
/**
* Sets a flag that indicates whether or not the data represents a time
* series.
*
* @param timeSeries the new value of the flag.
*/
public void setTimeSeries(boolean timeSeries) {
this.isTimeSeries = timeSeries;
}
/**
* ExecuteQuery will attempt execute the query passed to it against the
* existing database connection. If no connection exists then no action
* is taken.
*
* The results from the query are extracted and cached locally, thus
* applying an upper limit on how many rows can be retrieved successfully.
*
* @param query the query to be executed.
*
* @throws SQLException if there is a problem executing the query.
*/
public void executeQuery(String query) throws SQLException {
executeQuery(this.connection, query);
}
/**
* ExecuteQuery will attempt execute the query passed to it against the
* provided database connection. If connection is null then no action is
* taken.
*
* The results from the query are extracted and cached locally, thus
* applying an upper limit on how many rows can be retrieved successfully.
*
* @param query the query to be executed.
* @param con the connection the query is to be executed against.
*
* @throws SQLException if there is a problem executing the query.
*/
public void executeQuery(Connection con, String query)
throws SQLException {
if (con == null) {
throw new SQLException(
"There is no database to execute the query."
);
}
ResultSet resultSet = null;
Statement statement = null;
try {
statement = con.createStatement();
resultSet = statement.executeQuery(query);
ResultSetMetaData metaData = resultSet.getMetaData();
int numberOfColumns = metaData.getColumnCount();
int numberOfValidColumns = 0;
int [] columnTypes = new int[numberOfColumns];
for (int column = 0; column < numberOfColumns; column++) {
try {
int type = metaData.getColumnType(column + 1);
switch (type) {
case Types.NUMERIC:
case Types.REAL:
case Types.INTEGER:
case Types.DOUBLE:
case Types.FLOAT:
case Types.DECIMAL:
case Types.BIT:
case Types.DATE:
case Types.TIME:
case Types.TIMESTAMP:
case Types.BIGINT:
case Types.SMALLINT:
++numberOfValidColumns;
columnTypes[column] = type;
break;
default:
Log.warn(
"Unable to load column "
+ column + " (" + type + ","
+ metaData.getColumnClassName(column + 1)
+ ")"
);
columnTypes[column] = Types.NULL;
break;
}
}
catch (SQLException e) {
columnTypes[column] = Types.NULL;
throw e;
}
}
if (numberOfValidColumns <= 1) {
throw new SQLException(
"Not enough valid columns where generated by query."
);
}
/// First column is X data
this.columnNames = new String[numberOfValidColumns - 1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -