Its a bit Api shit - ends up writing a load of boiler plate code.
I believe the best way is to wrap the classes and make the utilization of the connection dispose of different material (since you can keep track of what happens when you exit wrapped calls).
As long as you have an IDE that can generate delegation methods in a class, then this is a trivial task to port such things.
I didn’t understand that all the extra things needed to be disposed of, but I just noticed that someone is doing it here, but I’m lucky as we are already completing the base classes to turn all annoying exceptions into RuntimeExceptions and provide a higher level of SQL level.
I made a small class to track various bits of material:
public class CleanupList { private final ArrayList<AutoCloseable> _disposables; public CleanupList() { _disposables = new ArrayList<>(); } public void cleanup() { for(AutoCloseable closeable : _disposables){
And then, for example, in Wrapped Connection (something that wraps the database connection):
public class WrappedConnection implements AutoCloseable { private final CleanupList _cleanupList; private Connection _connection; public WrappedConnection(Connection connection) { _connection = connection; _cleanupList = new CleanupList(); } public void close() { try { _connection.close(); _cleanupList.cleanup(); } catch (SQLException e) { throw new RuntimeException(e); } } public PreparedStatement prepareStatement(String sql) { try { return trackForDisposal(_connection.prepareStatement(sql)); } catch (SQLException e) { throw new RuntimeException(e); } } private <T extends AutoCloseable> T trackForDisposal(T statement) { return _cleanupList.track(statement); } .... lots more methods }
Then you can also pass the same list to certified versions of the PreparedStatement / Result sets (which I did not show here), etc. and use it in a similar way.
I don’t know what other people use, but in IDEA you can enable a warning for automatically closed material that is not used in the block (or I should say try-with-resources):
try(SomethingThatNeedsClosing somethingThatNeedsClosing = new SomethingThatNeedsClosing()){ //do stuff }
Using these blocks, you finally close auto-close and can only use things that have the AutoClosable interface type
I do not know why this warning is not included by default in IDEA, but there you go.