2016-01-19 3 views
0

Переход от C# к Java и попытка очистки пучка утечек соединения в некотором коде.с использованием java анонимных функций для возврата значений

Для предотвращения утечек я сделал бы что-то вроде

public class DB{ 
    public interface StatementUser{ 
     public void useit(Statement cmd); 
    } 

    public static void UseCommand(StatementUser usingfunc){ 
     try(Connection cnn = new Connection(...)){ 
      cnn.open(); 
      try(Statement stmt = new Statement(cnn)){ 
       usingfunc(stmt); 
      } 
     } 
    } 

    static void main(string[] args){ 
     int affected = 0; 
     DB.useStatement((stmt) -> { 
      // THIS STATEMENT IS DISALLOWED 
      affected = ... select/update... whatever 
     }); 
     System.out.println("Records: " + affected); 
    } 
} 

Мне нравится этот делегат, потому что она обрабатывает очистку, но по-прежнему оставляет большую часть взаимодействия с данными для творчества разработчиков.

Получается, что присваивание affected считается доступом к переменной за пределами ее области действия и не допускается. Итак, теперь я немного рад, как выполнить аналогичную операцию на Java (я хочу поддерживать общее использование объекта соединения/оператора)

Все, что я придумал, просто делает его более уродливым , поэтому я подозреваю, что просто иду по совершенно тупиковой траектории.

Что такое Java-способ сделать что-то подобное? (Я понимаю, что это может выглядеть сильно отличается, чем я жду)

+0

Где именно недопустимый доступ к переменному? Этот подход выглядит хорошо. – Thilo

+1

Если вы имеете в виду назначение «affected», возможно, это должно быть возвращаемое значение лямбда (в отличие от «void», которое у вас есть сейчас). В противном случае вы можете использовать обновляемый контейнерный класс (например, AtomicInteger). – Thilo

+0

Обновляемый класс контейнера - это путь, который мне не нравился. У меня начинались видения кучки быстрых классов, которые были разбросаны по всему коду. Я не знал о существовавшем ранее «AtomicInteger», который также дает хороший интерфейс. –

ответ

3

Другим способ, чтобы написать этот код, как это:

package controllers; 

import java.sql.Connection; 
import java.sql.SQLException; 
import java.sql.Statement; 

public class DB { 

    public interface StatementUser<T> { 
     T run(Statement cmd); 
    } 

    public static <T> T runStatement(StatementUser<T> usingfunc) { 
     try(Connection cnn = getConnection()){ 
      try(Statement stmt = cnn.createStatement()){ 
       return usingfunc.run(stmt); 
      } 
     } catch(SQLException ex) { 
      throw new RuntimeException(ex); 
     } 
    } 

    private static Connection getConnection() throws SQLException { 
     return ...; // someway to acquire a connection 
    } 

    public static void main(String[] args) { 
     int affected = DB.runStatement(cmd -> { 
      // do something with the statement 
      return 10; 
     }); 
     System.out.println(affected); 
    } 
} 
+0

Когда я увидел это, я рукой ладони на лбу сказал: что-то настолько очевидно (в ретроспективе). Благодарю. BTW: Мне нравится обертка «SQLException», это приятный штрих. –

+0

Для людей, читающих это в будущем, подумайте о том, чтобы изменить его на 'runConnection', может быть (или нет) быть преимущества для контроля над созданием инструкции. –

+0

Я не понимаю синтаксис ' T' в определении runStatement. Не могли бы вы объяснить? –

Смежные вопросы