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 将很快并且数据库将不得不执行该检查。
我有一个 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 将很快并且数据库将不得不执行该检查。