JDBC Return 生成的密钥或现有密钥

JDBC Return generated key or existing key

我有一个 table 具有唯一索引以消除重复项(简化示例)

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

据我所知,使用批处理执行的方法并不那么简单。您的方法是获取自动生成的密钥的最佳方式。 JDBC 驱动程序有一些限制,并且版本因版本而异,其中 getGeneratedKeys() 适用于单项。

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

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

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

您可以将 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,但上面应该可以解决问题。

如果您的 table 被正确索引,那么用于存在性检查的额外 SELECT 将很快并且数据库将不得不执行该检查。