[Spring JDBC] Generated keys not requested

함궈·2022년 7월 27일

스프링

목록 보기
4/5
post-thumbnail

insert 메서드를 실행시키면 MEMBER 테이블에 값은 저장되지만 다음과 같은 TransientDataAccessResourceException이 발생했다.

Generated keys not requested.
You need to specify Statement.RETURN_GENERATED_KEYS to Statement.executeUpdate(),
Statement.executeLargeUpdate() or Connection.prepareStatement().

키값이 제대로 생성되지 않았던 것 같다.

  • 방법 1.
    생성한 PreparedStatementCreatorFactory 객체에setReturnGeneratedKeys(true) 로 설정.
public void setReturnGeneratedKeys(boolean returnGeneratedKeys)
PreparedStatementAuto-Generated Key를 반환할 수 있도록 함.
  • 방법 2.
    생성한 PreparedStatementCreatorFactory 객체에 setGeneratedKeysColumnNames(String ... names) 설정.
public void setGeneratedKeysColumnNames(String... names)
auto-generated key들의 컬럼 이름들을 나열해 PreparedStatement에게 알려줌?

어떻게, 어느 순서로 실행되나요?

  1. newPreparedStatementCreator() 호출

  2. PreparedStatementCreator 인터페이스를 구현한 PreparedStatementCreatorImpl 반환.

  3. jdbcTemplate.update() 메소드 호출

  4. 인자로 전달받은 PreparedStatementCreator객체를 인자로 jdbcTemplate.execute()메서드 호출.

  5. PreparedStatementCreator.createPreparedStatement() 호출

  6. createPreparedStatement() 메서드를 살펴보자.
    PreparedStatementCreatorFactory클래스에 정의된 코드를 살펴본다.

@Override
		public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
			PreparedStatement ps;
			if (generatedKeysColumnNames != null || returnGeneratedKeys) {
				if (generatedKeysColumnNames != null) {
					ps = con.prepareStatement(this.actualSql, generatedKeysColumnNames);
				}
				else {
					ps = con.prepareStatement(this.actualSql, PreparedStatement.RETURN_GENERATED_KEYS);
				}
			}
			/*
            생략...
            */
			return ps;
		}

createPreparedStatement() 메서드의 구현부를 살펴보면, Autogenerated 컬럼의 이름들을 알려주던지, int 자료형인autoGeneratedKeys를 두번째 파라미터로 넣어주는 것을 알 수 있다.


적용

public void insert(final Member member){
        KeyHolder keyHolder = new GeneratedKeyHolder();
        PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(
                "insert into MEMBER(EMAIL, PASSWORD, NAME, REGDATE) values(?, ?, ?, ?)",
                Types.VARCHAR,
                Types.VARCHAR,
                Types.VARCHAR,
                Types.TIMESTAMP
        );
        /* 
        방법 1. pscf.setReturnGeneratedKeys(true);
        방법 2. pscf.setGeneratedKeysColumnNames("ID");
        */
        PreparedStatementCreator psc = pscf.newPreparedStatementCreator(Arrays.asList(member.getEmail(), member.getPassword(), member.getName(), member.getRegisterDateTime()));
        jdbcTemplate.update(psc, keyHolder);

        Number keyValue = keyHolder.getKey();
        member.setId(keyValue.longValue());
    }

참고 : https://blog.naver.com/chelsea2936/222209106611

0개의 댓글