Skip to content
This repository
Browse code

Add a db pool in a slightly elegant way without having to modify the …

…existing code base TOO much!:

Database pools required you to get a Connection object and then close it afterwards. LWC has 2000+ lines of database code. Modifying every instance of this is extremely (!!) time consuming and very inconvenient.

Instead of doing this we exploit the fact that in LWC's usecase, once a PreparedStatement or ResultSet is closed, everything above it is closed, e.g a close chain: ResultSet -> PreparedStatement -> Connection. This is done automatically by the new backing AutoClosingPreparedStatement and AutoClosingResultSet.

This however did require manually modifying anything that used raw Statement objects.

This means that this build truly is a "dev" build not an unreleased stable build. Care should be taken with this build.
  • Loading branch information...
commit cec9f858d42c34fd634723426293987963cd69ee 1 parent cf5b1c9
Tyler Blair authored November 18, 2012
3  build.xml
@@ -65,6 +65,9 @@
65 65
         <mkdir dir="${bin}/core/"/>
66 66
         <mkdir dir="${bin}/core/resources/"/>
67 67
 
  68
+        <!-- shade dbpool -->
  69
+        <unzip src="lib/dbpool-5.0.jar" dest="${bin}/core/" />
  70
+
68 71
         <!-- Timestamp, bitches -->
69 72
         <tstamp>
70 73
             <!-- Date format: MONTH DD YYYY e.g January 25, 2012 -->
BIN  lib/dbpool-5.0.jar
Binary file not shown
5  src/main/java/com/griefcraft/io/BackupManager.java
@@ -40,6 +40,7 @@
40 40
 
41 41
 import java.io.File;
42 42
 import java.io.IOException;
  43
+import java.sql.Connection;
43 44
 import java.sql.ResultSet;
44 45
 import java.sql.Statement;
45 46
 import java.text.SimpleDateFormat;
@@ -250,7 +251,8 @@ public void run() {
250 251
                         database.load();
251 252
 
252 253
                         // TODO separate stream logic to somewhere else :)
253  
-                        Statement resultStatement = database.getConnection().createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
  254
+                        Connection connection =  database.createConnection();
  255
+                        Statement resultStatement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
254 256
 
255 257
                         if (lwc.getPhysicalDatabase().getType() == Database.Type.MySQL) {
256 258
                             resultStatement.setFetchSize(Integer.MIN_VALUE);
@@ -324,6 +326,7 @@ public Void call() throws Exception {
324 326
                         // close the sql statements
325 327
                         result.close();
326 328
                         resultStatement.close();
  329
+                        connection.close();
327 330
 
328 331
                         // close the backup file
329 332
                         backup.close();
11  src/main/java/com/griefcraft/lwc/LWC.java
@@ -129,6 +129,7 @@
129 129
 import org.bukkit.plugin.Plugin;
130 130
 
131 131
 import java.io.IOException;
  132
+import java.sql.Connection;
132 133
 import java.sql.ResultSet;
133 134
 import java.sql.SQLException;
134 135
 import java.sql.Statement;
@@ -962,7 +963,8 @@ public int fastRemoveProtections(CommandSender sender, String where, boolean sho
962 963
         sender.sendMessage("Loading protections via STREAM mode");
963 964
 
964 965
         try {
965  
-            Statement resultStatement = physicalDatabase.getConnection().createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
  966
+            Connection connection = physicalDatabase.createConnection();
  967
+            Statement resultStatement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
966 968
 
967 969
             if (physicalDatabase.getType() == Database.Type.MySQL) {
968 970
                 resultStatement.setFetchSize(Integer.MIN_VALUE);
@@ -1007,6 +1009,7 @@ public int fastRemoveProtections(CommandSender sender, String where, boolean sho
1007 1009
             // Close the streaming statement
1008 1010
             result.close();
1009 1011
             resultStatement.close();
  1012
+            connection.close();
1010 1013
 
1011 1014
             // flush all of the queries
1012 1015
             fullRemoveProtections(sender, toRemove);
@@ -1039,7 +1042,8 @@ private void fullRemoveProtections(CommandSender sender, List<Integer> toRemove)
1039 1042
         String prefix = getPhysicalDatabase().getPrefix();
1040 1043
 
1041 1044
         // create the statement to use
1042  
-        Statement statement = getPhysicalDatabase().getConnection().createStatement();
  1045
+        Connection connection = getPhysicalDatabase().createConnection();
  1046
+        Statement statement = connection.createStatement();
1043 1047
 
1044 1048
         while (iter.hasNext()) {
1045 1049
             int protectionId = iter.next();
@@ -1063,6 +1067,7 @@ private void fullRemoveProtections(CommandSender sender, List<Integer> toRemove)
1063 1067
         }
1064 1068
 
1065 1069
         statement.close();
  1070
+        connection.close();
1066 1071
     }
1067 1072
 
1068 1073
     /**
@@ -1420,7 +1425,7 @@ public void load() {
1420 1425
 
1421 1426
             physicalDatabase.load();
1422 1427
 
1423  
-            log("Using database: " + StringUtil.capitalizeFirstLetter(physicalDatabase.getConnection().getMetaData().getDriverVersion()));
  1428
+            log("Using database: " + physicalDatabase.getType().toString());
1424 1429
         } catch (Exception e) {
1425 1430
             e.printStackTrace();
1426 1431
         }
6  src/main/java/com/griefcraft/migration/DatabaseMigrator.java
@@ -47,8 +47,6 @@
47 47
      */
48 48
     public boolean migrate(PhysDB fromDatabase, PhysDB toDatabase) {
49 49
         try {
50  
-            toDatabase.getConnection().setAutoCommit(false);
51  
-
52 50
             // some prelim data
53 51
             int startProtections = toDatabase.getProtectionCount();
54 52
             int protectionCount = fromDatabase.getProtectionCount();
@@ -63,7 +61,6 @@ public boolean migrate(PhysDB fromDatabase, PhysDB toDatabase) {
63 61
                     protection.saveNow();
64 62
                 }
65 63
 
66  
-                toDatabase.getConnection().commit();
67 64
                 if (expectedProtections != (protectionCount = fromDatabase.getProtectionCount())) {
68 65
                     logger.info("Weird, only " + protectionCount + " protections are in the database? Continuing...");
69 66
                 }
@@ -80,9 +77,6 @@ public boolean migrate(PhysDB fromDatabase, PhysDB toDatabase) {
80 77
                     history.sync();
81 78
                 }
82 79
             }
83  
-
84  
-            fromDatabase.getConnection().close();
85  
-            toDatabase.getConnection().setAutoCommit(true);
86 80
         } catch (Exception e) {
87 81
             e.printStackTrace();
88 82
             return false;
9  src/main/java/com/griefcraft/modules/admin/AdminCleanup.java
@@ -40,6 +40,7 @@
40 40
 import org.bukkit.command.CommandSender;
41 41
 import org.bukkit.scheduler.BukkitScheduler;
42 42
 
  43
+import java.sql.Connection;
43 44
 import java.sql.ResultSet;
44 45
 import java.sql.SQLException;
45 46
 import java.sql.Statement;
@@ -124,7 +125,8 @@ public void push(List<Integer> toRemove) throws SQLException {
124 125
             String prefix = lwc.getPhysicalDatabase().getPrefix();
125 126
 
126 127
             // create the statement to use
127  
-            Statement statement = lwc.getPhysicalDatabase().getConnection().createStatement();
  128
+            Connection connection = lwc.getPhysicalDatabase().createConnection();
  129
+            Statement statement = connection.createStatement();
128 130
 
129 131
             while (iter.hasNext()) {
130 132
                 int protectionId = iter.next();
@@ -147,6 +149,7 @@ public void push(List<Integer> toRemove) throws SQLException {
147 149
             }
148 150
 
149 151
             statement.close();
  152
+            connection.close();
150 153
         }
151 154
 
152 155
         public void run() {
@@ -173,7 +176,8 @@ public void run() {
173 176
                 database.connect();
174 177
                 database.load();
175 178
 
176  
-                Statement resultStatement = database.getConnection().createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
  179
+                Connection connection = database.createConnection();
  180
+                Statement resultStatement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
177 181
 
178 182
                 if (lwc.getPhysicalDatabase().getType() == Database.Type.MySQL) {
179 183
                     resultStatement.setFetchSize(Integer.MIN_VALUE);
@@ -240,6 +244,7 @@ public Void call() throws Exception {
240 244
                 // close the sql statements
241 245
                 result.close();
242 246
                 resultStatement.close();
  247
+                connection.close();
243 248
 
244 249
                 // flush all of the queries
245 250
                 push(toRemove);
14  src/main/java/com/griefcraft/modules/admin/AdminQuery.java
@@ -37,6 +37,7 @@
37 37
 import com.griefcraft.util.StringUtil;
38 38
 import org.bukkit.command.CommandSender;
39 39
 
  40
+import java.sql.Connection;
40 41
 import java.sql.ResultSet;
41 42
 import java.sql.SQLException;
42 43
 import java.sql.Statement;
@@ -68,14 +69,8 @@ public void onCommand(LWCCommandEvent event) {
68 69
         if (args[0].equals("query")) {
69 70
             String query = StringUtil.join(args, 1);
70 71
 
71  
-            try {
72  
-                Statement statement = lwc.getPhysicalDatabase().getConnection().createStatement();
73  
-                statement.executeUpdate(query);
74  
-                statement.close();
75  
-                sender.sendMessage(Colors.Green + "Done.");
76  
-            } catch (SQLException e) {
77  
-                sender.sendMessage(Colors.Red + "Err: " + e.getMessage());
78  
-            }
  72
+            lwc.getPhysicalDatabase().executeUpdateNoException(query);
  73
+            sender.sendMessage(Colors.Green + "Done.");
79 74
         }
80 75
 
81 76
         // Specific query, but the where statement is given
@@ -92,7 +87,8 @@ public void onCommand(LWCCommandEvent event) {
92 87
             // execute the query
93 88
             try {
94 89
                 PhysDB database = lwc.getPhysicalDatabase();
95  
-                Statement statement = database.getConnection().createStatement();
  90
+                Connection connection = database.createConnection();
  91
+                Statement statement = connection.createStatement();
96 92
 
97 93
                 // choose the statement
98 94
                 if (args[0].startsWith("update")) {
468  src/main/java/com/griefcraft/sql/AutoClosingPreparedStatement.java
... ...
@@ -0,0 +1,468 @@
  1
+/*
  2
+ * Copyright (c) 2011, 2012, Tyler Blair
  3
+ * All rights reserved.
  4
+ *
  5
+ * Redistribution and use in source and binary forms, with or without modification, are
  6
+ * permitted provided that the following conditions are met:
  7
+ *
  8
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
  9
+ *       conditions and the following disclaimer.
  10
+ *
  11
+ *    2. Redistributions in binary form must reproduce the above copyright notice, this list
  12
+ *       of conditions and the following disclaimer in the documentation and/or other materials
  13
+ *       provided with the distribution.
  14
+ *
  15
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
  16
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
  18
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  20
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  21
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  22
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  23
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24
+ *
  25
+ * The views and conclusions contained in the software and documentation are those of the
  26
+ * authors and contributors and should not be interpreted as representing official policies,
  27
+ * either expressed or implied, of anybody else.
  28
+ */
  29
+
  30
+package com.griefcraft.sql;
  31
+
  32
+import java.io.InputStream;
  33
+import java.io.Reader;
  34
+import java.math.BigDecimal;
  35
+import java.net.URL;
  36
+import java.sql.Array;
  37
+import java.sql.Blob;
  38
+import java.sql.Clob;
  39
+import java.sql.Connection;
  40
+import java.sql.Date;
  41
+import java.sql.NClob;
  42
+import java.sql.ParameterMetaData;
  43
+import java.sql.PreparedStatement;
  44
+import java.sql.Ref;
  45
+import java.sql.ResultSet;
  46
+import java.sql.ResultSetMetaData;
  47
+import java.sql.RowId;
  48
+import java.sql.SQLException;
  49
+import java.sql.SQLWarning;
  50
+import java.sql.SQLXML;
  51
+import java.sql.Time;
  52
+import java.sql.Timestamp;
  53
+import java.util.Calendar;
  54
+
  55
+/**
  56
+ * A prepared statement that will close the parent {@link Connection} object once it is closed
  57
+ */
  58
+public class AutoClosingPreparedStatement implements PreparedStatement {
  59
+
  60
+    /**
  61
+     * The connection this statement is bound to
  62
+     */
  63
+    private final Connection connection;
  64
+
  65
+    /**
  66
+     * The prepared statement that will be a single use
  67
+     */
  68
+    private final PreparedStatement statement;
  69
+
  70
+    public AutoClosingPreparedStatement(Connection connection, PreparedStatement statement) {
  71
+        this.connection = connection;
  72
+        this.statement = statement;
  73
+    }
  74
+
  75
+    public void close() throws SQLException {
  76
+        statement.close();
  77
+
  78
+        if (connection != null) {
  79
+            connection.close();
  80
+        }
  81
+    }
  82
+
  83
+    public int executeUpdate() throws SQLException {
  84
+        int ret = statement.executeUpdate();
  85
+        close();
  86
+        return ret;
  87
+    }
  88
+
  89
+    public ResultSet executeQuery() throws SQLException {
  90
+        return new AutoClosingResultSet(this, statement.executeQuery());
  91
+    }
  92
+
  93
+    public void setAsciiStream(int i, InputStream inputStream, int i2) throws SQLException {
  94
+        statement.setAsciiStream(i, inputStream, i2);
  95
+    }
  96
+
  97
+    public boolean isPoolable() throws SQLException {
  98
+        return statement.isPoolable();
  99
+    }
  100
+
  101
+    public void setURL(int i, URL url) throws SQLException {
  102
+        statement.setURL(i, url);
  103
+    }
  104
+
  105
+    public void setMaxFieldSize(int i) throws SQLException {
  106
+        statement.setMaxFieldSize(i);
  107
+    }
  108
+
  109
+    public boolean isClosed() throws SQLException {
  110
+        return statement.isClosed();
  111
+    }
  112
+
  113
+    public void setMaxRows(int i) throws SQLException {
  114
+        statement.setMaxRows(i);
  115
+    }
  116
+
  117
+    public void setBinaryStream(int i, InputStream inputStream, long l) throws SQLException {
  118
+        statement.setBinaryStream(i, inputStream, l);
  119
+    }
  120
+
  121
+    public void setFloat(int i, float v) throws SQLException {
  122
+        statement.setFloat(i, v);
  123
+    }
  124
+
  125
+    public void setBigDecimal(int i, BigDecimal bigDecimal) throws SQLException {
  126
+        statement.setBigDecimal(i, bigDecimal);
  127
+    }
  128
+
  129
+    public void setBinaryStream(int i, InputStream inputStream) throws SQLException {
  130
+        statement.setBinaryStream(i, inputStream);
  131
+    }
  132
+
  133
+    public void setBlob(int i, InputStream inputStream) throws SQLException {
  134
+        statement.setBlob(i, inputStream);
  135
+    }
  136
+
  137
+    public void setObject(int i, Object o, int i2, int i3) throws SQLException {
  138
+        statement.setObject(i, o, i2, i3);
  139
+    }
  140
+
  141
+    public boolean execute(String s, int i) throws SQLException {
  142
+        return statement.execute(s, i);
  143
+    }
  144
+
  145
+    public void setArray(int i, Array array) throws SQLException {
  146
+        statement.setArray(i, array);
  147
+    }
  148
+
  149
+    public int getResultSetType() throws SQLException {
  150
+        return statement.getResultSetType();
  151
+    }
  152
+
  153
+    public int getResultSetHoldability() throws SQLException {
  154
+        return statement.getResultSetHoldability();
  155
+    }
  156
+
  157
+    public void setShort(int i, short i2) throws SQLException {
  158
+        statement.setShort(i, i2);
  159
+    }
  160
+
  161
+    public void setAsciiStream(int i, InputStream inputStream) throws SQLException {
  162
+        statement.setAsciiStream(i, inputStream);
  163
+    }
  164
+
  165
+    public void setNull(int i, int i2, String s) throws SQLException {
  166
+        statement.setNull(i, i2, s);
  167
+    }
  168
+
  169
+    public void setUnicodeStream(int i, InputStream inputStream, int i2) throws SQLException {
  170
+        statement.setUnicodeStream(i, inputStream, i2);
  171
+    }
  172
+
  173
+    public int executeUpdate(String s) throws SQLException {
  174
+        return statement.executeUpdate(s);
  175
+    }
  176
+
  177
+    public void setCharacterStream(int i, Reader reader, long l) throws SQLException {
  178
+        statement.setCharacterStream(i, reader, l);
  179
+    }
  180
+
  181
+    public void setRef(int i, Ref ref) throws SQLException {
  182
+        statement.setRef(i, ref);
  183
+    }
  184
+
  185
+    public void setNCharacterStream(int i, Reader reader, long l) throws SQLException {
  186
+        statement.setNCharacterStream(i, reader, l);
  187
+    }
  188
+
  189
+    public void setDouble(int i, double v) throws SQLException {
  190
+        statement.setDouble(i, v);
  191
+    }
  192
+
  193
+    public void setClob(int i, Reader reader) throws SQLException {
  194
+        statement.setClob(i, reader);
  195
+    }
  196
+
  197
+    public void setNull(int i, int i2) throws SQLException {
  198
+        statement.setNull(i, i2);
  199
+    }
  200
+
  201
+    public void setBytes(int i, byte[] bytes) throws SQLException {
  202
+        statement.setBytes(i, bytes);
  203
+    }
  204
+
  205
+    public void setBinaryStream(int i, InputStream inputStream, int i2) throws SQLException {
  206
+        statement.setBinaryStream(i, inputStream, i2);
  207
+    }
  208
+
  209
+    public boolean execute(String s, int[] ints) throws SQLException {
  210
+        return statement.execute(s, ints);
  211
+    }
  212
+
  213
+    public SQLWarning getWarnings() throws SQLException {
  214
+        return statement.getWarnings();
  215
+    }
  216
+
  217
+    public void setDate(int i, Date date) throws SQLException {
  218
+        statement.setDate(i, date);
  219
+    }
  220
+
  221
+    public void setClob(int i, Reader reader, long l) throws SQLException {
  222
+        statement.setClob(i, reader, l);
  223
+    }
  224
+
  225
+    public void setDate(int i, Date date, Calendar calendar) throws SQLException {
  226
+        statement.setDate(i, date, calendar);
  227
+    }
  228
+
  229
+    public void setNClob(int i, Reader reader) throws SQLException {
  230
+        statement.setNClob(i, reader);
  231
+    }
  232
+
  233
+    public void clearParameters() throws SQLException {
  234
+        statement.clearParameters();
  235
+    }
  236
+
  237
+    public int getMaxRows() throws SQLException {
  238
+        return statement.getMaxRows();
  239
+    }
  240
+
  241
+    public int executeUpdate(String s, String[] strings) throws SQLException {
  242
+        return statement.executeUpdate(s, strings);
  243
+    }
  244
+
  245
+    public void setPoolable(boolean b) throws SQLException {
  246
+        statement.setPoolable(b);
  247
+    }
  248
+
  249
+    public void setTime(int i, Time time) throws SQLException {
  250
+        statement.setTime(i, time);
  251
+    }
  252
+
  253
+    public boolean execute(String s, String[] strings) throws SQLException {
  254
+        return statement.execute(s, strings);
  255
+    }
  256
+
  257
+    public int executeUpdate(String s, int[] ints) throws SQLException {
  258
+        return statement.executeUpdate(s, ints);
  259
+    }
  260
+
  261
+    public boolean execute() throws SQLException {
  262
+        return statement.execute();
  263
+    }
  264
+
  265
+    public void setTimestamp(int i, Timestamp timestamp, Calendar calendar) throws SQLException {
  266
+        statement.setTimestamp(i, timestamp, calendar);
  267
+    }
  268
+
  269
+    public int getQueryTimeout() throws SQLException {
  270
+        return statement.getQueryTimeout();
  271
+    }
  272
+
  273
+    public void setLong(int i, long l) throws SQLException {
  274
+        statement.setLong(i, l);
  275
+    }
  276
+
  277
+    public ParameterMetaData getParameterMetaData() throws SQLException {
  278
+        return statement.getParameterMetaData();
  279
+    }
  280
+
  281
+    public int[] executeBatch() throws SQLException {
  282
+        return statement.executeBatch();
  283
+    }
  284
+
  285
+    public <T> T unwrap(Class<T> tClass) throws SQLException {
  286
+        return statement.unwrap(tClass);
  287
+    }
  288
+
  289
+    public void setTime(int i, Time time, Calendar calendar) throws SQLException {
  290
+        statement.setTime(i, time, calendar);
  291
+    }
  292
+
  293
+    public void setClob(int i, Clob clob) throws SQLException {
  294
+        statement.setClob(i, clob);
  295
+    }
  296
+
  297
+    public void setBoolean(int i, boolean b) throws SQLException {
  298
+        statement.setBoolean(i, b);
  299
+    }
  300
+
  301
+    public void addBatch() throws SQLException {
  302
+        statement.addBatch();
  303
+    }
  304
+
  305
+    public void setSQLXML(int i, SQLXML sqlxml) throws SQLException {
  306
+        statement.setSQLXML(i, sqlxml);
  307
+    }
  308
+
  309
+    public void setTimestamp(int i, Timestamp timestamp) throws SQLException {
  310
+        statement.setTimestamp(i, timestamp);
  311
+    }
  312
+
  313
+    public int getFetchDirection() throws SQLException {
  314
+        return statement.getFetchDirection();
  315
+    }
  316
+
  317
+    public int getFetchSize() throws SQLException {
  318
+        return statement.getFetchSize();
  319
+    }
  320
+
  321
+    public void setBlob(int i, InputStream inputStream, long l) throws SQLException {
  322
+        statement.setBlob(i, inputStream, l);
  323
+    }
  324
+
  325
+    public void setString(int i, String s) throws SQLException {
  326
+        statement.setString(i, s);
  327
+    }
  328
+
  329
+    public ResultSetMetaData getMetaData() throws SQLException {
  330
+        return statement.getMetaData();
  331
+    }
  332
+
  333
+    public void setNString(int i, String s) throws SQLException {
  334
+        statement.setNString(i, s);
  335
+    }
  336
+
  337
+    public void setObject(int i, Object o) throws SQLException {
  338
+        statement.setObject(i, o);
  339
+    }
  340
+
  341
+    public void setCursorName(String s) throws SQLException {
  342
+        statement.setCursorName(s);
  343
+    }
  344
+
  345
+    public Connection getConnection() throws SQLException {
  346
+        return statement.getConnection();
  347
+    }
  348
+
  349
+    public void cancel() throws SQLException {
  350
+        statement.cancel();
  351
+    }
  352
+
  353
+    public void setFetchDirection(int i) throws SQLException {
  354
+        statement.setFetchDirection(i);
  355
+    }
  356
+
  357
+    public void setNClob(int i, Reader reader, long l) throws SQLException {
  358
+        statement.setNClob(i, reader, l);
  359
+    }
  360
+
  361
+    public void addBatch(String s) throws SQLException {
  362
+        statement.addBatch(s);
  363
+    }
  364
+
  365
+    public void clearBatch() throws SQLException {
  366
+        statement.clearBatch();
  367
+    }
  368
+
  369
+    public int getResultSetConcurrency() throws SQLException {
  370
+        return statement.getResultSetConcurrency();
  371
+    }
  372
+
  373
+    public void clearWarnings() throws SQLException {
  374
+        statement.clearWarnings();
  375
+    }
  376
+
  377
+    public void setObject(int i, Object o, int i2) throws SQLException {
  378
+        statement.setObject(i, o, i2);
  379
+    }
  380
+
  381
+    public int getMaxFieldSize() throws SQLException {
  382
+        return statement.getMaxFieldSize();
  383
+    }
  384
+
  385
+    public void setCharacterStream(int i, Reader reader, int i2) throws SQLException {
  386
+        statement.setCharacterStream(i, reader, i2);
  387
+    }
  388
+
  389
+    public void setEscapeProcessing(boolean b) throws SQLException {
  390
+        statement.setEscapeProcessing(b);
  391
+    }
  392
+
  393
+    public int getUpdateCount() throws SQLException {
  394
+        return statement.getUpdateCount();
  395
+    }
  396
+
  397
+    public void setAsciiStream(int i, InputStream inputStream, long l) throws SQLException {
  398
+        statement.setAsciiStream(i, inputStream, l);
  399
+    }
  400
+
  401
+    public void setNClob(int i, NClob nClob) throws SQLException {
  402
+        statement.setNClob(i, nClob);
  403
+    }
  404
+
  405
+    public boolean getMoreResults(int i) throws SQLException {
  406
+        return statement.getMoreResults(i);
  407
+    }
  408
+
  409
+    public void setFetchSize(int i) throws SQLException {
  410
+        statement.setFetchSize(i);
  411
+    }
  412
+
  413
+    public ResultSet executeQuery(String s) throws SQLException {
  414
+        return statement.executeQuery(s);
  415
+    }
  416
+
  417
+    public void setByte(int i, byte b) throws SQLException {
  418
+        statement.setByte(i, b);
  419
+    }
  420
+
  421
+    public ResultSet getGeneratedKeys() throws SQLException {
  422
+        return statement.getGeneratedKeys();
  423
+    }
  424
+
  425
+    public boolean getMoreResults() throws SQLException {
  426
+        return statement.getMoreResults();
  427
+    }
  428
+
  429
+    public void setBlob(int i, Blob blob) throws SQLException {
  430
+        statement.setBlob(i, blob);
  431
+    }
  432
+
  433
+    public boolean execute(String s) throws SQLException {
  434
+        return statement.execute(s);
  435
+    }
  436
+
  437
+    public boolean isWrapperFor(Class<?> aClass) throws SQLException {
  438
+        return statement.isWrapperFor(aClass);
  439
+    }
  440
+
  441
+    public void setCharacterStream(int i, Reader reader) throws SQLException {
  442
+        statement.setCharacterStream(i, reader);
  443
+    }
  444
+
  445
+    public void setNCharacterStream(int i, Reader reader) throws SQLException {
  446
+        statement.setNCharacterStream(i, reader);
  447
+    }
  448
+
  449
+    public void setInt(int i, int i2) throws SQLException {
  450
+        statement.setInt(i, i2);
  451
+    }
  452
+
  453
+    public void setRowId(int i, RowId rowId) throws SQLException {
  454
+        statement.setRowId(i, rowId);
  455
+    }
  456
+
  457
+    public int executeUpdate(String s, int i) throws SQLException {
  458
+        return statement.executeUpdate(s, i);
  459
+    }
  460
+
  461
+    public void setQueryTimeout(int i) throws SQLException {
  462
+        statement.setQueryTimeout(i);
  463
+    }
  464
+
  465
+    public ResultSet getResultSet() throws SQLException {
  466
+        return statement.getResultSet();
  467
+    }
  468
+}
805  src/main/java/com/griefcraft/sql/AutoClosingResultSet.java
... ...
@@ -0,0 +1,805 @@
  1
+package com.griefcraft.sql;
  2
+
  3
+import java.io.InputStream;
  4
+import java.io.Reader;
  5
+import java.math.BigDecimal;
  6
+import java.net.URL;
  7
+import java.sql.Array;
  8
+import java.sql.Blob;
  9
+import java.sql.Clob;
  10
+import java.sql.Date;
  11
+import java.sql.NClob;
  12
+import java.sql.PreparedStatement;
  13
+import java.sql.Ref;
  14
+import java.sql.ResultSet;
  15
+import java.sql.ResultSetMetaData;
  16
+import java.sql.RowId;
  17
+import java.sql.SQLException;
  18
+import java.sql.SQLWarning;
  19
+import java.sql.SQLXML;
  20
+import java.sql.Statement;
  21
+import java.sql.Time;
  22
+import java.sql.Timestamp;
  23
+import java.util.Calendar;
  24
+import java.util.Map;
  25
+
  26
+/**
  27
+ * A result set that will close the parent PreparedStatement and Connection
  28
+ */
  29
+public class AutoClosingResultSet implements ResultSet {
  30
+
  31
+    /**
  32
+     * The statement this result set belongs to
  33
+     */
  34
+    private final PreparedStatement statement;
  35
+
  36
+    /**
  37
+     * The {@link ResultSet} to proxy
  38
+     */
  39
+    private final ResultSet set;
  40
+
  41
+    public AutoClosingResultSet(PreparedStatement statement, ResultSet set) {
  42
+        this.statement = statement;
  43
+        this.set = set;
  44
+    }
  45
+
  46
+    public void close() throws SQLException {
  47
+        set.close();
  48
+
  49
+        if (statement != null) {
  50
+            statement.close();
  51
+        }
  52
+    }
  53
+
  54
+    public boolean next() throws SQLException {
  55
+        return set.next();
  56
+    }
  57
+
  58
+    public InputStream getAsciiStream(int i) throws SQLException {
  59
+        return set.getAsciiStream(i);
  60
+    }
  61
+
  62
+    public void updateFloat(String s, float v) throws SQLException {
  63
+        set.updateFloat(s, v);
  64
+    }
  65
+
  66
+    public long getLong(int i) throws SQLException {
  67
+        return set.getLong(i);
  68
+    }
  69
+
  70
+    public void updateClob(String s, Clob clob) throws SQLException {
  71
+        set.updateClob(s, clob);
  72
+    }
  73
+
  74
+    public Timestamp getTimestamp(String s, Calendar calendar) throws SQLException {
  75
+        return set.getTimestamp(s, calendar);
  76
+    }
  77
+
  78
+    public Clob getClob(int i) throws SQLException {
  79
+        return set.getClob(i);
  80
+    }
  81
+
  82
+    public void insertRow() throws SQLException {
  83
+        set.insertRow();
  84
+    }
  85
+
  86
+    public void moveToInsertRow() throws SQLException {
  87
+        set.moveToInsertRow();
  88
+    }
  89
+
  90
+    public void updateClob(String s, Reader reader, long l) throws SQLException {
  91
+        set.updateClob(s, reader, l);
  92
+    }
  93
+
  94
+    public boolean isBeforeFirst() throws SQLException {
  95
+        return set.isBeforeFirst();
  96
+    }
  97
+
  98
+    public void updateBlob(String s, InputStream inputStream) throws SQLException {
  99
+        set.updateBlob(s, inputStream);
  100
+    }
  101
+
  102
+    public Timestamp getTimestamp(int i, Calendar calendar) throws SQLException {
  103
+        return set.getTimestamp(i, calendar);
  104
+    }
  105
+
  106
+    public void updateBinaryStream(int i, InputStream inputStream) throws SQLException {
  107
+        set.updateBinaryStream(i, inputStream);
  108
+    }
  109
+
  110
+    public byte[] getBytes(String s) throws SQLException {
  111
+        return set.getBytes(s);
  112
+    }
  113
+
  114
+    public boolean isAfterLast() throws SQLException {
  115
+        return set.isAfterLast();
  116
+    }
  117
+
  118
+    public void updateDouble(String s, double v) throws SQLException {
  119
+        set.updateDouble(s, v);
  120
+    }
  121
+
  122
+    public void updateSQLXML(String s, SQLXML sqlxml) throws SQLException {
  123
+        set.updateSQLXML(s, sqlxml);
  124
+    }
  125
+
  126
+    public void updateBlob(int i, InputStream inputStream, long l) throws SQLException {
  127
+        set.updateBlob(i, inputStream, l);
  128
+    }
  129
+
  130
+    public Object getObject(int i, Map<String, Class<?>> stringClassMap) throws SQLException {
  131
+        return set.getObject(i, stringClassMap);
  132
+    }
  133
+
  134
+    public void setFetchDirection(int i) throws SQLException {
  135
+        set.setFetchDirection(i);
  136
+    }
  137
+
  138
+    public void updateAsciiStream(int i, InputStream inputStream) throws SQLException {
  139
+        set.updateAsciiStream(i, inputStream);
  140
+    }
  141
+
  142
+    public int getInt(String s) throws SQLException {
  143
+        return set.getInt(s);
  144
+    }
  145
+
  146
+    public float getFloat(int i) throws SQLException {
  147
+        return set.getFloat(i);
  148
+    }
  149
+
  150
+    public void updateInt(int i, int i2) throws SQLException {
  151
+        set.updateInt(i, i2);
  152
+    }
  153
+
  154
+    public void updateTime(String s, Time time) throws SQLException {
  155
+        set.updateTime(s, time);
  156
+    }
  157
+
  158
+    public int getConcurrency() throws SQLException {
  159
+        return set.getConcurrency();
  160
+    }
  161
+
  162
+    public Ref getRef(String s) throws SQLException {
  163
+        return set.getRef(s);
  164
+    }
  165
+
  166
+    public BigDecimal getBigDecimal(String s) throws SQLException {
  167
+        return set.getBigDecimal(s);
  168
+    }
  169
+
  170
+    public Object getObject(int i) throws SQLException {
  171
+        return set.getObject(i);
  172
+    }
  173
+
  174
+    public NClob getNClob(String s) throws SQLException {
  175
+        return set.getNClob(s);
  176
+    }
  177
+
  178
+    public void updateNString(int i, String s) throws SQLException {
  179
+        set.updateNString(i, s);
  180
+    }
  181
+
  182
+    public RowId getRowId(int i) throws SQLException {
  183
+        return set.getRowId(i);
  184
+    }
  185
+
  186
+    public Blob getBlob(int i) throws SQLException {
  187
+        return set.getBlob(i);
  188
+    }
  189
+
  190
+    public SQLWarning getWarnings() throws SQLException {
  191
+        return set.getWarnings();
  192
+    }
  193
+
  194
+    public void updateInt(String s, int i) throws SQLException {
  195
+        set.updateInt(s, i);
  196
+    }
  197
+
  198
+    public void updateNClob(int i, NClob nClob) throws SQLException {
  199
+        set.updateNClob(i, nClob);
  200
+    }
  201
+
  202
+    public Statement getStatement() throws SQLException {
  203
+        return set.getStatement();
  204
+    }
  205
+
  206
+    public Timestamp getTimestamp(String s) throws SQLException {
  207
+        return set.getTimestamp(s);
  208
+    }
  209
+
  210
+    public boolean isLast() throws SQLException {
  211
+        return set.isLast();
  212
+    }
  213
+
  214
+    public boolean rowUpdated() throws SQLException {
  215
+        return set.rowUpdated();
  216
+    }
  217
+
  218
+    public int getHoldability() throws SQLException {
  219
+        return set.getHoldability();
  220
+    }
  221
+
  222
+    public void updateRef(String s, Ref ref) throws SQLException {
  223
+        set.updateRef(s, ref);
  224
+    }
  225
+
  226
+    public void updateLong(String s, long l) throws SQLException {
  227
+        set.updateLong(s, l);
  228
+    }
  229
+
  230
+    public void updateBinaryStream(String s, InputStream inputStream) throws SQLException {
  231
+        set.updateBinaryStream(s, inputStream);
  232
+    }
  233
+
  234
+    public void deleteRow() throws SQLException {
  235
+        set.deleteRow();
  236
+    }
  237
+
  238
+    public void updateTimestamp(String s, Timestamp timestamp) throws SQLException {
  239
+        set.updateTimestamp(s, timestamp);
  240
+    }
  241
+
  242
+    public void updateNCharacterStream(int i, Reader reader, long l) throws SQLException {
  243
+        set.updateNCharacterStream(i, reader, l);
  244
+    }
  245
+
  246
+    public byte[] getBytes(int i) throws SQLException {
  247
+        return set.getBytes(i);
  248
+    }
  249
+
  250
+    public Time getTime(int i) throws SQLException {
  251
+        return set.getTime(i);
  252
+    }
  253
+
  254
+    public void updateSQLXML(int i, SQLXML sqlxml) throws SQLException {
  255
+        set.updateSQLXML(i, sqlxml);
  256
+    }
  257
+
  258
+    public void updateCharacterStream(String s, Reader reader, long l) throws SQLException {
  259
+        set.updateCharacterStream(s, reader, l);
  260
+    }
  261
+
  262
+    public Date getDate(int i) throws SQLException {
  263
+        return set.getDate(i);
  264
+    }
  265
+
  266
+    public void updateFloat(int i, float v) throws SQLException {
  267
+        set.updateFloat(i, v);
  268
+    }
  269
+
  270
+    public void updateBinaryStream(String s, InputStream inputStream, long l) throws SQLException {
  271
+        set.updateBinaryStream(s, inputStream, l);
  272
+    }
  273
+
  274
+    public InputStream getBinaryStream(String s) throws SQLException {
  275
+        return set.getBinaryStream(s);
  276
+    }
  277
+
  278
+    public String getString(String s) throws SQLException {
  279
+        return set.getString(s);
  280
+    }
  281
+
  282
+    public void updateBytes(int i, byte[] bytes) throws SQLException {
  283
+        set.updateBytes(i, bytes);
  284
+    }
  285
+
  286
+    public Time getTime(String s, Calendar calendar) throws SQLException {
  287
+        return set.getTime(s, calendar);
  288
+    }
  289
+
  290
+    public String getString(int i) throws SQLException {
  291
+        return set.getString(i);
  292
+    }
  293
+
  294
+    public Reader getNCharacterStream(int i) throws SQLException {
  295
+        return set.getNCharacterStream(i);
  296
+    }
  297
+
  298
+    public void updateDate(String s, Date date) throws SQLException {
  299
+        set.updateDate(s, date);
  300
+    }
  301
+
  302
+    public void updateLong(int i, long l) throws SQLException {
  303
+        set.updateLong(i, l);
  304
+    }
  305
+
  306
+    public void updateCharacterStream(String s, Reader reader) throws SQLException {
  307
+        set.updateCharacterStream(s, reader);
  308
+    }
  309
+
  310
+    public BigDecimal getBigDecimal(int i, int i2) throws SQLException {
  311
+        return set.getBigDecimal(i, i2);
  312
+    }
  313
+
  314
+    public Time getTime(int i, Calendar calendar) throws SQLException {
  315
+        return set.getTime(i, calendar);
  316
+    }
  317
+
  318
+    public void updateAsciiStream(String s, InputStream inputStream, long l) throws SQLException {
  319
+        set.updateAsciiStream(s, inputStream, l);
  320
+    }
  321
+
  322
+    public void updateTime(int i, Time time) throws SQLException {
  323
+        set.updateTime(i, time);
  324
+    }
  325
+