Весна: Как использовать KeyHolder с PostgreSQL

Недавно перенесен в POSTGRESQL, я пытаюсь получить уникально сгенерированный ключ при создании новой записи в таблице БД. Стол screenstable выглядит так:

CREATE TABLE screenstable
(
  id serial NOT NULL,
  screenshot bytea,
  CONSTRAINT screen_id PRIMARY KEY (id )
)

Метод, который вставляет данные в screenstable как следует:

@Autowired NamedParameterJDBCTemplate template;
public int insertImage(ImageBean imageBean){
        String query = "insert into screenstable (screenshot) values (:image)";
        SqlParameterSource data = new BeanPropertySqlParameterSource(imageBean);
        KeyHolder keyHolder = new GeneratedKeyHolder();
        template.update(query, data, keyHolder);
        return keyHolder.getKey().intValue();
    }

а также ImageBean является

import java.util.Arrays;

public class ImageBean {
    private int id;
    private byte[] image;
    @Override
    public String toString() {
        return "ImageBean [id=" + id + ", image=" + Arrays.toString(image)
                + "]";
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public byte[] getImage() {
        return image;
    }
    public void setImage(byte[] image) {
        this.image = image;
    }
}

Но выполнение кода дает следующее исключение

15:33:20,953 ERROR JsonParseExceptionMapper:15 - org.springframework.dao.InvalidDataAccessApiUsageException: The getKey method should only be used when a single key is returned.  The current key entry contains multiple keys: [{id=3, screenshot=[B@db59df}]
org.springframework.dao.InvalidDataAccessApiUsageException: The getKey method should only be used when a single key is returned.  The current key entry contains multiple keys: [{id=3, screenshot=[B@db59df}]
        at org.springframework.jdbc.support.GeneratedKeyHolder.getKey(GeneratedKeyHolder.java:65)
        at some.project.model.FeedbackDao.insertImage(FeedbackDao.java:20)
        at some.project.rest.FeedsRest.pluginCheck(FeedsRest.java:62)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597).....

Тот же код, используемый для нормальной работы в случае MySQL но не работает с ключами при использовании с POSTGRES. Является ли тип данных serial как-то ответственность за сбой кода или, может быть, я правильно использую функцию первичного ключа?

Пожалуйста посоветуй.

3 ответа

Решение

Если инфраструктура не проинформирована о том, какой столбец является ключом, она вернет все столбцы таблицы в качестве ключей.

Вы можете сообщить об этом, передав новый параметр методу обновления следующим образом:

template.update(query, data, keyHolder, new String[] { "id" });

См. NamedParameterJdbcTemplate.update (sql, paramSource, generateKeyHolder, keyColumnNames)

Вы также можете остаться с JdbcTemplate, но в этой ситуации вы должны проверить это:

    jdbcTemplate.update(this, holder);
    Long newId;
    if (holder.getKeys().size() > 1) {
        newId = (Long)holder.getKeys().get("your_id_column");
    } else {
        newId= holder.getKey().longValue();
    }

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

В ситуации, когда драйвер jdbc возвращает несколько ключей, вы должны определить столбец сгенерированного ключа (либо до обновления, либо после). Пожалуйста, взгляните на исходный код GeneratedKeyHolder#getKey - его очень просто проанализировать. Есть проверка размера списка ключей, и с большим, чем ключ, Spring не знает, какой ключ должен быть возвращен, и поэтому возвращается исключение.

Примечание: пожалуйста, помните, что подход не будет работать с Oracle, потому что Oracle возвращает что-то вроде ROWID. С Oracle вы должны использовать NamedParameterJdbcTemplate.

Просто предположение из быстрого взгляда... keyHolder.getKey(). IntValue () должно быть keyHolder.getKey () ["id"]. IntValue () (или что-то подобное)? Функция getKey () возвращает объект с несколькими ключами (id и изображение), и вы пытаетесь превратить объект в int с помощью функции intValue (), которая, как мне кажется, не работает, если вы не укажете на клавишу "id" в объекте, возвращаемом из "getKey ()" Приветствия, Франческо

Другие вопросы по тегам