Spring JDBC и составные первичные ключи - PullRequest
4 голосов
/ 28 июня 2010

Есть ли у пружины jdbc способ вернуть составной первичный ключ при вставке строки.Этот составной первичный ключ состоит из значений из отдельных последовательностей

Любая помощь с благодарностью

С уважением Дэмиен

Ответы [ 4 ]

3 голосов
/ 03 июля 2010

Вот полный пример (проверено на PostgreSQL 8.4):

Моя таблица:

CREATE TABLE test
(
  id serial NOT NULL,
  otherid serial NOT NULL,
  val text,
  CONSTRAINT test_pkey PRIMARY KEY (id, otherid)
)

Вот как вы получаете ключи обратно:

public void doStuff() {
    KeyHolder keyHolder = new GeneratedKeyHolder();
    jdbcTemplate.update(
            new PreparedStatementCreator() {
                public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                    PreparedStatement ps = connection.prepareStatement("insert into test(val) values (?)", Statement.RETURN_GENERATED_KEYS);
                    ps.setInt(1, 42);
                    return ps;
                }
            },
            keyHolder);

    keyHolder.getKeys().get("id");
    keyHolder.getKeys().get("otherid");
}

Теперь, если вы хотите получить составной ключ как экземпляр некоторого класса непосредственно из keyHolder, это не просто.

JdbcTemplate использует ColumnMapRowMapper для сопоставления сгенерированных ключей (сгенерированные ключи возвращаются как набор результатов, по крайней мере, приPostgreSQL. Он на самом деле возвращает всю строку, как если бы вы выполняли select для только что вставленной строки).Тот же ColumnMapRowMapper используется во многих других местах JdbcTemplate.

Единственная возможная точка расширения здесь - это сам KeyHolder.Вот что вы можете сделать:

public void doStuff() {
    CompositeKeyHolder keyHolder = new CompositeKeyHolder();
    ... same code here ...

    keyHolder.getCompositeKey();
}


class CompositeKeyHolder extends GeneratedKeyHolder {
    private boolean converted;

    public CompositeKey getCompositeKey() {
        return new CompositeKey((Integer)this.getKeys().get("id"), (Integer)this.getKeys().get("otherid"));
    }
}


class CompositeKey {

    private Integer id;

    private Integer otherId;

    CompositeKey(Integer id, Integer otherId) {
        this.id = id;
        this.otherId = otherId;
    }

    public Integer getId() {
        return id;
    }

    public Integer getOtherId() {
        return otherId;
    }

}
0 голосов
/ 01 июля 2010

Какой сервер базы данных вы используете? MySQL допускает только одно поле auto_increment на таблицу, и я предполагаю, что это часто имеет место, но, не зная ваших настроек, сложно сказать. Предполагая, что в вашей таблице есть только одно поле auto_generated, ваш INSERT должен был бы знать о значении, входящем во второе поле PK. Код Роберта должен работать для извлечения сгенерированного значения ключа, и самым чистым решением, вероятно, было бы выполнение SELECT после факта, использующего этот сгенерированный ключ и значение, которое у вас уже было.

0 голосов
/ 01 июля 2010

Я думаю, что вам нужно GeneratedKeyHolder.getKeys () .Код будет выглядеть как в этом примере , за исключением того, что вам придется звонить

keyHolder.getKeys()

вместо

keyHolder.getKey()
0 голосов
/ 30 июня 2010

Вот основная идея для одного ключа. Длинный идентификатор в конце является ключом. Если у вас несколько последовательностей, я бы рекомендовал использовать два отдельных оператора для получения каждого сгенерированного ключа.

JdbcTemplate template = getJdbcTemplate();
KeyHolder keyHolder = new GeneratedKeyHolder();
template.update(
    new PreparedStatementCreator() {
        public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
            PreparedStatement ps = connection.prepareStatement(...);
            return ps;
        }
    },
    keyHolder);
long id = keyHolder.getKey().longValue();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...