2012-06-01 42 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 –