Obtaining Auto-generated Keys in Spring JDBC – 在Spring JDBC中获取自动生成的密钥

最后修改: 2018年 4月 17日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In this quick tutorial, we’ll explore the possibility of getting the auto-generated key after inserting entities when working with Spring JDBC.

在这个快速教程中,我们将探讨在使用Spring JDBC时,插入实体后获得自动生成的密钥的可能性。

2. Maven Dependencies

2.Maven的依赖性

At first, we need to have spring-boot-starter-jdbc and H2 dependencies defined in our pom.xml:

首先,我们需要在spring-boot-starter-jdbcH2依赖中定义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>

We can check out the latest version of those two dependencies on Maven Central: spring-boot-starter-jdbc and h2.

我们可以在Maven中心查看这两个依赖项的最新版本。spring-boot-starter-jdbch2

3. Getting the Auto-Generated Key

3.获得自动生成的密钥

3.1. The Scenario

3.1.场景

Let’s define a sys_message table which has 2 columns: id (auto-generated key) and message:

让我们定义一个sys_message表,它有两列。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. Using the JdbcTemplate

3.2.使用JdbcTemplate

Now, let’s implement a method which will use JDBCTemplate to insert the new record and return the auto-generated id. 

现在,让我们实现一个方法,它将使用JDBCTemplate插入新的记录并返回自动生成的id。

Therefore, we’ll use the JDBCTemplate update() method which supports the retrieval of primary keys generated by the database. This method takes an instance of the PrepareStatementCreator interface as the first argument and the other argument is the KeyHolder. 

因此,我们将使用JDBCTemplate update()方法,它支持检索由数据库生成的主键。这个方法将PrepareStatementCreator接口的一个实例作为第一个参数,另一个参数是KeyHolder。键入者

Since the PrepareStatementCreator interface is a FunctionalInterface where its method accepts an instance of java.sql.Connection and return a java.sql.PreparedStatement object, for simplicity, we can use a lambda expression:

由于PrepareStatementCreator接口是一个FunctionalInterface,它的方法接受一个java.sql.Connection的实例,并返回一个java.sql.PreparedStatement对象,为了简单起见,我们可以使用一个lambda表述。

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();
    }
}

It’s worth noting that the keyHolder object will contain the auto-generated key return from the JDBCTemplate update() method.

值得注意的是,keyHolder对象将包含从JDBCTemplate update() 方法中返回的自动生成的键

We can retrieve that key by calling keyHolder.getKey().

我们可以通过调用keyHolder.getKey()来检索该密钥。

Besides, we can verify the method:

此外,我们可以验证该方法。

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

    assertEquals(MESSAGE_CONTENT, loadedMessage);
}

3.3. Using SimpleJdbcInsert

3.3.使用SimpleJdbcInsert

In addition to the JDBCTemplate, we also can use SimpleJdbcInsert to achieve the same result.

除了JDBCTemplate,我们还可以使用SimpleJdbcInsert来实现同样的结果。

Hence, we need to initialize an instance of the SimpleJdbcInsert:

因此,我们需要初始化一个SimpleJdbcInsert的实例。

@Repository
public class MessageRepositorySimpleJDBCInsert {

    SimpleJdbcInsert simpleJdbcInsert;

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

Consequently, we can call the executeAndReturnKey method of the SimpleJdbcInsert to insert a new record to sys_message table and get back the auto-generated key:

因此,我们可以调用SimpleJdbcInsertexecuteAndReturnKey方法,向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;
}

Furthermore, we can verify that method quite simply:

此外,我们可以很简单地验证这个方法。

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

    assertEquals(MESSAGE_CONTENT, loadedMessage);
}

4. Conclusion

4.结论

We’ve explored the possibility of using JDBCTemplate and SimpleJdbcInsert for inserting a new record and getting the auto-generated key back.

我们已经探讨了使用JDBCTemplateSimpleJdbcInsert插入新记录并获得自动生成的键的可能性。

As always, we can find the implementation of this article over on Github.

一如既往,我们可以在Github上找到本文的实现over