2016-09-02 6 views
-1

私はMinecraftサーバー用の簡単な刑務所システムを実装しています。
刑務所はオブジェクトで、彼らは自分のID、内部のプレイヤーの数と場所を持っています。コールバックを使用するオブジェクトを作成するメソッド

新しい刑務所を作成する簡単な方法を作成したいと思います。

public static Jail createJail(final Location location); 

このメソッドは、自動的に(すべての非同期を実行します)私のDBhelperを使用してDBに新たに作成された刑務所を挿入して、何かが失敗した場合、代わりに刑務所オブジェクトのnullを返す必要があります。私の内部の匿名クラス内で何かを返すことができないので、コールバックと匿名クラスで簡単なCallBackインターフェイスを実装するのは当然の問題です。ここで

は、私がこれまで持っているものです。

/** 
* Create new Jail object, fill with values and register in List 
* @param id Unique id of Jail, usually got from DB 
* @param location Location of Jail 
*/ 
private Jail(final int id, final Location location) { 
    this.id = id; 
    this.location = location; 
    this.amountOfJailed = 0; 
    jails.add(id, this); 
} 

/** 
* Tries to create new Jail<br /> 
* New Jail will be auto-inserted into DB. 
* @param location Valid Bukkit Location 
* @return Jail if successfully created, null otherwise 
*/ 
public static Jail createJail(final Location location) { 
    if (location == null) { 
     Bukkit.getLogger().warning(Lang.PREFIX + " Tried to create new Jail with invalid location"); 
     return null; 
    } 

    final Jail newJail; 

    DatabaseQuery db = new DatabaseQuery(); 
    db.insertJail(location, new SimpleCallBack() { 
     @Override 
     public void onQueryDone(ResultSet result) { 
      if (result == null) { 
       newJail = null; 
      } else { 
       result.next(); 
       int usedId = result.getInt("id"); 
       newJail = new Jail(usedId, location); 
      } 
     } 
    }); 

    return newJail; 
} 

とのDatabaseQuery#insertJail

/** 
* Inserts Jail into DB<br /> 
* When any error happens, callBack will receive null ResultSet<br /> 
* When everything goes well, ResultSet will hold generated id 
* @param location Location of inserted Jail 
* @param callBack Class with 'onQueryDone' method to be executed 
*/ 
public void insertJail(final Location location, final SimpleCallBack callBack) { 
    new BukkitRunnable() { 
     @Override 
     public void run() { 
      ResultSet result = null; 
      try 
      { 
       Connection connection = hikari.getConnection(); 
       PreparedStatement statement = connection.prepareStatement("INSERT INTO p_jails (`location`) VALUES (?);"); 
       statement.setString(1, Serializer.location_serialize(location)); 
       statement.executeUpdate(); 
       result = statement.getGeneratedKeys(); 
      } catch (SQLException e) { 
       e.printStackTrace(); 
      } 
      final ResultSet fResult = result; 
      new BukkitRunnable() { 
       @Override 
       public void run() { 
        callBack.onQueryDone(fResult); 
       } 
      }.runTask(Main.coreapi); 
     } 
    }.runTaskAsynchronously(Main.coreapi); 
} 

は、どのように私は、メソッドcreateJailを実装することが出来るのですか?私はそれがDBに正常に挿入されたかどうかを知る必要があり、ResultSetから使用されたIDを取得する必要があるので、最終的にその刑務所オブジェクトを返し、 "ID###の新しい刑務所を作成しました"

+0

そのわずか非常にシンプルなインターフェース'void onQueryDone(ResultSet result);'メソッド –

+0

最初の 'BukkitRunnable'はそれをAsyncにするためです。その後、私は時にはBukkitのティックスレッドと呼ばれる同期スレッドにコールバックします。2つのメソッドに分割すると、 'createJail'メソッド内から' Jail'オブジェクトを返す必要があるので、助けになりません。ただし、DBに適切に保存されている場合に限ります。その分割は、1つのクエリから2つのクエリを作成するだけです。最初に無料のIDを取得し、DBに '刑務所 'を保存します。 –

答えて

0

は、私はこのスレッドでトップの答えからコードを借りてきたsql jdbc getgeneratedkeys returns column "id" not found, column type unknown

のための答えを参照してください。

result = statement.getGeneratedKeys();の後に、生成されたIDを結果セットから取得する必要はありません。コードを使用すると、SimpleCallBackクラスを自分で作成した場合は、「刑務所」のオブジェクトや、システム内のすべてのエンティティの共通のスーパークラスを渡すためにcallBack.onQueryDone(fResult);の署名を変更

int autoIncKeyFromApi = -1; 
rs = stmt.getGeneratedKeys(); 
if (rs.next()) { 
    autoIncKeyFromApi = rs.getInt(1); // "autoIncKeyFromApi" is th generated key 
    // Write the code to construct a Jail object here 
    Jail newJail = new Jail(); 
    newJail.setID(autoIncKeyFromApi); 
    // Set all other fields 
} else { 
    // Did not have a generated key either because no rows were inserted or yur query does not have a generated key column 
} 
System.out.println(autoIncKeyFromApi); 

のようになります。コールバックは 'callBack.onQueryDone(newJail);'のようになります。 。コールバックは主にパラメータで動作し、戻り値の型ではないことに注意してください。

+0

こんにちは、お返事ありがとうございます。この質問の問題は、DBから自動インクリメントIDを受け取るのではなく、そのIDを持つ作成済みのオブジェクトをラップメソッド内から返すことです。 –

+0

OK、申し訳ありません、回答を更新 –

+0

Jailオブジェクト自体をコールバックに渡したら、どうすれば 'createJail'メソッドから返すことができますか? DB問合せが正常に完了した場合にのみ戻されます。 –

1

コードにCompletableFutureを使用することを検討する必要があります。

public static CompletableFuture<Jail> createJail(final Location location) 

それは、後に使用可能になります刑務所オブジェクトのすぐCompletableFutureこのメソッドの戻り値を:あなたの方法は次のようにシグネチャを持つ必要があります。

CompletableFutureインスタンスを簡単に作成でき、簡単に値(成功)または例外(失敗)を設定できます。たとえば、データベースが操作を実行した後に、挿入されたjailインスタンスを設定します。このために、成功または失敗した場合に何かをするcompletable将来のコールバック(または複数)を追加し、メソッド次にcomplete()completeExceptionnaly()

のためのドキュメントを参照してくださいと

future.thenAccept(jail -> { /* do something */ }); 
future.exceptionnaly(exception -> { /* do something */ }); 
関連する問題