2

私たちの Web アプリケーションには、HibernateSessionFactory接続を開いたり閉じたりするクラスがあります。すべて問題ありませんが、データベースのデータを更新しても、アプリケーションでは変更されません。残念ながら、データベースからの古いデータが表示されます。どうすれば修正できますか?

public class HibernateSessionFactory {

    private static final ThreadLocal threadLocal = new ThreadLocal();
    private static org.hibernate.SessionFactory sessionFactory;

    private static Configuration configuration = new Configuration();
    private static ServiceRegistry serviceRegistry; 

    private static final Logger log = Logger.getLogger(HibernateSessionFactory.class);

    static {
        try {
            configuration.configure();
            serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
            . buildServiceRegistry();
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        } catch (Exception e) {
            log.error("Error Creating SessionFactory",e);

        }
    }

    private HibernateSessionFactory() {
    }

    public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get(); 
        if (session == null || !session.isOpen()) {
            if (sessionFactory == null) {
                rebuildSessionFactory();
            }
            session = (sessionFactory != null) ? sessionFactory.openSession()
            : null;

            threadLocal.set(session);
        }
        return session;
    }

    public static void rebuildSessionFactory() {

        try {
            configuration.configure();
            serviceRegistry = new ServiceRegistryBuilder(). applySettings(configuration.getProperties()) 
            .buildServiceRegistry();
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        } catch (Exception e) {
            log.error("Error Creating SessionFactory",e);
        }
    }

    public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);
        if (session != null) {
            session.flush();
            session.close();

        }
    }

    public static org.hibernate.SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static Configuration getConfiguration() {
        return configuration;
    }

}
4

1 に答える 1

8

Hibernate は、プログラムとデータベースの間にレイヤーを構築するための洗練された複雑なフレームワークであり、オブジェクト指向プログラムの仕事を支援するオブジェクト指向モデルを提供します。

これを行うために、そしてもちろんパフォーマンスを向上させるために、データベースからのデータ、またはデータベースに送信されるデータの一部を保存するキャッシュを作成します。

この問題はデータベースへの接続に関するものではなく、データの保存と取得の方法に関係していると思います。私は自分自身をよりよく説明しようとします: データベースにクエリを実行してデータを保存するときは、次の手順を実行します。

  1. セッションを開く
  2. 取引を開く
  3. ビルドオブジェクト
  4. セッション内のオブジェクトをフラッシュして保存する
  5. トランザクションをコミットする
  6. 取引を閉じる
  7. セッションを閉じる

例えば

public Boolean saveNewCliente(Cliente c) {
    Session s = getSession();
    Transaction t = null;
    try {
        t = s.beginTransaction();
        s.save(c);
        s.flush();
        t.commit();
        s.close();
        return true;
    } catch (Exception e) {
         if (t!=null) t.rollback();
        System.out.println(e.getMessage());
        return false;
    }
    finally{
        s.close();
    }

}

データベースにクエリを実行してデータをフェッチするときによくある落とし穴は、トランザクションに関連する部分を「クエリ」ステップから除外することです。同様に、データを保存するために必要です

  1. セッションを開く
  2. 取引を開く
  3. クエリ/条件を作成する
  4. セッションでクエリを実行する
  5. 取引を閉じる
  6. セッションを閉じる

この手順に従わない場合、アプリケーションには古いデータが含まれている可能性がありますが、データベースには含まれていません。チェックは、更新/保存クエリを実行し、データが変更/作成されたかどうかをデータベースで手動でチェックすることです。その後、アプリケーションが古いデータをロードする場合、(トランザクションを使用せずに) フェッチクエリを間違った方法で実行していることがわかります。これは例の抜粋です

    public Cliente get(Integer id) {
    Session s = getSession();
    Transaction tx = s.beginTransaction();
    try {
        System.out.println("get cliente by id");
        Cliente res = new Cliente();
        res = (Cliente) s.get(Cliente.class, id);
        tx.commit();
        return res;
    } catch (Exception e) {
        tx.rollback();
        System.out.println(e.getMessage());
        return null;
    }finally{
        s.close();
    }
}

さらに調査したい場合は、休止状態でキャッシュの使用を一時停止できます。次の方法で実行できますが、データがキャッシュされている場合は理由があることに注意してください ;) これは、続行するための簡単なテストとして役立ちます。エラーが間違ったクエリの使用によるものかどうかを発見する際に。

これを hibernate config xml に追加する必要があります

<!-- to disable cache -->
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.cache.use_query_cache">false</property>
于 2013-10-13T15:26:27.863 に答える