JDBC返回生成的密钥或现有密钥

时间:2015-02-10 12:42:30

标签: java mysql jdbc prepared-statement

我有一个具有唯一索引的表来消除重复(简化示例)

CREATE TABLE `domain` (
      `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
      `subdomain` VARCHAR(255) NOT NULL,
      `domain` VARCHAR(63) NOT NULL,
      `zone` VARCHAR(63) NOT NULL,
      PRIMARY KEY (`id`),
      UNIQUE INDEX `UNIQUE` (`subdomain` ASC, `domain` ASC, `zone` ASC),
    ENGINE = InnoDB;

我插入了很多行,我需要返回主键(对于其他一对多插入)。

我的问题是,我插入了很多重复项,我也需要返回这些键。

这是我的解决方案,但有没有更简单的解决方案?有了这个,我不能使用批量插入,我希望这是最有效的。

PreparedStatement selectDomain = connection.prepareStatement("SELECT id FROM domain WHERE subdomain = ? AND domain = ? AND zone = ?");
PreparedStatement insertDomain = connection.prepareStatement("INSERT INTO domain(subdomain, domain, zone) VALUES (?,?,?)", Statement.RETURN_GENERATED_KEYS);

public int insertDomain(String subdomain, String domain, String zone) throws SQLException {
        int domainId = 0;
        selectDomain.setString(1, subdomain);
        selectDomain.setString(2, domain);
        selectDomain.setString(3, zone);
        ResultSet resultSet = selectDomain.executeQuery();
        if (resultSet.next()) {
            domainId = resultSet.getInt(1);
        } else {
            insertDomain.setString(1, subdomain);
            insertDomain.setString(2, subdomain);
            insertDomain.setString(3, subdomain);
            insertDomain.executeUpdate();
            resultSet = insertDomain.getGeneratedKeys();
            if (resultSet.next()) {
                domainId = resultSet.getInt(1);
            }
        }
        selectDomain.clearParameters();
        insertDomain.clearParameters();
}

2 个答案:

答案 0 :(得分:0)

据我所知,使用批量执行不是那么容易的方法。您的apporach是获取自动生成密钥的最佳方式。 JDBC驱动程序的限制很少,并且版本因版本而异,其中getGeneratedKeys()适用于单个条目。

请查看以下链接,它可能会对您有所帮助: -

How to get generated keys from JDBC batch insert in Oracle?

http://docs.oracle.com/database/121/JJDBC/jdbcvers.htm#JJDBC28099

答案 1 :(得分:0)

您可以将INSERT修改为:

INSERT INTO domain (subdomain, domain, zone)
SELECT $subdomain, $domain, $zone
FROM domain 
WHERE NOT EXISTS(
    SELECT subdomain, domain, zone
    FROM domain d
    WHERE d.subdomain= $subdomain and d.domain=$domain and d.zone=$zone
)
LIMIT 1

其中$subdomain, $domain, $zone是您要添加的标记(正确引用或作为占位符),如果尚未添加的话。如果标签已经存在,这种方法甚至不会触发INSERT(以及随后的自动增量浪费)。你可能会提出比这更好的SQL,但上面应该可以解决这个问题。

如果你的表被正确编入索引,那么存在检查的额外SELECT将很快,数据库将不得不执行该检查。