DB Insert 시 자동생성된 id 를 알아내기

· ☕ 2 min read · 👀... views

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 값으로 변경해서 넣어줘야 했는데, 이건 안해도 잘 들어간다.)

Share on

snack
WRITTEN BY
snack
Web Programmer


What's on this Page