2012-06-01 43 views
-3

我想將MySql數據庫中保存的整數保存到Java中的Integer中。我有一個表,包括PlayerName和Level。我想從特定玩家那裏獲得關卡(整數)。然後將整數「值」添加到它。然後把它放回數據庫。我的代碼到現在是:從MySQL選擇語句獲取整數

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

我不知道爲什麼,這是不行的,這有什麼明顯的,我很想念?先謝謝你。

+3

究竟什麼是行不通的?你有例外嗎?什麼都沒發生?我們需要更多信息。 – pcalcao

+0

您是否收到錯誤訊息?運行時發生了什麼? –

回答

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

所以,首先你必須瞭解的是,當你不會使用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(); 
     } 
    } 
} 

循序漸進,先初始化你的聲明,設置參數,如果你有那麼當你使用選擇,你會在ResultSet這是查詢產生的數據表中檢索數據。在ResultSet中的顯式遊標位於第一行之前的位置,所以您必須使用next()方法繼續當前行,並藉助getter方法將數據從ResultSet添加到您的變量。然後你檢查它是否正確,如果是,初始化第二條語句並執行它。就這樣。

但是當你使用更多的是1點的操作,您應該考慮設置autoCommit虛假和所有操作都將在一個Transaction做,因爲隱含在JDBC是一個操作=一次交易。其次,您應該考慮使用SQL存儲過程來添加任何數據,更新數據或刪除。它更安全,代碼更少。所以讓數據庫在能夠做到的時候工作,當然它也更快。最後,你真的應該考慮這種方法,並使你的代碼更安全,更快,更清潔。沒有看簡單,但在效率,可操作性和安全性。

更多SQL Injection

而當你決定使用權存儲過程,你可以使用它像這樣:

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

隨後的PreparedStatement這一翻譯必須使用CallableStatementinterface用於執行SQL存儲過程。

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

我不知道爲什麼很多人在尋找最簡單的方法來做一些事情,而不是看代碼的性能和可讀性。

Regards

+0

非常感謝!我會試試這個吧! –

+0

雖然這段代碼似乎很擅長它,但我不認爲這是我的意思。現在的情況:我有我的數據庫中的計數器和整數級別(表示由變量loc)和字符串PlayerName在表中。我希望每次調用該方法時都會獲得該級別,併爲其添加1,然後將其提交回數據庫。那是我失敗的地方。但無論如何,謝謝你的幫助,也許你也可以幫助我。 - Jan –