5

我一直在从 PostgreSQL 9.1 迁移到 Oracle 11gR2 并且遇到了一个奇怪的问题。

当客户添加到我们的 ERP 系统时,我一直在运行更新表格的代码。自 3 月以来,此代码一直在 PostgreSQL 上运行,没有出现任何问题。现在我切换到 Oracle,相同的代码不再更新。

原始代码

update = "UPDATE store SET added_customer = 'y' WHERE order_id = ?";
try {
    PreparedStatement pStmnt = getConn().prepareStatement(update);
    pStmnt.setString(1, orderId);               
    results = pStmnt.executeUpdate();

    if (results > 0) {
        added = true;                   
    }       
} catch (SQLException ex) {
    LOGGER.error(ex.toString());
}

没有抛出异常,但没有更改数据,所以我认为“自动提交一定不起作用,让我们手动提交”:

新代码

update = "UPDATE shop_ca_orders SET added_customer = 'y' WHERE order_id = ?";
try {                 
    getConn().setAutoCommit(false); //Added
    PreparedStatement pStmnt = getConn().prepareStatement(update);
    pStmnt.setString(1, orderId);               
    results = pStmnt.executeUpdate();

    if (results > 0) {
        added = true;
        getConn().commit(); //Added
        getConn().setAutoCommit(true); //Added
    }       
} catch (SQLException ex) {
    LOGGER.error(ex.toString());
}

仍然没有运气,所以我LOGGER.debug("Update to order returned {}",results);executeUpdate声明之后添加,发现我返回 0,所以没有记录被更新。

很有趣,所以我通过 SQL Developer 尝试了查询,它正确更新了。这让我想到了我的问题:

为什么我无法通过 JDBC 更新我的数据库?

基本数据:

  • order_id是类型VARCHAR(255 BYTE)
  • 爪哇 7
  • 在 Amazon RDS 上运行的 Oracle 11GR2
  • 从运行在 Heroku 上的 PostgreSQL 9.1 迁移而来
  • 在 PostgreSQLorder_id上是一个character varying(255)

编辑

未检测到小的架构更改并导致错误,其中订单 ID 实际上是人的姓名,而不是订单 ID。我的骨头错误。无论如何,既然我已经解决了这个问题并提取了正确的订单 ID,我发现我正在坚持executeUpdate。目前正在研究该问题。如果我无法解决,我可能会创建一个新问题。

4

3 回答 3

1

返回什么getConn()?我怀疑每次都是不同的(池化?)连接。

这个:

getConn().setAutoCommit(false); //Added
PreparedStatement pStmnt = getConn().prepareStatement(update);

应该是:

Connection c = getConn();
c.setAutoCommit(false); //Added
PreparedStatement pStmnt = c.prepareStatement(update);

即如果getConn()每次都返回不同的连接,那么你就有问题了。

于 2013-10-23T13:19:16.947 回答
1

所以我的问题是两个方面:

首先,我的初始结果集有问题。在迁移过程中删除了一列,我认为所有引用的列都在代码中进行了更改,但是缺少一列。解决此问题后,订单 ID 可以正常工作,并尝试更新数据库。

第二个问题是数据库挂在更新上的问题。事实证明,挂起是由 SQL Developer 持有数据库(或表,不确定是哪个)锁定引起的 - 一旦我关闭 SQL Developer,更新立即完成并且事情按预期进行。

于 2013-10-23T14:20:59.350 回答
0

几年前我经历过这个问题,当我在 WHERE 子句上使用字符串值时,使用标记,它没有用。顺便说一句,它也是一个 Oracle 数据库(10g)

最后,我放弃了,并更改了代码以连接值而不是对其进行标记

update = "UPDATE shop_ca_orders SET added_customer = 'y' WHERE order_id = ?";
try {                 
    getConn().setAutoCommit(false); //Added
    PreparedStatement pStmnt = getConn().prepareStatement(update);
    pStmnt.setString(1, orderId);               
    results = pStmnt.executeUpdate();

    if (results > 0) {
        added = true;
        getConn().commit(); //Added
        getConn().setAutoCommit(true); //Added
    }       
} catch (SQLException ex) {
    LOGGER.error(ex.toString());
}

update = "UPDATE shop_ca_orders SET added_customer = 'y' WHERE order_id = ' + order_id + '";
try {                 
    getConn().setAutoCommit(false); //Added
    PreparedStatement pStmnt = getConn().prepareStatement(update);
    results = pStmnt.executeUpdate();

    if (results > 0) {
        added = true;
        getConn().commit(); //Added
        getConn().setAutoCommit(true); //Added
    }       
} catch (SQLException ex) {
    LOGGER.error(ex.toString());
}

这对我有用......这不是最优雅的解决方案,而是一种解决方法

====================== 更新1 ========================== ==

我做了更多的研究,因为我也遇到了这个问题,但仍然没有得到有效的答案

看起来 Oracle 驱动程序希望您将具有相似长度的字符串传递给表定义。这只发生在固定长度的列(如 CHAR)上,VARCHAR 列似乎不受此影响。

这意味着,如果order_id是 CHAR(10) ,那么您应该填充您的 String 以完成列长度。更好的方法是修剪数据库值以匹配令牌值。

update = "UPDATE shop_ca_orders SET added_customer = 'y' " + 
         " WHERE LTRIM(RTRIM(order_id)) = ?";
try {                 
    getConn().setAutoCommit(false); //Added
    PreparedStatement pStmnt = getConn().prepareStatement(update);
    pStmnt.setString(1, orderId);               
    results = pStmnt.executeUpdate();

    if (results > 0) {
        added = true;
        getConn().commit(); //Added
        getConn().setAutoCommit(true); //Added
    }       
} catch (SQLException ex) {
    LOGGER.error(ex.toString());
}
于 2013-10-23T13:27:57.390 回答