programing

스프링 3 / Postgre에서 행 삽입에서 자동 생성 키 가져오기SQL 8.4.9

instargram 2023. 9. 24. 12:19
반응형

스프링 3 / Postgre에서 행 삽입에서 자동 생성 키 가져오기SQL 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

여기가 포스트그레입니다SQL 테이블:

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:

the current value (currval) of the sequence compte_idcompte_seq is not defined in this session, 생각은 했지만compte_idcompte_seq.NEXTVAL행을 삽입할 때 호출했어야 합니다.

편집:

행을 삽입할 때 자동 증분 값이 적절하게 생성됩니다.

감 잡히는 게 없어요?

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

Spring JDBC와 함께 INSERT에서 키를 돌려받는 가장 쉬운 방법은SimpleJdbcInsertclass. Spring Reference Guide의 Simple JdbcInsert를 사용하여 자동 생성 검색 섹션에서 예를 볼 수 있습니다.

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장 : 자동 생성 키 검색

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를 사용하면 파라미터가 이름으로 전달되고 코드가 더 읽기 쉽고 특히 큰 쿼리가 있을 때 오류가 발생하기 쉽기 때문에 이 솔루션이 좋습니다.

Keyholder 및 Postgre와 관련하여 알려진 몇 가지 있는 것 같습니다.SQL. 이 링크에서 해결 방법을 살펴보세요 Spring JDBC - 마지막으로 삽입된 ID

또한 데이터베이스 테이블을 직접 확인하여 레코드가 제대로 삽입되었는지(즉, PK로) 확인합니다.이것은 문제를 좁히는데 도움이 될 것입니다.

이 게시물, 특히 INSERT를 사용할 때 사용할 수 있는 답변을 살펴봅니다.반환 구문:

마지막으로 삽입된 행에서 값을 얻는 방법은?

Postgre에서 이 값을 얻는 가장 좋은 방법입니다.SQL은 네트워크 왕복을 한 번만 수행하고 서버에서 단일 원자 연산으로 수행됩니다.

저도 같은 문제가 있었는데 제 테이블 ID가 자동 증가하지 않는 것으로 나타났습니다.

저도 비슷한 문제에 직면했습니다.정확히 왜 이런 문제에 직면했는지는 모르겠지만 다행인 것은 아래 코드를 사용하여 이 문제를 해결할 수 있다는 것입니다.

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

누군가에게 도움이 되길 바랍니다.

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

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

만 왜 을 겪습니까?RETURNING:

INSERT INTO compte (prenom, nom, datenaissance, numtelephone)
VALUES (?, ?, ?, ?)
RETURNING id;

또는 JDBC를 사용할 경우:

try (PreparedStatement s = c.prepareStatement("""
    INSERT INTO compte (prenom, nom, datenaissance, numtelephone)
    VALUES (?, ?, ?, ?)
    RETURNING id;
    """
)) {
    s.setString(1, a.getSurname());
    s.setString(2, a.getName());
    s.setDate(3, a.getDob());
    s.setString(4, a.getPhone());

    try (ResultSet rs = s.executeQuery()) {
        while (rs.next())
            System.out.println("ID = " + rs.getLong(1));
    }
}

이 접근 방식은 분명히 Postgre입니다.SQL 특정(Firebird, MariaDB에서도 작동함).다른 SQL 방언을 사용하는 경우 다른 네이티브 구문이나 JDBC 접근 방식을 보여주는블로그 게시물이 도움이 될 수 있습니다.

언급URL : https://stackoverflow.com/questions/10597477/getting-auto-generated-key-from-row-insertion-in-spring-3-postgresql-8-4-9

반응형