1. /* ===========================================================
  2. * JFreeChart : a free chart library for the Java(tm) platform
  3. * ===========================================================
  4. *
  5. * (C) Copyright 2000-2004, by Object Refinery Limited and Contributors.
  6. *
  7. * Project Info: http://www.jfree.org/jfreechart/index.html
  8. *
  9. * This library is free software; you can redistribute it and/or modify it under the terms
  10. * of the GNU Lesser General Public License as published by the Free Software Foundation;
  11. * either version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  14. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. * See the GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License along with this
  18. * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. *
  21. * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  22. * in the United States and other countries.]
  23. *
  24. * -------------------
  25. * JDBCPieDataset.java
  26. * -------------------
  27. * (C) Copyright 2002-2004, by Bryan Scott and Contributors.
  28. *
  29. * Original Author: Bryan Scott; Andy
  30. * Contributor(s): David Gilbert (for Object Refinery Limited);
  31. * Thomas Morgner;
  32. *
  33. * $ Id: $
  34. *
  35. * Changes
  36. * -------
  37. * 26-Apr-2002 : Creation based on JdbcXYDataSet, but extending DefaultPieDataset (BS);
  38. * 24-Jun-2002 : Removed unnecessary import and local variable (DG);
  39. * 13-Aug-2002 : Updated Javadoc comments and imports, removed default constructor (DG);
  40. * 18-Sep-2002 : Updated to support BIGINT (BS);
  41. * 21-Jan-2003 : Renamed JdbcPieDataset --> JDBCPieDataset (DG);
  42. * 03-Feb-2003 : Added Types.DECIMAL (see bug report 677814) (DG);
  43. * 05-Jun-2003 : Updated to support TIME, optimised executeQuery method (BS);
  44. * 30-Jul-2003 : Added empty contructor and executeQuery(connection,string) method (BS);
  45. * 02-Dec-2003 : Throwing exceptions allows to handle errors, removed default constructor,
  46. * as without a connection, a query can never be executed (TM);
  47. * 04-Dec-2003 : Added missing Javadocs (DG);
  48. */
  49. package org.jfree.data.jdbc;
  50. import java.sql.Connection;
  51. import java.sql.DriverManager;
  52. import java.sql.SQLException;
  53. import java.sql.Timestamp;
  54. import java.sql.Types;
  55. import java.sql.ResultSet;
  56. import java.sql.ResultSetMetaData;
  57. import java.sql.Statement;
  58. import org.jfree.data.general.DefaultPieDataset;
  59. import org.jfree.data.general.PieDataset;
  60. /**
  61. * A {@link PieDataset} that reads data from a database via JDBC.
  62. * <P>
  63. * A query should be supplied that returns data in two columns, the first containing
  64. * VARCHAR data, and the second containing numerical data. The data is cached in-memory
  65. * and can be refreshed at any time.
  66. *
  67. * @author Bryan Scott.
  68. */
  69. public class JDBCPieDataset extends DefaultPieDataset {
  70. /** The database connection. */
  71. private transient Connection connection;
  72. /**
  73. * Creates a new JDBCPieDataset and establishes a new database connection.
  74. *
  75. * @param url the URL of the database connection.
  76. * @param driverName the database driver class name.
  77. * @param user the database user.
  78. * @param password the database users password.
  79. *
  80. * @throws ClassNotFoundException if the driver cannot be found.
  81. * @throws SQLException if there is a problem obtaining a database connection.
  82. */
  83. public JDBCPieDataset(String url,
  84. String driverName,
  85. String user,
  86. String password)
  87. throws SQLException, ClassNotFoundException {
  88. Class.forName(driverName);
  89. this.connection = DriverManager.getConnection(url, user, password);
  90. }
  91. /**
  92. * Creates a new JDBCPieDataset using a pre-existing database connection.
  93. * <P>
  94. * The dataset is initially empty, since no query has been supplied yet.
  95. *
  96. * @param con the database connection.
  97. */
  98. public JDBCPieDataset(Connection con) {
  99. if (con == null) {
  100. throw new NullPointerException("A connection must be supplied.");
  101. }
  102. this.connection = con;
  103. }
  104. /**
  105. * Creates a new JDBCPieDataset using a pre-existing database connection.
  106. * <P>
  107. * The dataset is initialised with the supplied query.
  108. *
  109. * @param con the database connection.
  110. * @param query the database connection.
  111. *
  112. * @throws SQLException if there is a problem executing the query.
  113. */
  114. public JDBCPieDataset(Connection con, String query) throws SQLException {
  115. this(con);
  116. executeQuery(query);
  117. }
  118. /**
  119. * ExecuteQuery will attempt execute the query passed to it against the
  120. * existing database connection. If no connection exists then no action
  121. * is taken.
  122. * The results from the query are extracted and cached locally, thus
  123. * applying an upper limit on how many rows can be retrieved successfully.
  124. *
  125. * @param query the query to be executed.
  126. *
  127. * @throws SQLException if there is a problem executing the query.
  128. */
  129. public void executeQuery(String query) throws SQLException {
  130. executeQuery(this.connection, query);
  131. }
  132. /**
  133. * ExecuteQuery will attempt execute the query passed to it against the
  134. * existing database connection. If no connection exists then no action
  135. * is taken.
  136. * The results from the query are extracted and cached locally, thus
  137. * applying an upper limit on how many rows can be retrieved successfully.
  138. *
  139. * @param query the query to be executed
  140. * @param con the connection the query is to be executed against
  141. *
  142. * @throws SQLException if there is a problem executing the query.
  143. */
  144. public void executeQuery(Connection con, String query) throws SQLException {
  145. Statement statement = null;
  146. ResultSet resultSet = null;
  147. try {
  148. statement = con.createStatement();
  149. resultSet = statement.executeQuery(query);
  150. ResultSetMetaData metaData = resultSet.getMetaData();
  151. int columnCount = metaData.getColumnCount();
  152. if (columnCount != 2) {
  153. throw new SQLException(
  154. "Invalid sql generated. PieDataSet requires 2 columns only"
  155. );
  156. }
  157. int columnType = metaData.getColumnType(2);
  158. double value = Double.NaN;
  159. while (resultSet.next()) {
  160. Comparable key = resultSet.getString(1);
  161. switch (columnType) {
  162. case Types.NUMERIC:
  163. case Types.REAL:
  164. case Types.INTEGER:
  165. case Types.DOUBLE:
  166. case Types.FLOAT:
  167. case Types.DECIMAL:
  168. case Types.BIGINT:
  169. value = resultSet.getDouble(2);
  170. setValue(key, value);
  171. break;
  172. case Types.DATE:
  173. case Types.TIME:
  174. case Types.TIMESTAMP:
  175. Timestamp date = resultSet.getTimestamp(2);
  176. value = date.getTime();
  177. setValue(key, value);
  178. break;
  179. default:
  180. System.err.println("JDBCPieDataset - unknown data type");
  181. break;
  182. }
  183. }
  184. fireDatasetChanged();
  185. }
  186. finally {
  187. if (resultSet != null) {
  188. try {
  189. resultSet.close();
  190. }
  191. catch (Exception e) {
  192. System.err.println("JDBCPieDataset: swallowing exception.");
  193. }
  194. }
  195. if (statement != null) {
  196. try {
  197. statement.close();
  198. }
  199. catch (Exception e) {
  200. System.err.println("JDBCPieDataset: swallowing exception.");
  201. }
  202. }
  203. }
  204. }
  205. /**
  206. * Close the database connection
  207. */
  208. public void close() {
  209. try {
  210. this.connection.close();
  211. }
  212. catch (Exception e) {
  213. System.err.println("JdbcXYDataset: swallowing exception.");
  214. }
  215. }
  216. }