-2

MySql DB に保存されている整数を Java の整数に変換したいと考えています。PlayerName と Level を含むテーブルがあります。特定のプレイヤーからレベル (整数) を取得したいと思います。そして、それに整数の「値」を追加します。その後、DBに戻します。今までの私のコードは次のとおりです。

public void addinputPData(String loc, int value, Player player, String playername){
    //add input Player Data
    try{
        logm("Putting Kill Death Int Data into  " +player.getName() + "'s Profile!");
        Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/WebCom", "root", "MyPW");

            int ovalue = -1;    
        Statement stmt = (Statement) con.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT "+loc+" FROM PlayerData WHERE PlayerName='"+playername+"'");
        if(rs.next()){
            ovalue= rs.getInt(loc);
        }
        if(ovalue == -1){
            logm("Error Occured");

        }
        int nvalue = value + ovalue;

        String insert = "UPDATE PlayerData SET "+ loc + "='" + nvalue + "' WHERE PlayerName='" + playername + "'";

        stmt.executeUpdate(insert);

        con.close();

    }catch(Exception e){

        logm("Could Not Send Data To MYSQL DATABASE SERVER s: "+ e.getMessage());
    }
}

なぜこれがうまくいかないのかわかりません。私が見逃していることは明らかですか?前もって感謝します。

4

2 に答える 2

1

したがって、最初に理解する必要があるのは、 を使用しない場合parametrized statements、 の危険性が非常に高いということですSQL Injection。したがって、あなたのコードは非常に汚いです。とにかく、パラメーター化PreparedStatementされた SQL ステートメントで使用すると、パフォーマンスが大幅に向上します。コードを次のように書き換えます。

final String SELECT_QUERY = "SELECT level FROM PlayerData WHERE PlayerName = ?";
final String UPDATE_QUERY = "UPDATE PlayerData SET level = ? WHERE PlayerName = ?";

public boolean dataMethod(String playerName) {
   Connection con = null;
   PreparedStatement ps = null;
   PreparedStatement ps1 = null;
   ResultSet rs = null;
   int dataLevel = 0;

   try {

   // getConnection etc...
   ps = con.prepareStatement(SELECT_QUERY);
   ps.setString(1, playerName) // first param is order of ? param, starts with 1(not 0)
   rs = ps.executeQuery();
   while (rs.next()) {
      dataLevel = rs.getInt();
   }
   if (dataLevel > 0) {
       ps1 = con.prepareStatement(UPDATE_QUERY);
       ps1.setInt(1, dataLevel);
       ps1.setString(2, playerName);
       ps1.executeUpdate();   
   }
   return true;
   }
   catch (SQLExcetion ex) {
      Logger.getLogger(YourClass.class.getName()).log(Level.SEVERE, null, ex);
      return false;
   }
   finally {
      if (con != null) {
         con.close();
      }
   }
}

ステップごとに、最初にステートメントを初期化し、パラメーターを設定する場合は、select を使用するResultSetと、クエリで生成されたデータのテーブルであるデータを取得します。暗黙的にカーソルがResultSet最初の行の前にあるため、next()メソッドを使用して現在の行に移動し、getter メソッドを使用ResultSetして変数にデータを追加する必要があります。次に、それが正しいかどうかを確認し、正しい場合は、2 番目のステートメントを初期化して実行します。それだけです。

ただし、複数の操作を使用する場合はautoCommit、 false を設定すると、すべての操作が 1つの操作で実行されることを考慮する必要があります。Transactionこれは、暗黙的にJDBC1 つの操作 = 1 つのトランザクションであるためです。次に、データの追加、データの更新、または削除にSQL ストアド プロシージャを使用することを検討する必要があります。さらに安全で、コードが少なくなります。したがって、データベースが実行できるときにデータベースを動作させます。もちろん、それはより高速です。最後に、このアプローチについて考えて、コードをより安全に、より速く、よりクリーンにする必要があります。シンプルさではなく、効率、互換性、およびセキュリティに注目してください。

SQL インジェクションの詳細

そして、ストアド プロシージャを使用する権利を決定したら、次のように使用できます。

CREATE OR REPLACE PROCEDURE SOME_NAME(VARCHAR v_name PlayerData.name%type)
AS
BEGIN
   SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
   // body
   COMMIT;
EXCEPTION
   WHEN OTHERS THEN
      ROLLBACK;
END;

したがって、呼び出しプロシージャの文字列を作成する必要があります。

final String CALL_SOMENAME = "{call SOME_NAME(?)}";

その代わりに、SQL ストアド プロシージャの実行に使用されるものPreparedStatementを使用する必要があります。CallableStatementinterface

cs.prepareCall(CALL_SOMENAME); // Creates a cs object for calling db stored procedures
cs.setString(1, playerName);
cs.execute();

なぜ多くの人が何かを行うための最も簡単な方法を探し、コードのパフォーマンスと可読性を考慮しないのか、私にはわかりません。

よろしく

于 2012-06-01T18:17:26.127 に答える
0

UPDATE ステートメントでは、"loc" 列の値を文字列として挿入しています (値は一重引用符で囲まれています)。データベース列が整数の場合、これが問題を引き起こしている可能性があります。

ヒント: JDBC には というクラスが用意されていますPreparedStatement。このクラスを使用すると、SQL クエリを安全に作成できます。セキュリティの脆弱性を回避するために、すべてのユーザー入力が適切にエスケープされるようにします。

PreparedStatement ps = con.prepareStatement("UPDATE PlayerData SET " + loc + " = ? WHERE PlayerName = ?");
ps.setInt(1, nvalue);
ps.setString(2, playername);
ps.execute();
于 2012-06-01T17:52:13.347 に答える