legacy-knowledge-base
公開されました Sep. 10, 2025

HibernateでJNDIリソースを使う

written-by

Liferay Support

How To articles are not official guidelines or officially supported documentation. They are community-contributed content and may not always reflect the latest updates to Liferay DXP. We welcome your feedback to improve How To articles!

While we make every effort to ensure this Knowledge Base is accurate, it may not always reflect the most recent updates or official guidelines.We appreciate your understanding and encourage you to reach out with any feedback or concerns.

legacy-article

learn-legacy-article-disclaimer-text

Tomcat(またはJNDIリソースを同じように管理するアプリケーションサーバー)でJNDIリソースに接続するためにHibernateを使用している場合、このチュートリアルはあなたのためにあります!

背景として、TomcatがアプリケーションがJNDIリソースにアクセスできるかどうかを判断する方法の1つは、コンテキストクラスローダをチェックすることです。 コンテキストクラスローダがWebアプリケーションクラスローダまたはWebアプリケーションクラスローダの子である場合、TomcatはそのクラスローダにJNDIリソースをアクセスさせることができます。

Liferay Digital Experience Platform(DXP)アプリケーションはTomcat上で展開し、DXPのクラスローダーはWebアプリケーションクラスローダーですが、DXPポートレットクラスローダーはそうではなく、ポートレットはOSGiクラスローダーを使用してLiferayのOSGiコンテナにインストールされたOSGiバンドルです。 ポートレットがTomcat上でアプリケーションに提供されるJNDIリソースにアクセスするためには、ポートレットがDXPのクラスローダの子であるクラスローダに切り替える必要があります。

このチュートリアルでは、Hibernateの構成がJNDIデータソースを活用できるように、コンテキスト・クラスローダーの切り替えを行う方法を説明します。

注: ここで示したコードは、Tomcatで動作しますが、他のアプリケーションサーバーでの動作を保証するものではありません。 JNDIリソースへのアクセスを管理する方法については、アプリケーションサーバーのドキュメントを参照してください。

環境

このコードは、Liferay DXP SP3から利用できる改良を活用しています。

解像度

まずHibernateの構成記述子で、JNDIデータソースを使用するセッションファクトリを指定します。 以下は省略した説明文です:

<?xml version="1.0"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>

        <property name="connection.datasource">java:comp/env/jdbc/mydb</property>

        <property name="current_session_context_class">thread</property>

        // Specify resources here ...
    </session-factory>
</hibernate-configuration>

上記の記述子をベースにする場合、 connection.datasource プロパティ値をJNDIデータソース名に置き換え、セッションで使用するリソースを指定することを確認してください。

次に、 HibernateUtil クラスは、DXPのクラスローダーを使用するHibernateセッションを作成および管理するためのメソッドを提供します。 注、 // カスタマイズ START/END コメントは、Hibernateの設定を処理する際に、呼び出し側がJNDIデータソースにアクセスできるようにするコードをマークします。

import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

// Customization START
import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
import com.liferay.portal.kernel.util.AggregateClassLoader;
// Customization END

public class HibernateUtil {

    public static final String COUNT_COLUMN_NAME = "COUNT_VALUE";

    public static void closeSession(Session session) {
        try {
            if ((session != null) && session.isOpen()) {
                session.close();
            }
        }
        catch (HibernateException he) {
            _log.error(he.getMessage());
        }
    }

    public static String getCountColumnName() {
        return COUNT_COLUMN_NAME;
    }

    public static SessionFactory getSessionFactory() {
        return _instance._sessionFactory;
    }

    public static Session openSession() throws HibernateException {
        return openSession(getSessionFactory());
    }

    public static Session openSession(SessionFactory sessionFactory)
        throws HibernateException {

        return sessionFactory.getCurrentSession();
    }

    private HibernateUtil() {
        // CUSTOMIZATION START

        Thread thread = Thread.currentThread();
        ClassLoader threadClassLoader = thread.getContextClassLoader();
        ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();

        ClassLoader hibernateClassLoader =
            AggregateClassLoader.getAggregateClassLoader(
                portalClassLoader, threadClassLoader);

        thread.setContextClassLoader(hibernateClassLoader);

        // CUSTOMIZATION END

        try {
            Configuration configuration = new Configuration();

            configuration = configuration.configure();

            _sessionFactory = configuration.buildSessionFactory();
        }
        catch (Exception e) {
            _log.error(e, e);
        }

        // CUSTOMIZATION START

        finally {
            thread.setContextClassLoader(threadClassLoader);
        }

        // CUSTOMIZATION END
    }

    private static Log _log = LogFactoryUtil.getLog(HibernateUtil.class);

    private static HibernateUtil _instance = new HibernateUtil();

    private SessionFactory _sessionFactory;

}

このクラスのロジックを分解してみましょう。 まず、その静的メンバが一番下で宣言されています。

private static Log _log = LogFactoryUtil.getLog(HibernateUtil.class);

private static HibernateUtil _instance = new HibernateUtil();

private SessionFactory _sessionFactory;

ここでは、各メンバーについて説明します:

  • _log: このクラスのメッセージをログに記録します。
  • _instance: HibernateUtil のインスタンスです。
  • _sessionFactory: 設定されると、JNDIリソース(例えば、JNDIデータソース)にアクセスすることを望むHibernateセッションを管理するものです。

コンストラクタ HibernateUtil() が "魔法 "をかけてくれる:

  1. 現在のスレッド、そのコンテキストのクラスローダー(OSGiのクラスローダーである)、DXPのクラスローダーを取得します。

    Thread thread = Thread.currentThread();
    ClassLoader threadClassLoader = thread.getContextClassLoader();
    ClassLoader portalClassLoader = PortalClassLoaderUtil.getClassLoader();
    
  2. DXPのクラスローダー(Portalクラスローダー)の子で、OSGiバンドル用に作成したOSGiクラスローダーからクラスと設定にアクセスできる新しいクラスローダーを作成する。 AggregateClassLoader を使えば、多くのボイラープレート・コードなしにこれを行うことができる。

    ClassLoader hibernateClassLoader =
        AggregateClassLoader.getAggregateClassLoader(
            portalClassLoader, threadClassLoader);
    
  3. 新しいクラスローダーを現在のスレッドのコンテキスト・クラスローダーとして設定します。

    thread.setContextClassLoader(hibernateClassLoader);
    
  4. セッションファクトリを作成し、Hibernateの構成(JNDIデータソースを使用する先に構成されたもの)をロードします。

    try {
       Configuration configuration = new Configuration();
    
       configuration = configuration.configure();
    
       _sessionFactory = configuration.buildSessionFactory();
    }
    catch (Exception e) {
       _log.error(e, e);
    }
    

    セッションファクトリーサービスは、新しく作成されたクラスローダーを使用して、JNDIデータソースを要求します。

  5. スレッドのコンテキストクラスローダとして、元のOSGiクラスローダを復元する。

    finally {
        thread.setContextClassLoader(threadClassLoader);
    }
    

HibernateUtil'の他のメソッドは、Hibernate セッションファクトリとそのセッションにアクセスし、動作します。

  • getSessionFactory()
  • closeSession(Session)
  • openSession()
  • openSession(SessionFactory)

HibernateUtil のようなクラスは、JNDIデータソースなどのJNDIリソースを使用するHibernateセッションの取得を容易にします。 Hibernateを使用するプロジェクトでは、そのバージョンを使用することができます。

追加情報

did-this-article-resolve-your-issue

legacy-knowledge-base