【问题标题】:Getting an Integer From MySQL Select Statement从 MySQL Select 语句中获取整数
【发布时间】:2012-06-01 16:43:18
【问题描述】:

我想将保存在 MySql DB 中的整数转换为 Java 中的整数。我有一个表,其中包括 PlayerName 和 Level。我想从特定玩家那里获得关卡(整数)。然后将整数“值”添加到它。然后将其放回数据库中。到目前为止,我的代码是:

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

我不知道为什么这不起作用,我有什么明显的遗漏吗?提前谢谢你。

【问题讨论】:

  • 究竟是什么不起作用?你有例外吗?没发生什么事?我们需要更多信息。
  • 您是否收到错误消息?运行时发生了什么?

标签: java mysql database integer


【解决方案1】:

所以首先你要明白,当你不使用parametrized statements时,SQL Injection就有很大的危险。所以你的代码写得很脏。 所以无论如何,将PreparedStatementparametrized 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 的数据添加到变量中。然后检查它是否正确,如果正确,则初始化第二条语句并执行它。仅此而已。

但是您应该考虑当您使用超过 1 个操作时,将 autoCommit 设置为 false 并且所有操作都将在一个 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 之外,您必须使用CallableStatement,即interface 用于执行SQL 存储过程。

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

我不知道为什么很多人在寻找最简单的方法来做某事,却不关注代码的性能和可读性。

问候

【讨论】:

  • 虽然这段代码看起来很擅长它的作用,但我不认为这就是我的意思。现在的情况:我的数据库中有一个计数器,表中有一个整数级别(由变量 loc 表示)和字符串 PlayerName。我希望每次调用该方法时都会获得级别,将其加 1,然后将其提交回数据库。那是我失败的地方。但无论如何,谢谢你的帮助,也许你也可以帮助我。 - 一月
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2011-01-19
    • 1970-01-01
    • 2015-11-19
    • 1970-01-01
    • 1970-01-01
    • 2012-01-10
    • 2022-11-20
    • 1970-01-01
    相关资源
    最近更新 更多