@ Transactionalと@ Serviceまたは@ Controllerを使用
「通常、トランザクションはサービス層に置く必要があります。」
「通常のケースは、サービス層レベルで注釈を付けることです。」
「トランザクションはサービスレイヤーに属していると考えてください。これは、作業単位とユースケースを知っているトランザクションです。単一のトランザクションで連携する必要があるサービスに複数のDAOが注入されている場合、これが正しい答えです。」 [ソース]
@ serviceレイヤーで@transactionalを使用する欠点
たとえば、saveUser()とsaveEmail()の2つのメソッドがある場合(メールをデータベースに保存して後で送信するため-キューのように)、トランザクションで使用するメソッドsaveUserAndSendEmail(User user)をサービスに作成します。 [ソース]
次のように1つのSave Genericメソッドではなく、サービスレイヤーに多くのメソッドを作成することを意味します
_public <T> long save(T entity) throws DataAccessException {
Session session = sessionFactory.getCurrentSession();
long getGenVal=(Long) session.save(entity);
return getGenVal;
}
_
上記の解決策によれば、LOLをフォローするような多くの方法があることを意味します。
public <T> long saveAccount(T entity)....
public <T> long saveWithAuditLog(T entity, K entity1)....
public <T> long saveWithAuditLogAndEntries(T entity, K entity, M entity)....
この状況を克服する
@Controllerで@Transactionalを使用し、Generic Saveメソッドを作成して、この単純なsaveメソッドを使用してすべてのエンティティ/モデルを保存します。いずれかのメソッドが保存に失敗した場合、コントローラーのすべてのトランザクションは正常にロールバックされます。
@ Transactionalが@Controllerで使用されるようにするその他の状況
@Controllerで:
_pt.save(entity1);
pt.save(entity2);
int a = 2/0;
pt.save(entity3);
_
サービスの@Transactionalの場合、最初の2つのエンティティは正常に保存されましたが、3番目はすべてのトランザクションをロールバックしていません
場合、@ Controllerの@Transactionalは、例外が発生したときにすべてのトランザクションをロールバックします
スタックオーバーフローが「コントローラーでトランザクションを実行しないでください。それらをサービスレイヤークラスに配置してください」と尋ねた理由 [ソース]
あなたはベストプラクティスについて質問しています。@Transactional
はMVCロジックのデータの永続性を認識していないため、ベストプラクティスはサービスレイヤーで@Controller
をマークすることです。@Service
は、分析から生成されたユースケースに基づいて構築され、作業の単位について知っており、再利用の観点から考えると実現されます。Webコンテキストからデスクトップコンテキストに切り替えた場合(たとえば、またはその他の視覚的なフロントエンド)@Controller
レイヤーが存在しない場合、すべてがサービスレイヤーにカプセル化されているため、問題はありません。
A @Service
はコントラクトであり、プレゼンテーションレイヤーの変更で@Service
コードの書き換えを要求するべきではありません。
しかし、Springはトランザクションの境界をどこに置くかを気にしません。@Controller
を使用できますが、アプリケーションの保守が難しくなる可能性があります。
これが十分に明確であることを願っています。そうでなければ申し訳ありません。英語は私の母国語ではありません。
他の(非トランザクション)サービスを使用する上位層サービスを作成しました。そして、上位層のサービスはトランザクションです。
@Service
public class Service1Impl implements Servcie1 {
public Object method11(){...}
public Object method12(){...}
}
@Service
public class Service2Impl implements Service2 {
public method21(){...}
}
public interface Service1 {
public Object method11();
public Object method12();
}
public interface Service2 {
public Object method21();
}
@Transactional
public interface UpperLayerService {}
@Service
public class UpperLayerServiceImpl implements UpperLayerService {
@Autowired
private Service2 service2;
@Autowired
private Service3 service3;
public Object doWork() {
Object o1 = service1.method11();
Object o2 = service1.method12();
Object o3 = service2.method21();
....
Object res = null;//...Any code
return res;
}
}
コントローラーはビューレイヤーにしっかりと固定されており、いつでも変更できます。サービスは引き続き作業単位を所有しており、どのビューがアクセスしているかに関係なく、正しく動作するはずです。私の答え ここ はまだ立っています。