插入具有重复唯一键的记录时如何获取主键

How to get the primary key when inserting a record with a duplicate unique key

我有一个 DAO 方法,用于将电子邮件记录插入和更新到 table 中,并使用电子邮件地址的唯一键。方法 returns 记录的 id,但是当插入重复的电子邮件时,我正在努力获取原始的现有记录的 id。我咨询了MYSQL: Getting existing primary key when inserting record with duplicate unique key?,但是我用的是JdbcTemplate。我尝试使用 'ON DUPLICATE KEY UPDATE',但它一直抛出 NullPointerException。

代码如下:

    @Override
    public Integer insertOrUpdate(final Email e) {
        if (e == null) throw new IllegalArgumentException();

        if (e.getIdEmail() != null) {
            String sql = "UPDATE Email SET email=? WHERE idEmail=?";
            jdbcTemplate.update(sql, e.getEmail(), e.getIdEmail());
            return e.getIdEmail();
        }
        else {
            final String sql = "INSERT IGNORE INTO Email (email) VALUES (?) ON DUPLICATE KEY UPDATE email=email";
            KeyHolder keyHolder = new GeneratedKeyHolder();
            jdbcTemplate.update(new PreparedStatementCreator() {
                public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                    PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
                    ps.setString(1, e.getEmail());
                    return ps;
                }
            }, keyHolder);
            return ((Long) keyHolder.getKey()).intValue();
        }
    }

在我尝试使用 'ON DUPLICATE KEY UPDATE' 之前,它为重复键抛出 MySQLIntegrityViolationException,但现在 keyHolder 不断抛出 NullPointerException。

如果 keyHolder 为 null,我通过单独查询 id 解决了这个问题。

这是更新后的代码:

    @Override
    public Integer insertOrUpdate(final Email e) {
        if (e == null) throw new IllegalArgumentException();

        if (e.getIdEmail() != null) {
            String sql = "UPDATE Email SET email=? WHERE idEmail=?";
            jdbcTemplate.update(sql, e.getEmail(), e.getIdEmail());
            return e.getIdEmail();
        }
        else {
            final String sql = "INSERT IGNORE INTO Email (email) VALUES (?)";
            KeyHolder keyHolder = new GeneratedKeyHolder();
            jdbcTemplate.update(new PreparedStatementCreator() {
                public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                    PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
                    ps.setString(1, e.getEmail());
                    return ps;
                }
            }, keyHolder);
            if (keyHolder.getKey() != null)
                return ((Long) keyHolder.getKey()).intValue();
            else {
                String sql2 = "SELECT idEmail FROM Email WHERE email=?";
                return jdbcTemplate.queryForObject(sql2, new Object[] {e.getEmail()}, Integer.class);
            }
        }
    }