4

Hibernate とのやり取りについていくつか質問があります。

  1. openSession または getCurrentSession (jta を使用せず、代わりにスレッド) を使用する必要がありますか?
  2. セッション操作と Swing GUI を混在させるにはどうすればよいですか? JavaBean クラスに次のようなコードがあってもよいでしょうか。

    public void actionPerformed(ActionEvent event) {
        // session code
    }
    
  3. HQL クエリを含むエンティティにメソッドを追加できますか?それとも悪い習慣ですか? 例えば:

     // This method is in an entity MyOtherEntity.java class
     public int getDuration(){
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        int sum = (Integer) session.createQuery("select sum(e.duration) as duration from MyEntity as e where e.myOtherEntity.id=:id group by e.name").
            .setLong("id", getId());
            .uniqueResult();
        return sum;
     }
    

どうすればこれをより適切でエレガントな方法で行うことができますか?

更新 広く使用されている方法は、サービス/dao クラスを作成して、エンティティ クラスの CRUD 操作を実現することです。しかし、なぜこれが良いのですか?エンティティを管理するために、エンティティごとにクラスを作成する必要があるのはなぜですか? 本当のメリットはどこにある?

UPDATE 2 サービス クラスは DAO パターンですか? これは何を意味するのでしょうか? Arthur Ronald FD Garcia のリポジトリの例は DAO パターンですが、これは「サービス層」と呼ばれるものですか?

4

1 に答える 1

1

プレーンな Hibernate API に依存したい場合は、サービス層を使用できます。

  • ユースケース主導です
  • トランザクション境界を区切る

たとえば、次のように AccountService を作成できます。

public static path.to.HibernateUtil.getSessionFactory;

public class AccountService {

    public void withdraw(Integer accountNumber, BigDecimal amount) throws Exception {
        /**
          * Here you set up Transaction boundaries
          */
        getSessionFactory().getCurrentSession().beginTransaction();

        // Some actions goes here

        getSessionFactory().getCurrentSession().getTransaction().commit();
    }

}

サービスレイヤー内で何らかのアクションを実行する場合、通常はリポジトリが必要です。リポジトリは、データ プロバイダーおよびストレージと考えることができます。ここで、リポジトリを実装する方法を確認できます。

保守可能で読みやすい HQL クエリが必要な場合は、複数行の外部化された xml ファイルで HQL クエリを外部化することをお勧めします。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <query name="GIFT_CARDS_WITH_BUYER">
        <![CDATA[
            from 
                GiftCard c
            left join fetch 
                c.buyer
            where
                c.recipientNotificationRequested = 1
       ]]>
    </query>
    <query name="GIFT_CARDS_WITHOUT_NO_RELATIONSHIP">
        <![CDATA[
            from 
                GiftCard
        ]]>
    </query>
</hibernate-mapping>

したがって、Swing GUI イベント内で、次のようにサービス層を呼び出すことができます

public void actionPerformed(ActionEvent event) {
    // Some related Swing GUI actions goes here (retrieve User input, validate data and so on...)

    accountService.withdraw(accountNumber, new BigDecimal(amount));
}

また、エンティティ内で永続化アクションを使用することはお勧めできません。エンティティ内で永続性関連の問題を実行する必要がある場合は、リポジトリをパラメーターとしてエンティティに渡す方がよいと思います

public class Account {

   public void doSomething(AccountRepository repository) {
       // code goes here
   }

}

多分あなたはこのスレッドを見たいと思うでしょう

Java Persistence with Hibernate book の第 9 章 (オブジェクトの操作) をご覧になることをお勧めします。ATT : よくお読みください

アップデート

なぜサービス層があるのが良いのですか?

初めに

  • ユースケース駆動型です(アプリが何をすべきかを描きます)

第二に

  • トランザクション境界を区切る

ここにサービス層があるとします

public class MyService {

    public void doSomething() {
        getSessionFactory().beginTransaction();

        // A POJO doing some operation

        // Other POJO doing other operation

        // Another POJO doing another operation

        getSessionFactory().getTransaction().commit();
    }

}

各 POJO 内でそれぞれを定義するのではなく、1 つのトランザクション境界を定義するだけであることに注意してください。さらに、Swing GUI 内のビジネス ルールを他のコンポーネント内で使用する必要がある場合はどうなりますか。Ctrl-c + Ctrl-v を使用しますか???

于 2010-06-17T23:11:33.270 に答える