私は、データベースから読み取るSpringトランザクションを持っています。探しているものが存在しない場合は、それを作成します。例:この方法は、二回同時に呼び出されると2つの同じ読み込み+書き込み同時トランザクションをお互いに待たせることができますか?
@Transactional
public int getUserIdCreateIfNotExistent(String email) throws Exception {
try {
return jdbcTemplate.queryForObject("SELECT id FROM users WHERE email = ?", Integer.class, email);
} catch (IncorrectResultSizeDataAccessException e) {
Thread.sleep(10000);
return jdbcTemplate.queryForObject("INSERT INTO users (email) values(?) RETURNING id", Integer.class, email);
}
}
それはDBに同じメールを持つ2人の別個のユーザを有するもたらすであろう(一意の電子メールには制約がなく、これは単に例示の目的のためのものです)。
最初のトランザクションを待ってから、1人のユーザーしか作成されないようにします。私はトランザクションの隔離レベルをIsolation.SERIALIZABLE
に変更しようとしましたが、最後にロールバックするトランザクションが行われます。
EDIT: 誰もがまたはそのような何かを使用してJavaでのソリューションをロック示唆する前に、この方法は、Webアプリケーションの一部であり、特定のエンドポイントがヒットした時に呼び出されることを理解することが重要です。 Webアプリケーションは複数の異なるマシン上で実行され、負荷分散されており、エンドポイントが同時に2回呼び出されると問題が発生します。これは、というコードが、2台の異なるマシン上で並列に実行され、異なるマシン上の同じDBと対話することを意味します。。
分離レベルは助けにはなりません。ユニークな制約に遭遇しない限り –