Перейти к основному содержимому

Получение автоматически сгенерированных ключей в Spring JDBC

· 3 мин. чтения

1. Введение

В этом кратком руководстве мы рассмотрим возможность получения автоматически сгенерированного ключа после вставки сущностей при работе с Spring JDBC .

2. Зависимости Maven

Сначала нам нужно иметь зависимости spring-boot-starter-jdbc и H2 , определенные в нашем pom.xml :

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

Мы можем проверить последнюю версию этих двух зависимостей на Maven Central: spring-boot-starter-jdbc и h2 .

3. Получение автоматически сгенерированного ключа

3.1. Сценарий

Давайте определим таблицу sys_message , которая имеет 2 столбца: id (автоматически сгенерированный ключ) и message :

CREATE TABLE IF NOT EXISTS sys_message (
id bigint(20) NOT NULL AUTO_INCREMENT,
message varchar(100) NOT NULL,
PRIMARY KEY (id)
);

3.2. Использование шаблона Jdbc

Теперь давайте реализуем метод, который будет использовать JDBCTemplate для вставки новой записи и возврата автоматически сгенерированного идентификатора.

Поэтому мы будем использовать метод JDBCTemplate update() , который поддерживает извлечение первичных ключей, сгенерированных базой данных. Этот метод принимает экземпляр интерфейса PrepareStatementCreator в качестве первого аргумента, а другим аргументом является KeyHolder.

Поскольку интерфейс PrepareStatementCreator является функциональным интерфейсом, где его метод принимает экземпляр java.sql.Connection и возвращает объект java.sql.PreparedStatement , для простоты мы можем использовать лямбда-выражение:

String INSERT_MESSAGE_SQL 
= "insert into sys_message (message) values(?) ";

public long insertMessage(String message) {
KeyHolder keyHolder = new GeneratedKeyHolder();

jdbcTemplate.update(connection -> {
PreparedStatement ps = connection
.prepareStatement(INSERT_MESSAGE_SQL);
ps.setString(1, message);
return ps;
}, keyHolder);

return (long) keyHolder.getKey();
}
}

Стоит отметить, что объект keyHolder будет содержать автоматически сгенерированный ключ, возвращаемый методом JDBCTemplate update() .

Мы можем получить этот ключ, вызвав keyHolder.getKey().

Кроме того, мы можем проверить метод:

@Test
public void
insertJDBC_whenLoadMessageByKey_thenGetTheSameMessage() {
long key = messageRepositoryJDBCTemplate.insert(MESSAGE_CONTENT);
String loadedMessage = messageRepositoryJDBCTemplate
.getMessageById(key);

assertEquals(MESSAGE_CONTENT, loadedMessage);
}

3.3. Использование SimpleJdbcInsert

В дополнение к JDBCTemplate мы также можем использовать SimpleJdbcInsert для достижения того же результата.

Следовательно, нам нужно инициализировать экземпляр SimpleJdbcInsert :

@Repository
public class MessageRepositorySimpleJDBCInsert {

SimpleJdbcInsert simpleJdbcInsert;

@Autowired
public MessageRepositorySimpleJDBCInsert(DataSource dataSource) {
simpleJdbcInsert = new SimpleJdbcInsert(dataSource)
.withTableName("sys_message").usingGeneratedKeyColumns("id");
}

//...
}

Следовательно, мы можем вызвать метод executeAndReturnKey класса SimpleJdbcInsert , чтобы вставить новую запись в таблицу sys_message и вернуть автоматически сгенерированный ключ :

public long insert(String message) {
Map<String, Object> parameters = new HashMap<>(1);
parameters.put("message", message);
Number newId = simpleJdbcInsert.executeAndReturnKey(parameters);
return (long) newId;
}

Кроме того, мы можем довольно просто проверить этот метод:

@Test
public void
insertSimpleInsert_whenLoadMessageKey_thenGetTheSameMessage() {
long key = messageRepositorySimpleJDBCInsert.insert(MESSAGE_CONTENT);
String loadedMessage = messageRepositoryJDBCTemplate.getMessageById(key);

assertEquals(MESSAGE_CONTENT, loadedMessage);
}

4. Вывод

Мы рассмотрели возможность использования JDBCTemplate и SimpleJdbcInsert для вставки новой записи и возврата автоматически сгенерированного ключа.

Как всегда, мы можем найти реализацию этой статьи на Github .