あなたの例では、リポジトリがある@Transactional
かどうかによって異なります。
はいの場合、サービスは(そのままで)あなたのケースでは使用しないでください@Transactional
(使用する意味がないため)。@Transactional
別のテーブル/リポジトリを処理するサービスにさらにロジックを追加する予定がある場合は、後で追加できます。その場合、それを使用するポイントがあります。
@Transactional
いいえの場合 -たとえば、まだ交換されていないものを読んでいないなど、分離に問題がないことを確認したい場合は、サービスを使用する必要があります。
--
一般的なリポジトリについて話している場合 (crud コレクション インターフェースとして):
- 私は言います:いいえ、@Transactionalを使用しないでください
理由:リポジトリがビジネス コンテキストの外にあり、伝播や分離 (ロックのレベル) を認識すべきではないと考えられる場合。どのトランザクション コンテキストに関与する可能性があるかを推測することはできません。
リポジトリは「ビジネスレス」です(そう信じている場合)
たとえば、リポジトリがあるとします。
class MyRepository
void add(entity) {...}
void findByName(name) {...}
MyServiceなどのビジネスロジックがあります
class MyService() {
@Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.SERIALIZABLE)
void doIt() {
var entity = myRepository.findByName("some-name");
if(record.field.equal("expected")) {
...
myRepository.add(newEntity)
}
}
}
つまり、この場合:MyService
リポジトリを何に含めたいかを決定します。
findByName()
この場合、propagation="Required" を使用すると、両方のリポジトリ メソッドが確実add()
に実行され、単一のトランザクションに関与し、isolation="Serializable" を使用すると、誰もそれを妨害できないようになります。get() & add() が関与するテーブルのロックを保持します。
しかし、他のサービスは MyRepository を別の方法で使用したい場合があり、トランザクションにまったく関与せず、findByName()
メソッドを使用し、現時点で見つけられるものを読み取るための制限に関心がないと言います。
- リポジトリを常に有効なエンティティ (ダーティ リードなし) などを返すものとして扱う場合 (ユーザーが誤って使用するのを防ぐ)、はいと言います。つまり、リポジトリは分離の問題 (同時実行性とデータの一貫性) に対処する必要があります。たとえば、次のようになります。
(リポジトリ) にadd(newEntity)
、同じ名前のエンティティが既に存在することを最初に確認するときに確認する必要があります。存在する場合は、すべて 1 つのロック作業単位に挿入します。(上記のサービスレベルで行ったことと同じですが、この責任をリポジトリに移動しません)
たとえば、「進行中」状態の同じ名前のタスクが 2 つ存在することはありません (ビジネス ルール)。
class TaskRepository
@Transactional(propagation=Propagation.REQUIRED,
isolation=Isolation.SERIALIZABLE)
void add(entity) {
var name = entity.getName()
var found = this.findFirstByName(name);
if(found == null || found.getStatus().equal("in-progress"))
{
.. do insert
}
}
@Transactional
void findFirstByName(name) {...}
2 つ目は、DDD スタイルのリポジトリに似ています。
次の場合は、さらにカバーする必要があると思います。
class Service {
@Transactional(isolation=.., propagation=...) // where .. are different from what is defined in taskRepository()
void doStuff() {
taskRepository.add(task);
}
}