12

私の他の質問にいくらか関連しています。生のHibernate注釈付きPOJOをデータアクセス層から返す必要がありますか、それともインターフェイスから返す必要がありますか?、私はうまく分離されたレイヤーの作成の経験がありますが、HibernateまたはJ2EE/JPAを使用していません。私はドキュメントとチュートリアルを見てきましたが、EntityMangerをエレガントな方法で使用する方法に戸惑っています。これは、トランザクション(サービス層で実行したい)と永続化メソッド(必要な)の両方を担当しているように見えるためです。データアクセス層に保持するため)。サービス層で作成してデータアクセス層に注入する必要がありますか、それともより良い方法がありますか?以下の疑似Javaは、私が考えていることを大まかに示しています。

編集:以下の私の擬似コードは、基本的に休止状態のJPAチュートリアルから取得され、レイヤー分離用に変更されており、製品がEJBコンテナー(Glassfish)で実行するように開発されていることを反映していません。回答では、Glassfishまたは同等のコードで実行されるコードのベストプラクティスとコード例を示してください。

MyService
{

  setup()
  {
       EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory( "Something" ); //is the String you pass in important?
       entityManager = entityManagerFactory.createEntityManager();
  }

  myServiceMethod()
   {
   entityManager.getTransaction().begin();
   MyDao.setEntityManager(entityManagerFactory); 
   MyDao.doSomething();
   MyDao.doSomethingElse();
   entityManager.getTransaction().commit();
   entityManager.close();
   }
 }

MyDao
{
   doSomething()
    {
     entityManager.persist(...); //etc 
    }

}
4

3 に答える 3

13

まず、DAOレイヤーを使用する必要があるかどうかは、多くの人がDAO自体と見なしているJPAとEntityManagerの登場以来の議論です。これに対する答えは、開発しているアプリケーションのタイプによって異なりますが、ほとんどの場合、次のことを行う必要があります。

  • JPA基準またはカスタムクエリを使用します。この場合、ビジネスロジックとクエリの作成を混在させたくないでしょう。これは大きな方法につながり、単一責任の原則に違反します。
  • JPAコードを可能な限り再利用します。40〜65歳で、会社で10年以上働いている従業員のリストを取得する基準クエリを作成するとします。このタイプのクエリをサービスレイヤーの別の場所で再利用したい場合があります。その場合、サービスにこのタイプのクエリを含めると、このタスクが困難になります。

そうは言っても、アプリケーションにCRUD操作だけがあり、JPAコードを再利用する必要がないと思われる場合、DAOレイヤーは、EntityManagerの単なるラッパーとして機能するため、おそらくやり過ぎです。正しく聞こえません。

次に、可能な限りコンテナ管理のトランザクションを使用することをお勧めします。TomEEやJBossなどのEJBコンテナを使用している場合、これにより、プログラムでトランザクションを作成および管理するための大量のコードを回避できます。

en EJBコンテナを使用している場合は、宣言型トランザクション管理を利用できます。DAOを使用するこの例は、サービス層コンポーネントをEJBおよびDAOとして作成することです。

@Stateless
public class CustomerService {

    @EJB
    CustomerDao customerDao;

    public Long save(Customer customer) {

        // Business logic here
        return customerDao.save(customer);
    }
}

@Stateless
public class CustomerDao {

    @PersistenceContext(unitName = "unit")
    EntityManager em;

    public Long save(Customer customer) {
        em.persist(customer);
        return customer.getId();
    }

    public Customer readCustomer(Long id) {
            // Criteria query built here
    }

}

上記の例では、デフォルトのトランザクション構成はREQUIREDです。これは、呼び出し元コンポーネントにトランザクションがない場合、EJBが新しいトランザクションを作成することを意味します。呼び出し元がすでにトランザクション(CustomerService)を作成している場合、呼び出されているコンポーネント(CustomerDao)はトランザクションを継承します。これは、 @TransactionAttributeアノテーションを使用してカスタマイズできます。

EJBコンテナを使用していない場合は、上記の例はおそらく同等だと思います。

編集済み:簡単にするために、上記ではインターフェイスなしのEJBを使用しましたが、テストしやすくするために、インターフェイスを使用することをお勧めします。

于 2011-10-22T15:00:32.810 に答える
2

通常、永続化コードをDAOレイヤーに分離する必要があります。したがって、サービス層はについてさえ知らないはずEntityManagerです。DAOレイヤーが注釈付きのpojoを返す場合、それらはまだpojoのままなので、問題ないと思います。

トランザクション管理については、SpringORMを参照することをお勧めします。ただし、Springまたはその他のAOPソリューションを使用しないことを選択した場合は、DAOを介してトランザクション関連のメソッドをいつでも公開できるため、サービスレイヤーからメソッドを呼び出すことができます。そうすることはあなたの人生をはるかに難しくしますが、選択はあなた次第です...

于 2011-10-22T08:17:54.343 に答える
0

getItem()、getEmployee()などの単純なケースでは、ServiceメソッドがDao(エンティティマネージャーが挿入されている)メソッドを呼び出し、ユーザーentitymanagerがオブジェクトを返すのではなく、メソッドで使用するServiceレイヤーに直接entitymanagerを挿入する方が適切です。 。これはやり過ぎであり、DAOは単にラッパーとして機能します。クエリと基準を含む複雑なビジネスロジックの場合、サービスメソッドがDBと通信するDaoを呼び出すようにします。

于 2016-02-03T18:10:31.983 に答える