如何使这个JDBC代码更具可移植性?

时间:2014-09-24 02:46:12

标签: mysql oracle jdbc portability

我有以下代码:

List<List<Object>> batch = db.executeInsert("insert into Batches (batch_date,source,log_file,status) values (?, ?, ?, ?)", 
    now, 
    importZip.getAbsolutePath(), 
    logFile.getAbsolutePath(), 
    BatchStatus.IMPORTING.toString())

当我在MySQL上运行它时返回的数据返回一个Integer,表示插入的ID符合预期。在Oracle下运行时,它返回一个不可移植的ROWID对象。我有一个标识列,最终将转换为表示ID的序列。但是,使用ROWID无法解决问题。

我已经检查了代码,我正在调用statement.getGeneratedKeys(),我认为这是制作可移植代码的重点。如何在不执行明显不可移植的select from table where ROWID=?之类的情况下以便携方式编写此内容。

2 个答案:

答案 0 :(得分:1)

正如您已经发现的那样,Oracle返回ROWID,以便您可以 - 例如 - 通过查询行来获取id。

有些数据库只返回最后生成的id(可能甚至不属于表,例如MySQL AFAIK),有些数据库只返回id列作为ResultSet中的第一列,其他数据库返回所有列(例如PostgreSQL,Firebird默认情况下),因此id列的位置可能不一定是第一列,因为它取决于表中的列顺序。

唯一真正的选择是创建一个特定于数据库的策略,该策略知道获取正确列的规则。这可能涉及触发针对Oracle的额外查询,使用一些启发式方法来查找PostgreSQL和Firebird的主键列等。

答案 1 :(得分:1)

所以我找到的便携式解决方案是使用稍微不同的PreparedStatement版本和getGeneratedKeys()。结果是在mysql和oracle上都是可移植的,我想象其他人:

Connection connection = createConnection();
PreparedStatement statement = null;
statement = connection.prepareStatement(sql,new String[] { "ID" });
int updateCount = statement.executeUpdate();

ResultSet keysRs = statement.getGeneratedKeys();
if( keysRs.next() ) {
    return keyRs.getInteger("ID");
}

这是我使用的解决方案。