2016-12-07 3 views
2

Java 8 forEachループ内でSpring Data JPAリポジトリを使用できますか?スレッドセーフですか?Java 8 forEachループ内でSpring Data JPAリポジトリを使用するのはスレッドセーフですか?

public interface MajorModOptRepository extends CrudRepository<MajorModOpt, Long> { 
    Set<MajorModOpt> findManyByManCodeAndModCode(String manCode, String modCode); 
} 

そしてここで、foreachループです:

@Component 
public class MajorModOptsHelper { 

    @Autowired 
    private MajorModOptRepository majorModOptRepository; 

    public void setMajorOpts(@NonNull List<Vehicle> vehicles) { 
     vehicles.forEach(this::setMajorOpts); 

    } 

    // This method is called by above forEach 
    public void setMajorOpts(Vehicle vehicle) { 
     ... 
     // Repository method is called here 
     Set<MajorModOptVO> knownOpts = majorModOptRepository.findManyByManCodeAndModCode(vehicle.getManCode(), vehicle.getModCode()); 
     ... 
    } 
} 

は、事前にありがとうございます。

+2

コレクションに対して 'forEach'を呼び出すときに、マルチスレッドが含まれていません。念頭に置いておくべきことは、 'ArrayList'や' HashSet'のような特定のコレクションは反復処理中に変更してはいけませんが、 'Iterator'ベースの' for'ループを使用する場合は同じです。 – Holger

+2

スレッドセーフです。しかし、それにもかかわらず、私はあなたがしようとしているヘルルワの悪い事にもっと惹かれます。そして、それは 'forEach'の中で' findManyByManCodeAndModCode'メソッドを呼び出すだけです。 :) –

答えて

3

トレッドセーブです。マルチスレッドは必要ありません。

あなたが気にするべき唯一の事柄は、それぞれfindManyByManCodeAndModCode(あなたがそれを望む場合を除く)ごとに新しい取引を開くことではありません。これを解決する最も簡単な方法はをsetMajorOpts(@NonNull List<Vehicle> vehicles)メソッドに追加することです。

+2

さらに悪いことに、彼は 'forEach'でリポジトリメソッドを起動しています。これは基本的に' N + 1'の問題に相当します。 –

+0

@Branislav Lazic:あなたはそうですが、その質問の範囲はスレッド化されていて、おそらく問題のようにスレッド化されていました。パフォーマンスはその問題の範囲にはありませんでした。 **あなたのコメントは価値があると思う、**。とにかく、パフォーマンスに関する重要な正当な理由は、コンテキストに関する知識があれば実現できます。たとえば、車両のリストが典型的な2または3アイテムしかない場合、帽子の最適化よりも時間が早すぎる可能性があります。 – Ralph

2

現在のforEach実装または従来のfor-loopでは、コードはスレッドセーフです。

あなたは概念的に次の2つのメソッドにList<Vehicle>save操作を分割しているので、(プログラムまたは@Transactional境界を介して実行)の代わりにトランザクション境界を心配する必要があります。 Vehiclesaveのいずれかの操作が失敗した場合はどうなりますか? Propagation.REQUIREDのデフォルト値では、操作全体がロールバックされますが、2台目の車両saveの操作がPropagation.REQUIRES_NEWの場合、前のすべての事前障害Vehicleはすべてコミット(=コミット)されています。

+2

実際、あなたがここで心配すべき唯一の事は、コンストラクタインジェクション(右)ではなく、フィールドインジェクション(悪い)の使用です。 –

+1

'setMajorOpts(@NonNullリストビークル)での単純な' @ Transactional'アノテーションや、作業ユニットの周りにブロックを構築するもっと外側のメソッドがその問題を解決します。 – Ralph

+1

@Engineer Dollery - 同意します。しかし、それが心配する唯一の事ではありません。 OPの提示されたコードに従って、ここではトランザクション境界が重要です。 – dimitrisli

関連する問題