Это немного дерьмо Api - в конечном итоге вы пишете код котельной плиты.
Я считаю, что лучший способ - это обернуть классы и сделать так, чтобы избавление от соединения избавляло от другого.вещи (так как вы можете отслеживать, что делается на выходе из обернутых вызовов).
Пока у вас есть IDE, которая может генерировать делегирующие вам методы в классе, это тривиальная задача для переносаи тому подобное.
Я не осознавал, что нужно избавляться от всего лишнего, а просто заметил, что кто-то делает это здесь, однако мне повезло, поскольку мы уже завершили базовые классы, чтобы превратить все надоедливые исключения вRuntimeExceptions и для предоставления некоторых более высокоуровневых SQL-операций.
Я создал небольшой класс для отслеживания различных вещей:
public class CleanupList
{
private final ArrayList<AutoCloseable> _disposables;
public CleanupList()
{
_disposables = new ArrayList<>();
}
public void cleanup()
{
for(AutoCloseable closeable : _disposables){
//it sucks that they put an exception on this interface
//if anyone actually throws an exception in a close method then there's something seriously wrong going on
//they should have copied the c# more closely imo as it has nicer syntax aswell
try
{
closeable.close();
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
_disposables.clear();
}
public <T extends AutoCloseable> T track(T statement)
{
_disposables.add(statement);
return statement;
}
}
А затем, например, в Wrapped 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
}
Затем вы можете также передать тот же список в упакованные версии PreparedStatement/ Наборы результатов (которые я здесь не показывал) и т. Д. И используют их аналогичным образом.
Я не знаю, что используют другие люди, но в IDEA вы можете включить предупреждение для автоматического закрытиявещи, которые не находятся в блоке использования (или я должен сказать, попытка с ресурсами):
try(SomethingThatNeedsClosing somethingThatNeedsClosing = new SomethingThatNeedsClosing()){
//do stuff
}
Эти блоки использования позволяют вам окончательно автоматически закрываться и могут использоваться только с объектами AutoClosable.тип интерфейса
Я не знаю, почему это предупреждение не включено по умолчанию в IDEA, но все готово.