Использование ключа Spring с программно генерируемыми первичными ключами

StackOverflow https://stackoverflow.com/questions/2819514

Вопрос

Я использую Spring NamedParameterJDBCTEMPTEMPTEMPTEMPTEM для выполнения вставки в таблицу. Таблица использует NextVal на последовательности для получения первичного ключа. Затем я хочу, чтобы этот сгенерированный идентификатор был передан мне. Я использую реализацию Spring Keyholder, как это:

KeyHolder key = new GeneratedKeyHolder();
jdbcTemplate.update(Constants.INSERT_ORDER_STATEMENT, params, key);

Однако, когда я запускаю это утверждение, я получаю:

org.springframework.dao.DataRetrievalFailureException: The generated key is not of a supported numeric type. Unable to cast [oracle.sql.ROWID] to [java.lang.Number]
    at org.springframework.jdbc.support.GeneratedKeyHolder.getKey(GeneratedKeyHolder.java:73)

Любые идеи, что мне не хватает?

Это было полезно?

Решение

Я думаю, что вы используете неправильный метод на JdbcTemplate. Отказ Единственный из update методы, которые, казалось бы, чтобы соответствовать вашим фрагменте кода

int update(String sql, Object... args)

Если так, вы проходите params а также key как двухэлементный массив Vargs и JdbcTemplate лечится key как нормальный параметры связывания и неправильно интерпретировать.

Единственная публика update метод включения JdbcTemplate это принимает А. KeyHolder является

int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)

Таким образом, вам нужно перефразировать ваш код, чтобы использовать это.

Другие советы

Только что решил подобную проблему - с Oracle вам нужно использовать другой метод (из NamedParameterJdbcOperations) -

int update(String sql,
           SqlParameterSource paramSource,
           KeyHolder generatedKeyHolder,
           String[] keyColumnNames)
           throws DataAccessException

С KeyColumnnames, содержащими автоматически сгенерированные столбцы, в моем случае [«ID»]. В противном случае все, что вы получаете, это ROWID. Видеть Весной док для деталей.

Вы должны выполнить JdbcTemplate.update(PreparedStatementCreator p, KeyHolder k).

Ключ, возвращенный из базы данных, будет введен в KeyHolder объект параметра.

Пример:

final String INSERT_ORDER_STATEMENT 
       = "insert into order (product_id, quantity) values(?, ?)";

KeyHolder keyHolder = new GeneratedKeyHolder();
    jdbcTemplate.update(new PreparedStatementCreator() {
        public PreparedStatement createPreparedStatement(
            Connection connection) throws SQLException {
                PreparedStatement ps = connection.prepareStatement(
                    INSERT_ORDER_STATEMENT, new String[] { "id" });
                ps.setInt(1, order.getProductId());
                ps.setInt(2, order.getQuantity());
                return ps;
            }
        }, keyHolder);

Больше информации можно найти здесь В справочной документации.

Не разработано на @konstantin Ответ: вот полностью рабочий пример: при условии, что база данных - это имя базы данных Oracle и столбца, который сгенерированный для хранения ID «Genered_id» (может быть любое имя). Примечание: я использовал namedparameterjdbctemplate.update (....) В этом примере не класс JDBCTEMPLETS класса пружины.

       public Integer insertRecordReturnGeneratedId(final MyObject obj)
            {
            final String INSERT_QUERY = "INSERT INTO MY_TABLE  VALUES(GENERATED_ID_SEQ.NEXTVAL, :param1, :param2)";
            try
                {
                    MapSqlParameterSource parameters = new MapSqlParameterSource().addValue( "param1", obj.getField1() ).addValue( "param2",  obj.getField1() ) ;
                    final KeyHolder holder = new GeneratedKeyHolder();
                    this.namedParameterJdbcTemplate.update( INSERT_QUERY, parameters, holder, new String[] {"GENERATED_ID" } );
                    Number generatedId = holder.getKey();
                   // Note: USING holder.getKey("GENERATED_ID") IS ok TOO.
                    return generatedId.intValue();
                }
                catch( DataAccessException dataAccessException )
                {
        }
        }

С MySQL

CREATE TABLE `vets` (
  `id` int(4) unsigned NOT NULL AUTO_INCREMENT,
  `first_name` varchar(30) DEFAULT NULL,
  `last_name` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `last_name` (`last_name`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;


public @Data class Vet {
    private int id;
    private String firstname;
    private String lastname;
}

@Repository
public class VetDaoImpl implements VetDao {
/** Logger. */
private static final Logger LOGGER = LoggerFactory.getLogger(VetDaoImpl.class);

private static final String INSERT_VET = "INSERT INTO vets (first_name, last_name) VALUES (:first_name, :last_name)";

@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

@Override
public Number insertVet(final Vet vet) {
    MapSqlParameterSource paramSource = new MapSqlParameterSource();
    paramSource.addValue("first_name", vet.getFirstname());
    paramSource.addValue("last_name", vet.getLastname());
    KeyHolder keyHolder = new GeneratedKeyHolder();
    int nbRecord = namedParameterJdbcTemplate.update(INSERT_VET, paramSource, keyHolder, new String[] {"id" });
    LOGGER.info("insertVet: id ["+keyHolder.getKey()+"]");
    return nbRecord;
}
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top