2016-05-02 17 views
0

I Methode selectAll genannt haben, die Datensätze aus der Datenbank ausgewählt zurückkehren, aber wenn ich sie als String zurückgeben möchten sie es nicht erlauben, und gibt mir:Vert.x: Abrufen von Datensätzen aus der Datenbank

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

Ich habe versucht, meinen String zu vervollständigen, aber es ist immer noch dasselbe.

Hier ist meine selectAll() Methode:

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); 
} 

Und ich erstellen eine andere Klasse für meine Anfragen:

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

Grüße.

Antwort

0

Problem ist, dass Sie lokale Variablen als final deklarieren müssen, wenn Sie sie in einem Lambda-Ausdruck verwenden möchten. Sie können einer endgültigen Variablen jedoch keinen Wert zuweisen. So funktioniert das nicht:

final String S = ""; 

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

Vert.x ist hoch asynchron. Das bedeutet, dass die meisten Operationen, wie getConnection(), die Rückkehr sofort infizieren werden, aber ihre Ergebnisse, in diesem Fall SQLConnection, werden für die Handler zu einem späteren Zeitpunkt verfügbar sein.

Wenn Sie versuchen, ein asynchrones Ergebnis im Hauptprogrammablauf zur Verfügung zu stellen, das nicht funktionieren würde. Was Sie mit S alles machen wollen ist wahrscheinlich falsch. Wenn Sie S danach nicht benötigen, würde ich S in eine lokale Variable umwandeln.

Ich schlage vor, Sie lesen über Future in der documentation. A Future ist ein Platzhalter für Ergebnisse asynchroner Aufrufe. Vert.x ist voll von asynchronen Aufrufen. Mit Future können Sie etwas tun:

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()); 
    } 
}); 

Sie einen Handler auf einem Future angeben zum Abrufen der asynchronen Ergebnis in einer viel lesbarer Weise als Rückrufe/Lambdas:

connection.setHandler(res -> { 
    ... 
}) 
Verwandte Themen