스프링 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에서 키를 돌려받는 가장 쉬운 방법은SimpleJdbcInsert
class. 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
'programing' 카테고리의 다른 글
Laravel의 Expulent ORM에서 테이블 데이터를 피벗하여 주문하는 방법 (0) | 2023.09.24 |
---|---|
이 C 또는 C++ 매크로가 전처리기에 의해 확장되지 않는 이유는 무엇입니까? (0) | 2023.09.24 |
워드프레스에서 새 게시물을 작성할 수 없는 이유는 무엇입니까?경고: 라인 716에서 /public_html/wp-admin/includes/post.php의 빈 값으로 기본 개체를 만듭니다. (0) | 2023.09.24 |
리터럴 문자열 및 함수 반환 값이 l값입니까, r값입니까? (0) | 2023.09.24 |
모든 도커 컨테이너를 정지시키고 제거합니다. (0) | 2023.09.24 |