MySQL Abfragen einfach asynchron im Hintergrund

Hier könnt ihr anderen Leuten helfen, indem ihr Anleitungen oder praktische Codesegmente zur Verfügung stellt.

Re: MySQL Abfragen einfach asynchron im Hintergrund

Beitragvon crysis992 » So 30. Nov 2014, 18:45

Irgendwie stell ich mich grade echt doof an das zu verstehn :(

Ich möchte aus dieser Tabelle ( http://puu.sh/dbDwu/351ba4d3df.png ) die Votes für einen Spieler auslesen, habe es nun wie folgt versucht:

Code: Alles auswählen
  1. sql.query("SELECT uuid,votes,nickname FROM network_player WHERE uuid = '"+ p.getUniqueId().toString() + "';", t -> System.out.println(t.getInt("votes")));


Klappt aber nicht, Eclipse sagt mir ich soll ein Try/Catch nutzen, setz ich da ein try/catch bekomm ich folgende fehlermeldung: http://puu.sh/dbCUZ/7deba66cd9.png


Wie lese ich nun die Anzahl der Votes aus? Und ist es möglich das ganze auch in eine Methode zu packen wie z.B
Code: Alles auswählen
  1. public int getVotes(Player p) {
  2. // Wie?
  3. }
Benutzeravatar
crysis992
 
Beiträge: 148
Registriert: So 16. Jun 2013, 11:48

Re: MySQL Abfragen einfach asynchron im Hintergrund

Beitragvon Jofkos » So 30. Nov 2014, 18:56

crysis992 hat geschrieben:
Code: Alles auswählen
  1. sql.query("SELECT uuid,votes,nickname FROM network_player WHERE uuid = '"+ p.getUniqueId().toString() + "';", t -> System.out.println(t.getInt("votes")));


Klappt aber nicht, Eclipse sagt mir ich soll ein Try/Catch nutzen, setz ich da ein try/catch bekomm ich folgende fehlermeldung: http://puu.sh/dbCUZ/7deba66cd9.png


Du müsstest noch ein Try-Catch Block da hin packen:
Code: Alles auswählen
  1.             sql.query("SELECT uuid,votes,nickname FROM network_player WHERE uuid = '"+ p.getUniqueId().toString() + "';", t -> {
  2.                try {
  3.                   System.out.println(t.getInt("votes"));
  4.                } catch (Exception e) {
  5.                   e.printStackTrace();
  6.                }
  7.             });
Was evlt mit einer Methoden-Referenz schöner aussieht:
Code: Alles auswählen
  1.    public void deineMethode(Player p) {
  2.       sql.query("SELECT uuid,votes,nickname FROM network_player WHERE uuid = '" + p.getUniqueId().toString() + "';", this::proceed);
  3.    }
  4.    public void proceed(ResultSet t) {
  5.       try {
  6.          System.out.println(t.getInt("votes"));
  7.       } catch (Exception e) {
  8.          e.printStackTrace();
  9.       }
  10.    }
crysis992 hat geschrieben:Wie lese ich nun die Anzahl der Votes aus? Und ist es möglich das ganze auch in eine Methode zu packen wie z.B
Code: Alles auswählen
  1. public int getVotes(Player p) {
  2. // Wie?
  3. }
Wenn du den Wert in einer Methode zurückgeben willst, musst du den Thread in der die Methode ausgeführt wird einfrieren, bist du eine Antwort vom Server erhältst.
Dafür ist ja genau der Consumer. Du erhälst den Rückgabewert über den Consumer dann, wenn der Server geantwortet hat, erst dann gibt es den Wert, also kannst du auch erst dann drauf reagieren -> Wenn du eine Methode mit Rückgabewert haben willst, dann musst du diese in einem Extra-Thread ausführen.
Jofkos

...........

..Bild
Benutzeravatar
Jofkos
 
Beiträge: 1537
Registriert: So 16. Jun 2013, 22:45

Re: MySQL Abfragen einfach asynchron im Hintergrund

Beitragvon leNic » So 30. Nov 2014, 19:07

Jofkos hat geschrieben:sql.query("*query*", t -> System.out.println(t.toString()));

Und wie kann ich z.B. einen String in dieser void Funktion returnen?:
Code: Alles auswählen
  1. public static String sqlQuery(String query){
  2.       sql.query(query, t -> System.out.println(t.toString()));
  3.    }
Benutzeravatar
leNic
 
Beiträge: 168
Registriert: Fr 6. Jun 2014, 18:23

Re: MySQL Abfragen einfach asynchron im Hintergrund

Beitragvon IK_Raptor » So 30. Nov 2014, 19:29

Du kannst in einer void-Methode keinen String returnen. So einfach ist das.
Der Consumer<ResultSet> ist dafür da, dass, sobald das ResultSet angekommen ist, bestimmte Code zeilen ausgeführt werden (z.B Stats ausgeben in Chat etc.).
Benutzeravatar
IK_Raptor
 
Beiträge: 609
Registriert: Mo 12. Aug 2013, 15:37

Re: MySQL Abfragen einfach asynchron im Hintergrund

Beitragvon crysis992 » So 30. Nov 2014, 19:30

Jofkos hat geschrieben:Du müsstest noch ein Try-Catch Block da hin packen:
Code: Alles auswählen
  1.             sql.query("SELECT uuid,votes,nickname FROM network_player WHERE uuid = '"+ p.getUniqueId().toString() + "';", t -> {
  2.                try {
  3.                   System.out.println(t.getInt("votes"));
  4.                } catch (Exception e) {
  5.                   e.printStackTrace();
  6.                }
  7.             });



Gut, hab ich nun mal so gemacht:
Code: Alles auswählen
  1.   @Override   
  2.   public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
  3.   {
  4.     if ((sender instanceof Player)) {
  5.       Player p = (Player)sender;
  6.       Runtime.getRuntime().gc();
  7.       p.sendMessage(UtilChat.pr + "Ram verbrauch: §a" + getUsedRam() + "§7/§a" + getMaxRam() + "§7MB");
  8.                  /// TEST CODE ////
  9.      AsyncMySQL sql = new AsyncMySQL("localhost", 3306, "global", "*****", "global");
  10.      sql.query("SELECT uuid,votes,nickname FROM network_player WHERE uuid = '"+ p.getUniqueId().toString() + "';", t -> {
  11.           try {
  12.              System.out.println(t.getInt("votes"));
  13.           } catch (Exception e) {
  14.              e.printStackTrace();
  15.           }
  16.        });
  17.            
  18.     }
  19.     return true;
  20.   }



Bekomme aber folgenden Fehler:

Code: Alles auswählen
  1. 30.11 19:28:51 [Server] WARN at java.lang.Thread.run(Thread.java:745)
  2. 30.11 19:28:51 [Server] WARN at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  3. 30.11 19:28:51 [Server] WARN at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  4. 30.11 19:28:51 [Server] WARN at crytec.core.mysql.AsyncMySQL$$Lambda$16/69048869.run(Unknown Source)
  5. 30.11 19:28:51 [Server] WARN at crytec.core.mysql.AsyncMySQL.lambda$3(AsyncMySQL.java:40)
  6. 30.11 19:28:51 [Server] WARN at hub.Commands.Memory$$Lambda$15/1423200913.accept(Unknown Source)
  7. 30.11 19:28:51 [Server] WARN at hub.Commands.Memory.lambda$0(Memory.java:30)
  8. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2813)
  9. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1105)
  10. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:794)
  11. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
  12. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
  13. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
  14. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
  15. 30.11 19:28:51 [Server] WARN java.sql.SQLException: Operation not allowed after ResultSet closed
Benutzeravatar
crysis992
 
Beiträge: 148
Registriert: So 16. Jun 2013, 11:48

Re: MySQL Abfragen einfach asynchron im Hintergrund

Beitragvon Jofkos » So 30. Nov 2014, 21:20

crysis992 hat geschrieben:
Jofkos hat geschrieben:Du müsstest noch ein Try-Catch Block da hin packen:
Code: Alles auswählen
  1.             sql.query("SELECT uuid,votes,nickname FROM network_player WHERE uuid = '"+ p.getUniqueId().toString() + "';", t -> {
  2.                try {
  3.                   System.out.println(t.getInt("votes"));
  4.                } catch (Exception e) {
  5.                   e.printStackTrace();
  6.                }
  7.             });



Gut, hab ich nun mal so gemacht:
Code: Alles auswählen
  1.   @Override   
  2.   public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
  3.   {
  4.     if ((sender instanceof Player)) {
  5.       Player p = (Player)sender;
  6.       Runtime.getRuntime().gc();
  7.       p.sendMessage(UtilChat.pr + "Ram verbrauch: §a" + getUsedRam() + "§7/§a" + getMaxRam() + "§7MB");
  8.                  /// TEST CODE ////
  9.      AsyncMySQL sql = new AsyncMySQL("localhost", 3306, "global", "*****", "global");
  10.      sql.query("SELECT uuid,votes,nickname FROM network_player WHERE uuid = '"+ p.getUniqueId().toString() + "';", t -> {
  11.           try {
  12.              System.out.println(t.getInt("votes"));
  13.           } catch (Exception e) {
  14.              e.printStackTrace();
  15.           }
  16.        });
  17.            
  18.     }
  19.     return true;
  20.   }



Bekomme aber folgenden Fehler:

Code: Alles auswählen
  1. 30.11 19:28:51 [Server] WARN at java.lang.Thread.run(Thread.java:745)
  2. 30.11 19:28:51 [Server] WARN at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  3. 30.11 19:28:51 [Server] WARN at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  4. 30.11 19:28:51 [Server] WARN at crytec.core.mysql.AsyncMySQL$$Lambda$16/69048869.run(Unknown Source)
  5. 30.11 19:28:51 [Server] WARN at crytec.core.mysql.AsyncMySQL.lambda$3(AsyncMySQL.java:40)
  6. 30.11 19:28:51 [Server] WARN at hub.Commands.Memory$$Lambda$15/1423200913.accept(Unknown Source)
  7. 30.11 19:28:51 [Server] WARN at hub.Commands.Memory.lambda$0(Memory.java:30)
  8. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2813)
  9. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1105)
  10. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:794)
  11. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
  12. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
  13. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
  14. 30.11 19:28:51 [Server] WARN at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
  15. 30.11 19:28:51 [Server] WARN java.sql.SQLException: Operation not allowed after ResultSet closed
Wenn man eine PreparedStatement closed, ist auch das ResultSet getclosed. Mein Fehler, habe es gefixt.
Ersetzte mal deine Klasse mit der neuen Version.
Zudem darf der Zeiger des ResultSets nicht vor dem Anfang sein, du musst, bevor du getInt machen kannst, next() ausführen.
Jofkos

...........

..Bild
Benutzeravatar
Jofkos
 
Beiträge: 1537
Registriert: So 16. Jun 2013, 22:45

Re: MySQL Abfragen einfach asynchron im Hintergrund

Beitragvon leNic » Mo 1. Dez 2014, 14:43

Was ist, wenn man den Inhalt des ResultSets weiterverwenden möchte?
Benutzeravatar
leNic
 
Beiträge: 168
Registriert: Fr 6. Jun 2014, 18:23

Re: MySQL Abfragen einfach asynchron im Hintergrund

Beitragvon IK_Raptor » Mo 1. Dez 2014, 15:22

Dann führst du den Code, der das ResultSet benötigt durch den Cosumer aus.
Benutzeravatar
IK_Raptor
 
Beiträge: 609
Registriert: Mo 12. Aug 2013, 15:37

Re: MySQL Abfragen einfach asynchron im Hintergrund

Beitragvon Jofkos » Mo 1. Dez 2014, 20:28

Update
  • Die im Consumer ausgeführten Aktionen werden nun im Main-Thread ausgeführt, da es sonst Probleme mit dem AsyncCatcher geben könnte.
Jofkos

...........

..Bild
Benutzeravatar
Jofkos
 
Beiträge: 1537
Registriert: So 16. Jun 2013, 22:45

Re: MySQL Abfragen einfach asynchron im Hintergrund

Beitragvon Twister_21 » Do 5. Feb 2015, 11:17

Hi, ich wollte es jetzt mal asynchron machen und hab diese Methode:

Code: Alles auswählen
  1.    public static void setMoney(String user, int money){
  2.       if(!MySQL_Money.hasAccount(user)) {
  3.          MySQL_Money.createAccount(user);
  4.       }
  5.       
  6.       try {
  7.       PreparedStatement pps = con.prepareStatement("UPDATE economy SET money = ? WHERE user = ?");
  8.       pps.setInt(1, money);
  9.       pps.setString(2, user);
  10.       executor.execute(() -> pps.executeUpdate());
  11.       pps.close();
  12.       }
  13.        catch(Exception e) {
  14.        e.printStackTrace();
  15.       }
  16.    }


Aber eclipse will um
Code: Alles auswählen
  1. executor.execute(() -> pps.executeUpdate());
ein try-catch haben und wenn ich eins drum setzt will eclipse wieder eins haben, das geht in einer Endlosschleife so.

Muss man den das bei BungeeCord anders machen? Da klappt es nicht ganz.

Das war mein Versuch das Geld mit einem Consumer zurückzugeben:

Code: Alles auswählen
  1.    public void getMoney(String user, Consumer<Integer> consumer) {
  2.                 int money = 0;
  3.                try {
  4.                PreparedStatement pps = con.prepareStatement("SELECT money FROM economy WHERE user = ?");
  5.                pps.setString(1, user);   
  6.                
  7.                ResultSet rs = pps.executeQuery();
  8.                 while(rs.next()) {
  9.                money = rs.getInt("money");
  10.                }
  11.                
  12.                executor.execute(() -> {
  13.                ProxyServer.getInstance().getScheduler().runAsync(plugin, () -> consumer.accept(money));
  14.                });
  15.                
  16.                pps.close();
  17.             }
  18.                catch(SQLException e) {
  19.                   e.printStackTrace();
  20.                }
  21.       
  22.    }



Ok, kann man das nicht auch so machen? So gehts auf jede Fall:
Code: Alles auswählen
  1.    public static void getMoney(String user, Consumer<Integer> consumer) {
  2.       new Thread(new Runnable() {
  3.          
  4.          @Override
  5.          public void run() {
  6.             int money = 0;
  7.             try {
  8.             PreparedStatement pps = con.prepareStatement("SELECT money FROM economy WHERE user = ?");
  9.             pps.setString(1, user);   
  10.             ResultSet rs = pps.executeQuery();
  11.              while(rs.next()) {
  12.             money = rs.getInt("money");
  13.             }
  14.              consumer.accept(money);
  15.          }
  16.             catch(SQLException e) {
  17.                e.printStackTrace();
  18.             }
  19.             
  20.          }
  21.       }).start();
  22.       
  23.    }
Mit freundlichen Grüßen
Twister21
Benutzeravatar
Twister_21
 
Beiträge: 652
Registriert: Mi 11. Jun 2014, 05:51
Wohnort: Deutschland

VorherigeNächste

Zurück zu Anleitungen

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste