【问题标题】:SQL returning wrong dataSQL 返回错误数据
【发布时间】:2018-06-20 01:13:09
【问题描述】:

由于某种原因,我的 SQL 连接似乎返回了完全无效的响应。不知何故,在一次调用和下一次调用之间(经过一段短暂的时间,大约一秒钟),它返回一个完全不同的值。我应该注意,我有其他行以完全相同的方式设置,没有这个问题。

我应该注意,我将 apache dbcp2 用于 SQL 数据源,这是 getConnection() 调用的地方。我应该注意,其他一切都可以正常工作,但由于某种原因不是这样。

希望我提供了足够的信息。我不是要求你为我做这项工作,我只是不知道这里可能出现什么问题。

//First call
//Note Global.TOKEN_TTL is a constant value of 300000
System.out.println((System.currentTimeMillis() + Global.TOKEN_TTL));
Start.getSQLConnection().setTTL(userID, (System.currentTimeMillis() + Global.TOKEN_TTL));
System.out.println(Start.getSQLConnection().getTTL(userID));
//Second Call
System.out.println(System.currentTimeMillis());
System.out.println(Start.getSQLConnection().getTTL(userID));


Output
----Call one
System call: 1529456964416
DB call:     1529456964416
DB Actual:   1529456964416
----Call two
System call: 1529456665144
DB call:     4294967295
DB Actual:   1529456964416

数据库是使用 MariaDB 建立的。该行是一个有符号的 BIGINT,长度为 20。

检索

下面的代码按从头到尾的顺序调用:

第一次通话:

getLong("adbname", "TTL", "SELECT TTL FROM atablename WHERE ID=?;", userID);

第二次通话:

public long getLong(String database, String tag, String sql, Object... parameters) throws SQLException {
    return (long) getObject(database, sql, tag, parameters);
}

第三次调用:

public Object getObject(String database, String sql, String tag, Object... parameters) throws SQLException {
    Connection conn = getConnection(database);
    conn.setAutoCommit(false);
    PreparedStatement stmt = conn.prepareStatement(sql);
    assert parameters != null && parameters.length > 0;

    for (int i = 0; i < parameters.length; i++) {
        stmt.setObject(i + 1, parameters[i]);
    }
    ResultSet rs = stmt.executeQuery();
    if (!rs.next())
        return null;

    Object o = rs.getObject(tag);
    conn.commit();

    if (rs != null)
        rs.close();
    if (stmt != null)
        stmt.close();
    if (conn != null)
        conn.close();

    return o;
}

设置

public boolean setTTL(long userID, long TTL) throws SQLException {
    return executeUpdate("adbname", "UPDATE atablename SET TTL=? WHERE ID=?;", TTL, userID);
}
//The actual work
public boolean executeUpdate(String database, String sql, Object... parameters) throws SQLException {
    Connection conn = getConnection(database);
    conn.setAutoCommit(false);
    PreparedStatement stmt = conn.prepareStatement(sql);
    for (int i = 0; i < parameters.length; i++) {
        stmt.setObject(i + 1, parameters[i]);
    }
    boolean result = stmt.executeUpdate() > 0;
    conn.commit();

    if (stmt != null)
        stmt.close();
    if (conn != null)
        conn.close();

    return result;
}

【问题讨论】:

  • getObjectexecuteUpdate 中,您应该将您的开盘和收盘包装到try-with=resource 中,这样如果发生异常,它将保证关闭。还有你在哪里使用transactions
  • 更改了结束,运行“BEGIN;”和“提交;” SQL 语句之前和之后分别似乎没有意义。如果我使用错误的交易,你有一个不错的 mariadb 指南吗?从我设法找到的内容来看,这应该符合我的预期。
  • 我给了你那个链接来说明如何使用交易。除非你修改你的问题以显示你做了什么,否则很难提供帮助。
  • 很难从您的代码中理解出了什么问题,但是,1) 为什么您使用Objects 而不是longs? 2)Start.getSQLConnection() 在做什么,如果在executeUpdate 内您通过Connection conn = getConnection(database); 获得连接,为什么有必要这样做 3)抛出了哪些异常? 4)为此,我认为这个问题将是糟糕,我忘了告诉你......这就是问题 - 尝试做一个血腥简单的例子

标签: java sql mariadb


【解决方案1】:

我不想承认这一点,但@Scary Wombat 是对的。它最终(不完全是)成为那些“哦,我忘了告诉你”的场景之一。

问题是检索用户 ID 的方式存在设计缺陷,因为不能保证它们是唯一的(我认为这是非常严重的缺陷)。它正在从另一个用户那里提取数据。

非常感谢您提供的所有帮助,虽然它并没有直接解决问题,但您让我深入了解了我在 SQL 和存储方面做错的一些事情。我一定会记住这个,再次感谢!

【讨论】:

  • 很高兴听到你修复了它
【解决方案2】:

线索:4294967295 = 2^32-1

闻起来就像您拥有某些产品的 32 位版本,甚至可能是操作系统。

或者您在需要BIGINT 时使用INT UNSIGNED。你说“该行是一个长度为 20 的签名 BIGINT”——请提供SHOW CREATE TABLE

什么是让Object o = rs.getObject(tag); 不被限制为 32 位?

【讨论】:

  • 这是一个 64 位产品和操作系统,问题是它只是检索无效行。不过谢谢你的想法,我会记住的!
猜你喜欢
  • 2012-04-21
  • 2011-03-15
  • 1970-01-01
  • 2016-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多