JPA:サービスと複数のリポジトリを使用するための正しい方法

マリアーノL:

私はJPAと春を使用するシステムを作りました。私はアカウントを処理する必要がある場合たとえば、私はリポジトリを使用します。

@Repository
public interface AccountRepository extends JpaRepository<Account, Long>

それから私は、リポジトリを使用してサービスを作成します。

class AccountServiceImpl implements AccountService {

  @Autowired
  private AccountRepository repository;

  @Transactional
  public Account save(Account account){
    return repository.save(account);
  }

...

今、私はアカウントのPOSTメソッドを扱うコントローラを作成しました:

@Controller
public class AccountController {

@Autowired    
private final accountService service;

@RequestMapping(value = "/account", method = RequestMethod.POST)
        public ModelAndView account(@Valid Account account, BindingResult bindingResult) {
    ...
service.save(account);

顧客、製品、連絡先などのために同じ

さて、私も彼のアカウント、連絡先データと製品との十分なcontaintsデータは、顧客を作成することを「登録」と呼ばれるクラス、(多くのデータを)持っていることとしましょう。登録にアクション「確認」はそれを行うために専用のいずれかです。

@RequestMapping(value = "/confirm", method = RequestMethod.POST)
    public ModelAndView confirmRegistration(@Valid Registration registration, BindingResult bindingResult) {

今、私の質問:コールする正しい方法は何であるのセーブすべてのリポジトリのための方法は?

1)万一、私は内のクラスを作成し、コントローラ、その後、作成された各クラスの保存メソッドを呼び出します。

@RequestMapping(value = "/confirm", method = RequestMethod.POST)
        public ModelAndView confirmRegistration(@Valid Registration registration, BindingResult bindingResult) {
...
customerService.save(customer);
accountService.save(account);
contactDataService.save(contactData);
productService.save(contactData);
...

2)お電話での各サービスのセーブRegistrationServiceに

class RegistrationServiceImpl implements RegistrationService {

  @Autowired
  private AccountService accountService;
  @Autowired
  private CustomerService customerService;
  ....

  @Transactional
  public void confirm(Registration registration){
  ... here I create the object
  customerService.save(customer);
  accountService.save(account);
  }

3)お電話でのそれぞれのセーブリポジトリ RegistrationServiceに:

class RegistrationServiceImpl implements RegistrationService {

  @Autowired
  private AccountRepository accountRepository;
  @Autowired
  private CustomerRepository customerRepository;
  ....

  @Transactional
  public void confirm(Registration registration){
  ... here I create the object
  customerRepository.save(customer);
  accountRepository.save(account);
  }

私は(1)を使用する必要があれば私がundertand。しかし、オプション(2)及び(3)について混乱。

再質問:

万一/ CAN Iは、サービス内の他のサービスを使用できますか?それとも私がサービスでのみリポジトリを使用する必要がありますか?

この説明をGoogleに正しい方法は何ですか?申し訳ありませんが、英語は私の母国語ではないと私はこの種の設計について質問するための正しい方法を見つけることができません。

ネイサン・ヒューズ:

サービスは常にトランザクションである必要はありませんが、あなたはJPAトランザクションとデータベースの仕事をやっている時にトランザクションが必ずあなたの変更が同時に起こっている他の作業からの干渉を受けることなく、予想通りにコミットさせるために、極めて重要です。春はそれが簡単にあなたがそれらを最大限に活用することができますので、必ず取引を理解させる、あなたのサービスがトランザクションにすることができます。

あなたができるサービス内のサービスを使用し、あなたはどちらを使用して同じトランザクションをトランザクション伝播を設定することができたり、彼らが別のトランザクションを使用することができ、これらのいずれかの有効な場合があります。しかし、私はあなたがここで何をやっているやっていないお勧めします。

サービスは、ビジネス・ロジック、あなたは(オールオアナッシング)トランザクションする必要があること、特に、ビジネスロジックを置く場所です。これは、サービスメソッドは、いくつかの特定の部分を再生し、ユーザーが実行したアクションあるよう、機能に応じてサービスにあなたのロジックを整理する意味があります。

しかし、エンティティの種類ごとにサービスを持つことは本当に便利ではないと私はそれに対してお勧めします。サービスは、リポジトリの任意の番号を持つことができ、あなたは、独自のサービスで各1をラップする必要はありません。(彼らはあなたのフレームワークの特徴を示す、およびビジネス・ロジックを最小限に抑えたい。しかし、実際のアプリケーションは、ビジネスロジックの多くを持っている傾向があるためだと、チュートリアルは企業固有のサービスを表示する、またはそれらを完全にサービス層をスキップすることがあります。)

それぞれが独自のトランザクションを使用して他の手段の後に、コントローラ1でそれらを呼び出す:あなたは企業固有のサービスをやっていることの一つの問題。トランザクションを作成すると遅く、別のものを持つことは可能なデータの不整合にあなたを開きます。1つのトランザクション内でビジネスロジックを持つことは、あなたのトランザクション分離レベルに関連したものだけに一貫性の問題へのあなたの露出を制限します。

また、私はサービスがDTOSとエンティティとの間の変換されなければならないという考えに反対します。一度あなたがDTOの必要性を見つけるかもしれないが、それは日常的であるべきではないながら。JSPを使用したWebアプリケーションの場合、またはあなたが喜んリクエスト属性などのエンティティを追加し、直接テンプレートの使用にそれらを聞かせすることができるかもしれthymeleaf。お使いのコントローラがJSONを返すために必要がある場合は、エンティティから直接JSONを生成するか、DTOを持っている方が良いかもしれmessageconverterをフックアップすることができるかもしれません。コードのようなものが脆くでエラーが発生しやすいため、ビジネス機能の実装に焦点を維持し、ホルダーの異なる種類にホルダーの一種からデータを移動しないようにしてください。

コントローラとサービス間の違いのために私は答えを持っているここここ

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=173297&siteId=1