2016-05-02 2 views
0

У меня есть метод, называемый selectAll, который должен возвращать записи, выбранные из базы данных, но когда я хочу, чтобы вернуть их как строки не позволяет это и дает мне:Vert.x: извлечения записей из базы данных

Local variable S defined in an enclosing scope must be final or effectively final.

Я попытался добавить финал в свою строку, но он по-прежнему остается неизменным.

Вот мой selectAll() метод:

public String selectAll(String table, String order) { 
    String S; 
    S = ""; 
    this.getCnx().getConnection(res -> { 
    if (res.succeeded()) { 
     SQLConnection connection = res.result(); 
     connection.queryWithParams(ReqSql.SELECT_ALL, new JsonArray().add(table).add(order), (ar) -> { 
     if (ar.failed()) { 
      this.sendError(500, response); 
     } else { 
      JsonArray arr = new JsonArray(); 
      ar.result().getRows().forEach(arr::add); 
      S = ar.result().getRows().toString(); 
      response.putHeader("content-type", "application/json").end(arr.encode()); 
     } 
     }); 
    } 
    }); 
} 

public AsyncSQLClient getCnx(){ 
    JsonObject mySQLClientConfig = new JsonObject() 
      .put("host", "localhost") 
      .put("database", "test") 
      .put("username", "test") 
      .put("password", "test")      
      .put("port", 3306); 

    return MySQLClient.createShared(vertx, mySQLClientConfig); 
} 

И я создал еще один класс для моих запросов:

public class ReqSql { 
    public static final String SELECT_ALL = "SELECT * FROM ? ORDER BY ? ASC"; 
} 

С уважением.

ответ

0

Проблема в том, что вам нужно объявить локальные переменные как final, если вы хотите использовать их в выражении лямбда. Но вы не можете присвоить значение конечной переменной. Так что это не сработает:

final String S = ""; 

this.getCnx().getConnection(res -> { 
    //... 
    S = ar.result().getRows().toString(); 
    //... 
}); 

Vert.x очень асинхронный. Это означает, что большинство операций, таких как getConnection(), немедленно заражают возврат, но их результаты, в данном случае SQLConnection, будут доступны для Handler до более позднего момента времени.

Если вы попытаетесь сделать асинхронный результат доступным в основном потоке программы, который не сработает. То, что вы хотите делать с S, вероятно, неверно. Поэтому, если вам не понадобится S, я бы преобразовал S в локальную переменную.

Предлагаю вам прочитать о Future в documentation. A Future является заполнитель для результатов асинхронных вызовов. Vert.x полон асинхронных вызовов. С Future вы можете сделать что-то вроде этого:

Future<SQLConnection> connection = Future.future(); 
this.getCnx().getConnection(res -> { 
    if (res.succeeded()) { 
    logger.info("Got a connection."); 
    connection.complete(res.result()); 
    } else { 
    connection.fail(res.cause()); 
    } 
}); 

Вы указываете Handler на Future для получения асинхронного результата в гораздо более удобным для чтения образом, чем обратные вызовы/лямбды:

connection.setHandler(res -> { 
    ... 
}) 
Смежные вопросы