spring jparepositoryメソッドがスレッドセーフであるかどうか不思議に思っていましたが、スタックフロー記事(Is a Spring Data (JPA) Repository thread-safe? (aka is SimpleJpaRepository thread safe))を読みました。そこから、私はリポジトリメソッドがスレッドセーフであることを理解してから、スレッドセーフティをテストするために1つのPOCを作成しました。私は1つのリポジトリにFormRepositoryと言って、JpaRepositoryを拡張している 'フォーム'エンティティのCRUD操作を行いました。 DAOから、フォームオブジェクトを作成し、そのidを手動で設定してから、フォームオブジェクトを保存する100個のスレッドを呼び出すだけでした。以下はSpring JpaRepositoryメソッドのスレッドセーフティについて
参照のためのコードである: -
@Repository
public interface FormRepository extends JpaRepository<Tbldynamicform, Long> {
Tbldynamicform save(Tbldynamicform tblform);
@Query("SELECT max(tblform.formid) FROM Tbldynamicform tblform")
Optional<Integer> findMaxId();
}
......End of Repository above and start of DAO below...
@Component
public class DynamicFormDAO implements DynamicFormDAO {
@Inject
private FormRepository formRepository;
public void testThreadSafety() throws Exception {
List<Callable<Integer>> tasks = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
tasks.add(() -> {
try {
Tbldynamicform tbldynamicform = new Tbldynamicform();//Set all the required fields for form
if (tbldynamicform.getFormid() == null)
tbldynamicform.setFormid(findFormID());
Tbldynamicform form = formRepository.save(tbldynamicform);
return form.getFormid();
} catch (Exception e) {
e.printStackTrace();
}
return null;
});
}
ExecutorService executor = Executors.newFixedThreadPool(100);
executor.invokeAll(tasks);
}
private int findFormID() throws Exception {
Optional<Integer> id = formRepository.findMaxId();
if (id != null && id.isPresent() && id.get() != null) {
int generatedId = id.get().intValue();
return ++generatedId;
}
return 0;
}
}
私はこれを行うと、私は、フォームのリポジトリメソッドはスレッドセーフですが、何とか私は、SQL dataintegrityviolationexceptionがいくつか取得していますので、物事が正常に動作していることを想定しましたいくつかのレコードの挿入を失敗させるログの回数。参照のための以下のエラー: -
org.springframework.dao.DataIntegrityViolationException:ステートメントを実行できませんでした。 SQL [n/a];制約["PRIMARY ON ON PUBLIC.TBLDYNAMICFORM(FORMID)"; SQL文: Tbldynamicformに挿入(ClientIDを、copyfromexisting、のCreationDate、formdesc、formmode、フォーム名、formtemplate、formtitle、procutype、ステータス、フォームID)の値(、、、、...
これが作られたのか???私はこれがスレッドの安全性の問題か他のいくつかの問題かどうか考えていますが、私のDAOで作成したすべてのtbldynamicformオブジェクトはスレッドスタックに残っています。
私がsetIdを実行して同期ブロックに保存すると、すべて正常に動作しますが、それは私の意図ではなく、リポジトリメソッドがスレッドセーフであれば必要ではありません。
エキスパート、何か助けてください?
はい、私は同じことを考えました。なぜなら、私がsaveとfindformIdをsyncronizedブロックに置くと、すべて正常に動作するからです。 –