行挿入から自動生成された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
を取得します:
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
クラスを使用することです。 Spring Reference Guideの SimpleJdbcInsertを使用して自動生成キーを取得する というタイトルのセクションに例を見ることができます。
私はSpring3.1 + PostgreSQL9.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);
ここではありません。公式ガイドは here 、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を使用すると、特に大きなクエリがある場合に、パラメーターが名前で渡され、コードが読みやすくエラーが発生しにくいため、このソリューションが気に入っています。
キーホルダーとPostgreSQLにはいくつかの既知の問題があるようです。このリンクの回避策をご覧ください Spring JDBC-Last Inserted id
また、データベーステーブルを直接チェックして、レコードが適切に挿入されているかどうかを確認します(PKを使用)。これは問題を絞り込むのに役立ちます。
この投稿、特にINSERT ... RETURNING構文を使用することで受け入れられている答えをご覧ください。
これはPostgreSQLでこの値を取得するための最良の方法です。ネットワークラウンドトリップを1つだけ実行し、サーバー上で単一のアトミック操作として実行されるためです。
私は同じ問題を抱えていましたが、テーブルIDが自動インクリメントされていませんでした。
同様の問題に直面しました。この問題に正確に直面した理由はわかりませんが、以下のコードを使用してこれを解決するのは良いことです:
final KeyHolder holder = new GeneratedKeyHolder();
int status = myTemplate.update(yourInsertSQL, namedParameters, holder, new String[]{"PrimaryKeyColumnName"});
それが誰かを助けることを願っています。
setGeneratedKeysColumnNames(new String[]{"column_name"});
自動生成された列の名前を設定することを忘れないでください。