복붙노트

[SPRING] 스프링 3에서 자동 삽입 된 키 얻기 / PostgreSQL 8.4.9

SPRING

스프링 3에서 자동 삽입 된 키 얻기 / PostgreSQL 8.4.9

행 삽입에서 자동 생성 된 ID를 검색하고 싶습니다. 그러나 NullPointerException이 발생합니다.

다음은 코드입니다.

long result = 0;
        final String SQL = "INSERT INTO compte (prenom, nom, datenaissance, numtelephone) "
                            + " VALUES(?,?,?,?)";
        KeyHolder keyHolder = new GeneratedKeyHolder();
        int row= this.jdbcTemplate.update(new PreparedStatementCreator(){
            public PreparedStatement createPreparedStatement(Connection connection)
                throws SQLException {
                PreparedStatement ps =connection.prepareStatement(SQL);
                ps.setString(1, a.getSurname());
                ps.setString(2, a.getName());
                ps.setDate(3, a.getDob());
                ps.setString(4, a.getPhone());
                return ps;
            }
        },keyHolder);

        if (row > 0)
            result = keyHolder.getKey().longValue(); //line 72

그리고 이것은 PostgreSQL 테이블입니다 :

CREATE TABLE compte
(
  idcompte serial NOT NULL,
  prenom character varying(25) NOT NULL,
  nom character varying(25) NOT NULL,
  datenaissance date NOT NULL,
  numtelephone character varying(15) NOT NULL,
  CONSTRAINT pk_compte PRIMARY KEY (idcompte )
);

PostgreSQL은 자동 생성 키를 지원하지만이 예외가 발생합니다 :

java.lang.NullPointerException
    at com.tante.db.JDBCUserAccountDAO.insertAccount(JDBCUserAccountDAO.java:72)

편집하다 : 자동 생성 된 키를 얻으려면이 시도했다 :

result = jdbcTemplate.queryForLong("select currval('compte_idcompte_seq')");

하지만 PSQLException 얻을 :

compte_idcompte_seq.NEXTVAL이라고 생각했지만이 세션에서는 compte_idcompte_seq 시퀀스의 현재 값 (currval)이 정의되어 있지 않습니다. 행을 삽입 할 때 호출해야합니다.

편집하다 :

행이 삽입되면 자동 증가 값이 올바르게 생성됩니다.

어떤 생각?

해결법

  1. ==============================

    1.

    KeyHolder holder = new GeneratedKeyHolder();
    
    getJdbcTemplate().update(new PreparedStatementCreator() {           
    
                    @Override
                    public PreparedStatement createPreparedStatement(Connection connection)
                            throws SQLException {
                        PreparedStatement ps = connection.prepareStatement(sql.toString(),
                            Statement.RETURN_GENERATED_KEYS); 
                        ps.setString(1, person.getUsername());
                        ps.setString(2, person.getPassword());
                        ps.setString(3, person.getEmail());
                        ps.setLong(4, person.getRole().getId());
                        return ps;
                    }
                }, holder);
    
    Long newPersonId = holder.getKey().longValue();
    

    최신 버전의 Postgres에서는 다음을 사용해야합니다.

    connection.prepareStatement(sql.toString(), 
        new String[] { "idcompte" /* name of your id column */ })
    

    대신에

    connection.prepareStatement(sql.toString(), 
        Statement.RETURN_GENERATED_KEYS);
    
  2. ==============================

    2.Spring JDBC로 INSERT에서 키를 얻는 가장 쉬운 방법은 SimpleJdbcInsert 클래스를 사용하는 것이다. 예제는 Spring Reference Guide의 SimpleJdbcInsert를 사용하여 자동 생성 키 검색 섹션에서 볼 수있다.

    Spring JDBC로 INSERT에서 키를 얻는 가장 쉬운 방법은 SimpleJdbcInsert 클래스를 사용하는 것이다. 예제는 Spring Reference Guide의 SimpleJdbcInsert를 사용하여 자동 생성 키 검색 섹션에서 볼 수있다.

  3. ==============================

    3.나는 Spring 3.1 + PostgreSQL 9.1을 사용하고 있는데 이것을 사용할 때

    나는 Spring 3.1 + PostgreSQL 9.1을 사용하고 있는데 이것을 사용할 때

        KeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(new PreparedStatementCreator() {
            public PreparedStatement createPreparedStatement(Connection connection)
                    throws SQLException {
                PreparedStatement ps = 
                    connection.prepareStatement(youSQL, 
                        Statement.RETURN_GENERATED_KEYS);
                ps.setString(1, post.name_author);
                ...
                return ps;
            }
        }, keyHolder);
        long id = keyHolder.getKey().longValue();
    

    나는이 예외가있다 :

     org.springframework.dao.InvalidDataAccessApiUsageException: 
    The getKey method should only be used when a single key is returned.  
    The current key entry contains multiple keys: ...
    

    그래서 나는 다음과 같이 바꿨다 :

    PreparedStatement ps = 
    connection.prepareStatement(youSQL, new String[]{"id"});
    

    여기서 "id"는

    id serial not null primary key
    

    그리고 문제가 해결되었습니다. 그래서 나는

    prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
    

    여기 없어. 공식 가이드는 13.2.8 절. 자동 생성 키 검색

  4. ==============================

    4.Sequence.nextval과 함께 NamedParameterJdbcTemplate을 사용하는 솔루션 :

    Sequence.nextval과 함께 NamedParameterJdbcTemplate을 사용하는 솔루션 :

            MapSqlParameterSource parameters = new MapSqlParameterSource();
            parameters.addValue("prenom", prenom);
            parameters.addValue("nom", nom);
            parameters.addValue("datenaissance", datenaissance);
            parameters.addValue("numtelephone", numtelephone);
    
        final String SQL = "INSERT INTO compte (idcompte,  prenom, nom, datenaissance, numtelephone) "
                            + " VALUES(compte_idcompte_seq.NEXTVAL, :prenom, :nom, :datenaissance, :numtelephone)";
    
            KeyHolder keyHolder = new GeneratedKeyHolder();
            NamedParameterJdbcTemplate namedJdbcTemplate = new NamedParameterJdbcTemplate(txManager.getDataSource());
            int nb = namedJdbcTemplate.update(SQL, parameters, keyHolder, new String[]{"idcompte"});
            Long generatedId = keyHolder.getKey().longValue();
    

    NamedParameterJdbcTemplate을 사용하면 매개 변수가 이름으로 전달되고 코드가 읽기 쉽고 오류가 발생하지 않기 때문에 특히 큰 쿼리가있을 때이 솔루션이 마음에 들다.

  5. ==============================

    5.Keyholder 및 PostgreSQL에는 몇 가지 알려진 문제가있는 것으로 보입니다. 이 링크에서 해결 방법을 살펴 보자. Spring JDBC - 마지막 삽입 ID

    Keyholder 및 PostgreSQL에는 몇 가지 알려진 문제가있는 것으로 보입니다. 이 링크에서 해결 방법을 살펴 보자. Spring JDBC - 마지막 삽입 ID

    또한 데이터베이스 테이블을 직접 점검하여 레코드가 올바르게 삽입되었는지 (즉 PK로) 확인하십시오. 이렇게하면 문제의 범위를 좁히는 데 도움이됩니다.

  6. ==============================

    6.이 게시물, 특히 INSERT ...를 사용하여 받아 들여지는 답변을 살펴보십시오. RETURNING syntax :

    이 게시물, 특히 INSERT ...를 사용하여 받아 들여지는 답변을 살펴보십시오. RETURNING syntax :

    마지막으로 삽입 된 행에서 값을 가져 오는 방법은 무엇입니까?

    이것은 PostgreSQL에서이 값을 얻는 가장 좋은 방법은 하나의 네트워크 왕복을 만들고 서버에서 단일 원자 연산으로 수행하기 때문입니다.

  7. ==============================

    7.나는 동일한 문제가 있었는데 내 테이블 ID가 자동으로 증가하지 않는 것으로 밝혀졌습니다.

    나는 동일한 문제가 있었는데 내 테이블 ID가 자동으로 증가하지 않는 것으로 밝혀졌습니다.

  8. ==============================

    8.나는 비슷한 문제에 직면했다. 왜 내가이 문제에 직면했는지 모르겠지만 좋은 점은 아래 코드를 사용하여이 문제를 해결해야한다는 것입니다.

    나는 비슷한 문제에 직면했다. 왜 내가이 문제에 직면했는지 모르겠지만 좋은 점은 아래 코드를 사용하여이 문제를 해결해야한다는 것입니다.

    final KeyHolder holder = new GeneratedKeyHolder();
    int status = myTemplate.update(yourInsertSQL, namedParameters, holder, new String[]{"PrimaryKeyColumnName"});
    

    희망은 누군가를 돕습니다.

  9. ==============================

    9.

    setGeneratedKeysColumnNames(new String[]{"column_name"});
    

    자동 생성 된 열의 이름을 설정하는 것을 잊지 마십시오.

  10. from https://stackoverflow.com/questions/10597477/getting-auto-generated-key-from-row-insertion-in-spring-3-postgresql-8-4-9 by cc-by-sa and MIT license