8

simpleJdbcTemplateを使用してデータをデータベースに入れています。

simpleJdbcTemplate.update("insert into TABLE values(default)");

単体テストの目的でデータが必要ないため、データを入れたくありません。

挿入された行からIDを取得するにはどうすればよいですか?現在のシーケンス値を取得できますが、他の誰かが挿入を行うと、次のシーケンス値が取得されます。

simpleJdbcTemplateを使用して行を挿入し、IDを取得する方法はありますか?updateメソッドは、挿入された行の数を再調整します。IDが必要です。ご協力ありがとうございました。

4

8 に答える 8

5

答えはもう見つかりましたか?そうでない場合は、SimpleJdbcInsert代わりに使用してみてください。例えば:

SimpleJdbcInsert sji = new SimpleJdbcInsert(dataSource)
    .withTableName(TableName)
    .usingColumns(new String[]{your columns})
    .usingGeneratedKeyColumns(you auto-increment id colums);

次に取得する

sji.executeAndReturnKey(args).longValue();
于 2011-02-11T06:07:10.447 に答える
4

特定のRDBMS製品に縛られることなく、IDを簡単に取得するには、シーケンスを手動で処理する必要があります。

つまり、デプロイメント固有DataFieldMaxValueIncrementerのBeanを指定し、それをデータベース処理クラスに注入する必要があります。これは、で行う可能性が最も高い場合と同じですDataSource。Beanの定義は次のようになります(この例はPostgreSQL用です)

<bean id="incrementer" class="org.springframework.jdbc.support.incrementer.PostgreSQLSequenceMaxValueIncrementer">
    <property name="dataSource" ref="dataSource" />
    <property name="incrementerName" value="seq_name" />
</bean>

次に、クラスにインクリメント機能がある場合、コードでそれを使用して、次のようにid値を取得できます。

public long saveBeanAndReturnId(Bean b) {
    long id = incrementer.nextLongValue();
    simpleJdbc.update("...");
    return id;
}
于 2010-02-10T08:37:21.347 に答える
4

見た目ほどタフだとは思いません.. :-O

Y次のようなことを試してはいけません:

int newID = simpleJdbcTemplate.queryForInt("INSERT INTO TABLE(Column_Names) 
                                            values (default) 
                                            RETURNING ID");

newIDには、新しく挿入された行 ID が含まれます

乾杯..!!:)

于 2011-12-27T14:53:30.180 に答える
1

この質問に答えてください:あなたはあなたのテストで何を達成しようとしていますか?更新がエラーなしで実行されることを確認しますか?毎回新しいIDを取得するということですか?テーブルが存在すること?

答えに応じて、テストを変更する必要があります。ステートメントの構文が正しいことを知りたいだけの場合は、ステートメントを実行する以外に何もする必要はありません(エラーが発生してテストが失敗すると、例外がスローされます)。

毎回新しいIDを取得するようにしたい場合は、シーケンスを2回クエリし、2番目の値が最初の値と異なることを確認する必要があります。

新しい一意のIDを持つ行が挿入されていることを確認する場合は、挿入を実行して1が返されることを確認します。機能する場合は、主キー(ID)に違反していないこと、および行が挿入されました。したがって、「一意のIDで追加」メカニズムが機能する必要があります。

[編集]Oracleには、作成したばかりのIDを返す手段がないため、新しい行にIDを追加するトリガーをテストする方法はありません。シーケンスを読み取ることはできますがnextval-1、トリガーが見たのと同じ結果が得られるという保証はありません。

試すことはできselect max(ID)ますが、クエリを実行する前に(デフォルトのトランザクションレベルを使用して)他の誰かが別の行を挿入してコミットすると、失敗する可能性がありますREAD_COMMITTED

したがって、トリガーを取り除き、他の人が使用する標準の2ステップ(「新しいIDを取得」と「新しいIDで挿入」)アルゴリズムを使用することを強くお勧めします。これにより、テストがより簡単になり、脆弱性が低くなります。

于 2010-02-10T08:37:49.843 に答える
1

id最初に適切なからクエリを実行しsequence、次にそれをid挿入ステートメントで指定する必要があります。それと同じくらい簡単です。

さらに、おそらく単体テストではなく、統合テストと呼んでいます。このSOスレッドを参照して、統合テストとIDに関するアイデアを得ることができます。

[コメント後に編集]

その場合、そのトリガーを取り除きます。そして、を作成する前にidsequenceを直接取得しますinsert

さて、SELECT... FOR UPDATEテーブルでを起動し、最後のを取得して、idそれを1ずつインクリメントできます。idシーケンシャルでない場合は、そうではないと思いますが、ROWIDOracleAFAIKに固有のを保持できます。そして、それをid使用するためのクエリを実行します。確かに、そのすべての種類の回避策。

注: AaronDigullaの投稿をご覧になることを強くお勧めします。そのいずれかで十分かどうかを確認してください。

于 2010-02-10T08:30:43.773 に答える
1

simpleJdbcTemplate は廃止され、NamedParameterJdbcTemplate が優先されます。

Pello X は正しい答えを持っていますが、彼の提出物はわかりにくいものです。簡略化:

NAME という列と bigint 型の ID という生成された主キーを持つ SAMPLE という非常に単純なテーブルがあるとします。

MapSqlParameterSource namedParameters = new MapSqlParameterSource().addValue("name", name);

KeyHolder keyHolder = new GeneratedKeyHolder();
int numberOfAffectedRows = namedParameterJdbcTemplate.update("insert into SAMPLE(name) values(:name)", namedParameters, keyHolder);

return numberOfAffectedRows == 1 ? keyHolder.getKey().longValue() : -1L;

これは、更新で生成された唯一のキーを返すか、複数の行が影響を受けた場合は -1 を返します。

生成されたキーは 1 つしかないため、列名は気にしませんでした。

生成されたキーが複数ある場合は、http://docs.spring.io/spring/docs/3.2.7.RELEASE/javadoc-api/org/springframework/jdbc/support/KeyHolder.html#getKeysを調べてください。 %28%29

于 2014-02-07T14:37:34.173 に答える