DB Insert 시 자동생성된 id 를 알아내기
1.Mybatis
1
2
3
4
5
6
7
8
9
10
11
|
<insert id="insertStudent" parameterType="studentDto" useGeneratedKeys="true" keyProperty="id">
INSERT INTO student (
name,
grade,
phone
)
VALUES (
#{name},
#{grade},
#{phone}
)
|
사용하는 데이터베이스가 Auto Increment 가 된다면 (e.g. MySQL, Maria) 다음을 통해 id 를 알아낼 수 있다.
1
2
3
4
5
6
7
8
9
|
StudentDTO student = StudentDTO.builer().
.name("snack")
.grade(1)
.phone(01011112222)
.build();
mapper.insertStudent(student);
student.getId() // get ID
|
2. KeyHolder 를 사용한 방법
MyBatis 를 사용하지 않고, jdbcTemplate 를 사용하는 경우로,
이번 작성을 하게 만든 주인공이다. jdbcTemplate 을 사용한 경험이 거의 없기에, insert 후 pk id 를 어떻게 불러올까 했는데, 이런 방법이 있었다.
(알았어도, 학부 이후로 jdbcTemplate를 사용한 적이 없기에 까먹었을 수도..)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public Long saveStudent(final StudentDTO studnet) {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO student (name, grade, phone) VALUES (?, ?, ?)", new String[] {"id"});
pstmt.setString(1, student.getName());
pstmt.setInt(2, student.getGrade());
pstmt.setString(3, student.getPhone());
return pstmt;
}
}, keyHolder);
student.setId(keyHolder.getKey().longValue());
return student.getId();
}
|
다음과 같이 하면 생성된 student 의 id 를 알 수 있다.
(필자는 delete 와 update 에 대한 테스트 코드를 짜는데 id 가 필요했었다.)
덧붙여서 람다를 사용하면,
1
2
3
4
5
6
7
8
9
10
11
12
|
public Long saveStudent(final StudentDTO studnet) {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(conn -> {
PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO student (name, grade, phone) VALUES (?, ?, ?)", new String[] {"id"});
...
...
}, keyHolder);
student.setId(keyHolder.getKey().longValue());
return student.getId();
}
|
같이 표현할 수 있다.
(추가) 3. SimpleJdbcInsert 사용
keyHolder 에 대해 찾아보다가 이런 방식도 있다는 것을 알고 추가해본다.
(출처 : baeldung)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@Repository
public class StudentDaoImpl implements StudentDao {
private final SimpleJdbcInsert simpleJdbcInsert;
public StudnetDaoImpl(DataSource datasource) {
this.simpleJdbcInsert = new SimpleJdbcInsert(datasource)
.withTableName("student").usingGeneratedKeyColumns("id");
}
@Override
public Long saveStudent(final StudentDTO studnet) {
SqlParameterSource sqlParameterSource = new MapSqlParameterSource()
.addValue("name", student.getName())
.addValue("grade", student.getGrade())
.addValue("phone", student.getPhone()));
Number id = simpleJdbcInsert.executeAndReturnKey(sqlParameterSource);
student.setId(id.longValue());
return student.getId();
}
}
|
이름만큼 insert 에 최적화 되어 있는 것 같다. 특히 타입을 Object 로 받기 때문에 타입을 크게 타지 않는 것 같다.
(이전 PreparedStatement 를 사용할 때는 시간 값에 대해 timestamp 값으로 변경해서 넣어줘야 했는데, 이건 안해도 잘 들어간다.)