ヘッダーをスキップ
Oracle® Coherenceチュートリアル
リリース3.6
B61373-01
  ドキュメント・ライブラリへ
ライブラリ
製品リストへ
製品
目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

9 キャッシュとデータベースの相互作用

この章では、このチュートリアルで提示したすべての概念を使用して、Oracle JDeveloperでOracle Coherenceキャッシュを作成および構成します。この演習では、次の作業を行います。

この章の内容は次のとおりです。

9.1 概要

Coherenceキャッシュは、データベースとクライアント・アプリケーションの仲介者の役割を果たすデータ・オブジェクトのコレクションです。データベースのデータをキャッシュにロードして、別のアプリケーションで使用可能にすることができます。したがって、Coherenceキャッシュを使用すると、データベースの負荷が軽減し、データベースのデータに、より迅速にアクセスできるようになります。

Coherenceキャッシュは、データベースの分離やデータのレプリケーションによって可用性がさらに向上します。キャッシュに対する変更は、データベースが使用可能であれば常にデータベースと同期できます。データベースまたはアプリケーション・サーバー・ノードが使用できない場合でも、Coherenceキャッシュで使用されている遅延ロードおよび遅延書込みのメカニズムによって、またOracle Coherenceのフェイルオーバーおよびフェイルバックによって、データベース更新の信頼性は保たれます。

Coherenceキャッシュでは、データ変更操作をデータ・オブジェクトに対して実行できるため、アプリケーション・サーバー・ノードのクラスタ全体だけでなく、キャッシュ内のデータ・オブジェクト間で処理が分散されます。

Oracle Coherenceでは、イベントベースの処理も可能です。キャッシュ内のデータ・オブジェクトの状態を監視し、ビジネス・プロセス実行言語(BPEL)プロセスの開始など、他のプロセスでアクションを起動できます。

Oracle Coherenceでは、様々なタイプのキャッシュがサポートされています。

Oracle Coherenceは、クラスタ・サービス、分散キャッシュ・サービス、レプリケーション・キャッシュ・サービスなどのサービスを使用して実装されます。どのタイプのキャッシュを使用しても、アプリケーションでは、同じAPIを使用してデータへのアクセスおよびデータの格納を行います。

キャッシュの構成には、キャッシュ構成デプロイメント・ディスクリプタを使用します。キャッシュ構成ファイルのルート要素はcache-configです。キャッシュ名および名前のパターンは、サブ要素cache-mappingを使用して、caching-scheme-mapping要素のキャッシュ・タイプにマップされます。キャッシュ・タイプはcaching-schemes要素で定義します。よく使用されるキャッシュ・タイプの一部を表9-1で説明します。

表9-1 キャッシュ・タイプの説明

キャッシュ・タイプ 説明

分散スキーム

複数ノードのクラスタ全体にデータが格納される分散キャッシュを定義します。

レプリケーション・スキーム

すべてのクラスタ・ノードにキャッシュ・エントリがレプリケートされるキャッシュを定義します。

read-write-backing-mapスキーム

リレーショナル・データベースなどの永続ストアのキャッシュを提供するマップを定義します。

外部スキーム

ディスクなどの外部キャッシュを定義します。

クラス・スキーム

java.util.Mapインタフェースの実装に必要なカスタム・キャッシュ実装を定義します。


9.2 キャッシュ・アプリケーションの作成

この項では、キャッシュ・データの挿入と取得を行うアプリケーションを作成および実行する方法について説明します。

  1. キャッシュを作成するアプリケーションの作成

  2. キャッシュ構成ファイルの作成

  3. プロジェクト・プロパティの構成

  4. キャッシュ・サーバー起動ファイルの編集

  5. キャッシュ作成アプリケーションの実行

9.2.1 キャッシュを作成するアプリケーションの作成

次の手順に従い、Coherenceキャッシュを作成するJavaクラスを作成します。

  1. Oracle JDeveloperでプロジェクトを作成します。

    1. Oracle JDeveloperでInteractというプロジェクトを作成します。詳細は、「既存アプリケーションでの新規プロジェクトの作成」を参照してください。

    2. CoherenceのJARファイルcoherence.jarおよびC:\home\oracle\labsを、プロジェクト・クラスパスに追加します。また、Oracle JDBCライブラリも追加します。これは、データベースからプロジェクト・ライブラリへのアクセスに必要です。

      図9-1 クラスパスへのCoherence Jar、LabsディレクトリおよびJDBCライブラリの追加

      クラスパスへのOracle JDBCライブラリの追加
  2. JavaクラスCoherenceCacheを作成します。これは、Coherenceキャッシュの作成に使用します。クラスの作成の詳細は、「Javaクラスの作成」を参照してください。

    1. CoherenceCache Javaクラス内にキャッシュを作成します。CacheFactoryクラスおよびNamedCacheインタフェースをインポートします。

      import com.tangosol.net.CacheFactory; 
      import com.tangosol.net.NamedCache;
      
    2. キャッシュのインスタンスがCacheFactoryクラスから作成されます。CacheFactoryクラスのgetCache()メソッドを使用してNamedCacheを作成します。キャッシュ名VirtualCacheを使用します。これは分散キャッシング・スキームにマップされます。

      NamedCache cache = CacheFactory.getCache ( "VirtualCache");
      
    3. NamedCacheは、クラスタ内のノードで共有されるリソースを保持するjava.util.Mapです。put()メソッドを使用してキャッシュ・エントリを追加します。

      cache.put (key, "Hello Cache");
      
    4. キャッシュ・エントリは、get()メソッドを使用して取得できます。

      System.out.println((String)cache.get("hello"));
      

      例9-1に、可能な解決策を示します。Oracle JDeveloperで、このコードをCoherenceCacheアプリケーションにコピーできます。

      例9-1 Coherenceキャッシュの実装

      package com.oracle.handson;
      
      import com.tangosol.net.CacheFactory; 
      import com.tangosol.net.NamedCache;
      
      public class CoherenceCache {
          NamedCache cache;
          public CoherenceCache() {
          }
          public void putCache(){
                  cache = CacheFactory.getCache ( "VirtualCache"); 
                 String key = "hello"; 
                 cache.put (key, "Hello Cache"); 
             
             }
             
             public void retrieveCache(){
             
                 System.out.println((String)cache.get("hello"));
      
             }
             
              public static void main (String [] args) {
              CoherenceCache cache = new CoherenceCache(); 
              cache.putCache();
              cache.retrieveCache();
              }
      }
      

9.2.2 キャッシュ構成ファイルの作成

キャッシュ構成デプロイメント・ディスクリプタとして、cache-config.xmlというXMLドキュメントを作成します。

XMLドキュメントを追加するには、プロジェクトを右クリックして「新規」を選択します。「新規ギャラリ」ウィンドウで、「一般」カテゴリの下の「XML」を選択します。「XMLドキュメント」を選択して「OK」をクリックします。「ファイル名」をcache-config.xmlに変更します。ディレクトリをC:\home\oracle\labs\に変更します。

キャッシュ構成ファイルで次の作業を行います。

  • caching-scheme-mapping要素内のcache-mapping要素を使用して、キャッシュ名およびネーミング・パターンのマッピングを定義します。

  • キャッシュ名VirtualCacheをキャッシュ・タイプdefault-distributedにマップします。

  • distributed-scheme要素でDistributedCacheサービスを使用して分散キャッシング・スキームを定義します。

キャッシュ構成ファイルを例9-2に示します。Oracle JDeveloperで、この例の内容をcache-config.xmlファイルにコピーします。

例9-2 キャッシュ構成ファイル

<?xml version="1.0"?>
<!DOCTYPE cache-config SYSTEM "cache-config.dtd">
<cache-config>
    <caching-scheme-mapping>
        
        <cache-mapping>
            <cache-name>VirtualCache</cache-name>
            <scheme-name>default-distributed</scheme-name>
        </cache-mapping>
    </caching-scheme-mapping>
    <caching-schemes>
        <!--
        Default Distributed caching scheme.
        -->
        <distributed-scheme>
            <scheme-name>default-distributed</scheme-name>
            <service-name>DistributedCache</service-name>
            <backing-map-scheme>
                <class-scheme>
                    <scheme-ref>default-backing-map</scheme-ref>
                </class-scheme>
            </backing-map-scheme>
        </distributed-scheme>
         <class-scheme>
            <scheme-name>default-backing-map</scheme-name>
            <class-name>com.tangosol.util.SafeHashMap</class-name>
         </class-scheme>
  <autostart>true</autostart>
 </caching-schemes>
</cache-config>

9.2.3 プロジェクト・プロパティの構成

アプリケーションの実行構成を変更し、ランタイムJavaオプションとしてキャッシュ構成ファイルを追加します。

  1. プロジェクト・ノードを選択し、「ツール」→「プロジェクト・プロパティ」を選択します。「プロジェクト・プロパティ」ウィンドウで、「実行/デバッグ/プロファイル」を選択します。「デフォルト」構成がデフォルトで選択されています。「デフォルト」構成の「編集」をクリックします。

  2. 実行構成の編集」ウィンドウで、「起動設定」を選択します。「Javaオプション」フィールドで、-Dtangosol.coherence.cacheconfigによりキャッシュ構成ファイル(cache-config.xml)を指定します。

    たとえば、自分で作成したOracle Coherenceアプリケーションの場合は、「Javaオプション」フィールドで次のように指定して(cache-config.xmlの実際のパスは異なる場合があります)、「OK」をクリックします。

    -Dtangosol.coherence.cacheconfig=/home/oracle/labs/cache-config.xml
    

    図9-2 ランタイム・オプションの設定

    ランタイム・オプション用のキャッシュ構成ファイルの設定

    実行/デバッグ/プロファイル」ウィンドウで「OK」をクリックします。このキャッシュ構成ファイルは、ランタイムJavaオプションとしてCoherence Javaアプリケーションに追加されます。

9.2.4 キャッシュ・サーバー起動ファイルの編集

第8章「JPAとCoherenceの併用」で作成したJPAキャッシュ・サーバー(jpa-cache-server.cmd)起動ファイルを編集します。

キャッシュ構成ファイルjpa-cache-config.xmlの名前をcache-config.xmlに置き換えます。

-Dtangosol.coherence.cacheconfig=\home\oracle\labs\cache-config.xml

クラスパスのJPA\classesディレクトリのパスを、Interact\classesディレクトリのパスに置き換えます。

C:\home\oracle\labs\Interact\classes; 

9.2.5 キャッシュ作成アプリケーションの実行

次の手順に従い、キャッシュ作成アプリケーションCoherenceCache.javaを実行します。

  1. 稼働しているキャッシュ・サーバーがあれば停止します。jpa-cache-server.cmdを実行してキャッシュ・サーバーを起動します。

  2. Oracle CoherenceアプリケーションCoherenceCache.javaを右クリックして「実行」をクリックします。JDeveloperログ・ウィンドウに、次のように出力が表示されます。

    • tangosol-coherence.xmlからオペレーション構成がロードされます。このファイルは、Coherenceでクラスタ化、通信、データ管理の各サービスに使用するオペレーション設定およびランタイム設定を指定します。

    • cache-config.xmlからキャッシュ構成がロードされます。

    • 新しいクラスタが作成され、DistributedCacheサービスがこのクラスタに参加します。

    • CoherenceCache.javaプログラムの出力、Hello Cacheが表示されます。

    例9-3 Coherenceキャッシュ・アプリケーションの出力

    2010-06-02 17:11:36.197/0.313 Oracle Coherence 3.6.0.0 DPR3 <Info> (thread=main, member=n/a): Loaded operational configuration from "jar:file:/C:/oracle/product/coherence/lib/coherence.jar!/tangosol-coherence.xml"
    2010-06-02 17:11:36.213/0.329 Oracle Coherence 3.6.0.0 DPR3 <Info> (thread=main, member=n/a): Loaded operational overrides from "jar:file:/C:/oracle/product/coherence/lib/coherence.jar!/tangosol-coherence-override-dev.xml"
    2010-06-02 17:11:36.213/0.329 Oracle Coherence 3.6.0.0 DPR3 <D5> (thread=main, member=n/a): Optional configuration override "/tangosol-coherence-override.xml" is not specified
    2010-06-02 17:11:36.213/0.329 Oracle Coherence 3.6.0.0 DPR3 <D5> (thread=main, member=n/a): Optional configuration override "/custom-mbeans.xml" is not specified
    
    Oracle Coherence Version 3.6.0.0 DPR3 Build 16141
     Grid Edition: Development mode
    Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
    
    2010-06-02 17:11:36.431/0.547 Oracle Coherence GE 3.6.0.0 DPR3 <Info> (thread=main, member=n/a): Loaded cache configuration from "file:/C:/home/oracle/labs/cache-config.xml"
    2010-06-02 17:11:36.853/0.969 Oracle Coherence GE 3.6.0.0 DPR3 <D4> (thread=main, member=n/a): SystemSocketProvider bound to port 8088
    2010-06-02 17:11:40.353/4.469 Oracle Coherence GE 3.6.0.0 DPR3 <Info> (thread=Cluster, member=n/a): Created a new cluster "cluster:0xC4DB" with Member(Id=1, Timestamp=2010-06-02 17:11:36.869, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:4884, Role=OracleHandsonCoherenceCache, Edition=Grid Edition, Mode=Development, CpuCount=2, SocketCount=1) UID=0x822363D500000128FB261625C2D51F98
    2010-06-02 17:11:40.353/4.469 Oracle Coherence GE 3.6.0.0 DPR3 <Info> (thread=main, member=n/a): Started cluster Name=cluster:0xC4DB
    
    Group{Address=224.3.6.0, Port=36000, TTL=4}
    
    MasterMemberSet
      (
      ThisMember=Member(Id=1, Timestamp=2010-06-02 17:11:36.869, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:4884, Role=OracleHandsonCoherenceCache)
      OldestMember=Member(Id=1, Timestamp=2010-06-02 17:11:36.869, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:4884, Role=OracleHandsonCoherenceCache)
      ActualMemberSet=MemberSet(Size=1, BitSetCount=2
        Member(Id=1, Timestamp=2010-06-02 17:11:36.869, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:4884, Role=OracleHandsonCoherenceCache)
        )
      RecycleMillis=1200000
      RecycleSet=MemberSet(Size=0, BitSetCount=0
        )
      )
    
    TcpRing{Connections=[]}
    IpMonitor{AddressListSize=0}
    
    2010-06-02 17:11:40.431/4.547 Oracle Coherence GE 3.6.0.0 DPR3 <D5> (thread=Invocation:Management, member=1): Service Management joined the cluster with senior service member 1
    2010-06-02 17:11:40.697/4.813 Oracle Coherence GE 3.6.0.0 DPR3 <D5> (thread=DistributedCache, member=1): Service DistributedCache joined the cluster with senior service member 1
    Hello Cache
    2010-06-02 17:11:40.775/4.891 Oracle Coherence GE 3.6.0.0 DPR3 <D4> (thread=ShutdownHook, member=1): ShutdownHook: stopping cluster node
    2010-06-02 17:11:40.775/4.891 Oracle Coherence GE 3.6.0.0 DPR3 <D5> (thread=Cluster, member=1): Service Cluster left the cluster
    Process exited with exit code 0.
    

9.3 データベース・キャッシュの作成

この項では、Oracleデータベースでバックアップされるキャッシュを作成します。これは、Oracleデータベース・キャッシュとも呼ばれます。

  1. Oracleデータベース・キャッシュの作成

  2. カスタムCacheStoreを定義するクラスの作成

  3. キャッシュ構成ファイルの変更

  4. データベース・キャッシュを作成するクラスの作成

  5. データベース・キャッシュ・アプリケーションの実行

9.3.1 Oracleデータベース・キャッシュの作成

次の手順に従い、SQL*PlusおよびOracle Database 10g Express Edition(XE)を使用してOracleデータベース・キャッシュを作成します。この項では、データベースが各自のシステムにインストールされていることを前提としています。

  1. SQL*Plusを起動します。

    スタート」→「すべてのプログラム」→「Oracle Database 10g Express Edition」→「SQLコマンドラインの実行」に移動します。

  2. ユーザー名をhr、パスワードをhrとして接続します。

    connect hr/hr;
     
    
  3. Oracle Databaseの表を作成します。

    テキスト・エディタを開いて、次のSQLコードをコピーします。このファイルをdbscript.sqlという名前で/home/oracle/labs/フォルダに保存します。

    例9-4 データベース表を作成するSQLスクリプト

    CREATE TABLE HR.CATALOG(id VARCHAR(25) PRIMARY KEY, value VARCHAR(96)); 
    INSERT INTO HR.CATALOG VALUES('catalog1', 'Tuning Undo Tablespace');
    INSERT INTO HR.CATALOG VALUES('catalog2', 'Tuning Your View Objects');
    
  4. SQLスクリプトを実行します。

    例9-5にスクリプトの出力を示します。

    例9-5 データベース表を作成するSQLスクリプトの実行

    SQL*Plus: Release 10.2.0.1.0 - Production on Wed Jun 2 16:30:15 2010
    Copyright (c) 1982, 2005, Oracle.  All rights reserved.
    SQL> connect hr/hr;
    Connected.
    SQL> @/home/oracle/labs/dbscript.sql
    
    Table created
    
    1 row created
    
    1 row created
    

9.3.2 カスタムCacheStoreを定義するクラスの作成

次の手順に従い、データベースに接続して表データを取得するJavaクラスを作成します。

  1. Oracle JDeveloperでJavaクラスDBCacheStoreを作成します。詳細は、「Javaクラスの作成」を参照してください。

  2. データベースに接続して表データを取得するコードを作成します。

    例9-6に、可能な解決策を示します。Oracle JDeveloperで、このコードをDBCacheStoreアプリケーションにコピーします。DBCacheStoreアプリケーションは、Java Database Connectivity(JDBC)を使用してOracle Databaseにアクセスしますが、かわりにHibernateやJava Data Objects(JDO)などの別のメカニズムも使用できます。

    例9-6 Database CacheStore実装

    package com.oracle.handson;
    
    import com.tangosol.net.cache.CacheStore;import com.tangosol.util.Base;
    
    import java.sql.DriverManager;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.Collection;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    
    public class DBCacheStore
    
            extends Base
            implements CacheStore {
        
            protected Connection m_con;
            protected String m_sTableName;
            private static final String DB_DRIVER   = "oracle.jdbc.OracleDriver";
    
                
                private static final String DB_URL      = "jdbc:oracle:thin:@localhost:1521:XE";
                private static final String DB_USERNAME = "hr";
                private static final String DB_PASSWORD = "hr";
        
        public DBCacheStore(String sTableName)
            {
            m_sTableName = sTableName;
    
            configureConnection();        }
        protected void configureConnection()
            {
            try
                {
                Class.forName("oracle.jdbc.OracleDriver");
                m_con = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD);
                m_con.setAutoCommit(true);
                }
            catch (Exception e)
                {
                throw ensureRuntimeException(e, "Connection failed");
                }
            }
    
        public String getTableName()        {
            return m_sTableName;
            }
    
        public Connection getConnection()
            {
            return m_con;
            }
    
        public Object load(Object oKey)
            {
            Object     oValue = null;
            Connection con    = getConnection();
            String     sSQL   = "SELECT id, value FROM " + getTableName()
                        + " WHERE id = ?";
            try
                {
                PreparedStatement stmt = con.prepareStatement(sSQL);
    
                stmt.setString(1, String.valueOf(oKey));
                ResultSet rslt = stmt.executeQuery();
                if (rslt.next())
                    {
                    oValue = rslt.getString(2);
                    if (rslt.next())
                        {
                        throw new SQLException("Not a unique key: " + oKey);
                        }                }
                stmt.close();
                }
            catch (SQLException e)
                {
                throw ensureRuntimeException(e, "Load failed: key=" + oKey);
                }
            return oValue;
            }
    
          public void store(Object oKey, Object oValue)
            {
            Connection con     = getConnection();
            String     sTable  = getTableName();
            String     sSQL;
            
            if (load(oKey) != null)
                {
                
                sSQL = "UPDATE " + sTable + " SET value = ? where id = ?";
                }
            else
                {
                
                sSQL = "INSERT INTO " + sTable + " (value, id) VALUES (?,?)";
                }
            try
                {
                PreparedStatement stmt = con.prepareStatement(sSQL);
                int i = 0;
                stmt.setString(++i, String.valueOf(oValue));
                stmt.setString(++i, String.valueOf(oKey));
                stmt.executeUpdate();
                stmt.close();
                }
            catch (SQLException e)
                {
                throw ensureRuntimeException(e, "Store failed: key=" + oKey);
                }
            }
        public void erase(Object oKey)
            {
            Connection con  = getConnection();
            String     sSQL = "DELETE FROM " + getTableName() + " WHERE id=?";
            try
                {
                PreparedStatement stmt = con.prepareStatement(sSQL);
    
                stmt.setString(1, String.valueOf(oKey));
                stmt.executeUpdate();
                stmt.close();
                }
            catch (SQLException e)
                {
                throw ensureRuntimeException(e, "Erase failed: key=" + oKey);
                }
            }
        public void eraseAll(Collection colKeys)
            {
            throw new UnsupportedOperationException();
            }
    
        
    
        public Map loadAll(Collection colKeys)        {
            throw new UnsupportedOperationException();
            }
    
        public void storeAll(Map mapEntries)
            {
            throw new UnsupportedOperationException();
            }
       
        public Iterator keys()
            {
            Connection con  = getConnection();
            String     sSQL = "SELECT id FROM " + getTableName();
            List       list = new LinkedList();
            
            try
                {
                PreparedStatement stmt = con.prepareStatement(sSQL);
                ResultSet         rslt = stmt.executeQuery();
                while (rslt.next())
                    {
                    Object oKey = rslt.getString(1);
                    list.add(oKey);
                    }
                stmt.close();
                }
            catch (SQLException e)
                {
                throw ensureRuntimeException(e, "Iterator failed");
                }
    
            return list.iterator();
            }
        
        }
    

9.3.3 キャッシュ構成ファイルの変更

作成済のキャッシュ構成ファイル(cache-config.xml)を、データベース・キャッシュ用に変更します。

キャッシュをバックエンド・データベースに接続するには、キャッシュ構成ファイル(cache-config.xml)の要素cachestore-schemeが必要です。cachestore-scheme要素は、com.tangosol.net.cache.CacheLoadercom.tangosol.net.cache.CacheStore のいずれかのインタフェースを実装するカスタム・クラスで構成する必要があります。

例9-7に示すデータベース・キャッシュのキャッシュ構成ファイルをコピーして、Oracle JDeveloperでcache-config.xmlファイル内の既存のコードを置き換えます。

例9-7 データベース・キャッシュ構成ファイル

<?xml version="1.0" encoding="UTF-8" ?>
<cache-config>
    <caching-scheme-mapping>
        
  <!-- 
    Caches with names that start with 'DBBacked' will be created 
    as distributed-db-backed.   
    -->
  <cache-mapping>
   <cache-name>DBBacked*</cache-name>
   <scheme-name>distributed-db-backed</scheme-name>
  </cache-mapping>
 </caching-scheme-mapping>
 <caching-schemes>
  <!-- 
    DB Backed Distributed caching scheme.
    -->
  <distributed-scheme>
   <scheme-name>distributed-db-backed</scheme-name>
   <service-name>DistributedCache</service-name>
   <backing-map-scheme>
    <read-write-backing-map-scheme>
     <internal-cache-scheme>
      <class-scheme>
       <class-name>com.tangosol.util.ObservableHashMap</class-name>
      </class-scheme>
     </internal-cache-scheme>
     <cachestore-scheme>  
      <class-scheme> 
       <class-name>com.oracle.handson.DBCacheStore</class-name> 
       <init-params>   
        <init-param> 
         <param-type>java.lang.String</param-type> 
         <param-value>CATALOG</param-value> 
        </init-param> 
       </init-params> 
      </class-scheme> 
     </cachestore-scheme>   
     <read-only>false</read-only>
     <!--
        To make this a write-through cache just change the value below to 0 (zero)
        -->
     <write-delay-seconds>0</write-delay-seconds>
    </read-write-backing-map-scheme>
   </backing-map-scheme>
   <listener/>
   <autostart>true</autostart>
  </distributed-scheme>
 </caching-schemes>
</cache-config>

キャッシュ構成ファイルでは、次の作業を行いました。

  • キャッシュ名パターンDBBacked*の定義。このパターンは、分散キャッシング・スキームdistributed-db-backedにマップされます。

  • coherence.DBCacheStoreクラスを使用して、分散スキームでCacheStoreスキームを指定。これによってCacheStoreインタフェースが実装されます。

  • キャッシュのバックエンドにあるデータベース表のinitパラメータをDBCacheStoreクラス用に指定。表の名前はinit-param要素で指定します。DBCacheStoreクラスは、キャッシュ・エントリの読取りや書込みなどのデータベース操作を行います。

  • Coherenceでは、read-write-backing-mapスキームが使用されているデータソースの読取り/書込みキャッシングをサポートしています。read-write-backing-mapスキームは、バッキング・マップを定義します。これによって永続ストアのキャッシュがサイズ制限付きで提供されます。ここでライトスルー・メカニズムを使用します。Oracle Coherenceでサポートされている読取り/書込みキャッシングのタイプを表9-2で説明します。

表9-2 Coherenceでサポートされている読取り/書込みキャッシングのタイプ

読取り/書込みキャッシングのタイプ 処理

リードスルー

キャッシュ・エントリは、必要に応じてデータベースからキャッシュに読み込まれ、アプリケーションで使用可能になります。

ライトスルー

キャッシュ・エントリに対する更新は、遅延なくデータベースと同期化されます。

リフレッシュアヘッド

キャッシュ・エントリは定期的にリフレッシュされます。

ライトビハインド

キャッシュ・エントリに対する更新は、キャッシュ構成ファイルのwrite-delay-seconds要素で指定した遅延の後に、データベースに非同期で書き込まれます。


9.3.4 データベース・キャッシュを作成するクラスの作成

データベース・キャッシュ用のJavaクラスDatabaseCacheを、Oracle JDeveloperで作成します。このクラスにはmainメソッドを含める必要があります。詳細は、「Javaクラスの作成」を参照してください。

このクラス・ファイルで、キャッシュ・エントリの追加、データベース・キャッシュの問合せ、およびキャッシュ・エントリの取得を行うコードを追加します。createCache()addEntry()retrieveEntry()eraseEntry()queryCache()の各メソッドを追加します。例9-8に示すコードをコピーできます。

例9-8 データベース・キャッシュ・クラス・ファイル用の実装

package com.oracle.handson;

import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
import com.tangosol.net.cache.ContinuousQueryCache;
import com.tangosol.util.Filter;
import com.tangosol.util.extractor.IdentityExtractor;
import com.tangosol.util.filter.LikeFilter;

import java.util.HashSet;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class DatabaseCache {
    NamedCache cache;
    public DatabaseCache() {
    }

    public void createCache() {
         cache = CacheFactory.getCache("DBBackedCache");
        //cache.put(new String("catalog3"), new String("Evolving Grid Management"));
           // System.out.println((String) cache.get( "catalog3"));
        
    }

    public void addEntry() {
    
        cache.put(new String("catalog3"), new String("Tuning Grid Management"));
        cache.put(new String("catalog4"), new String("Tuning Coherence"));
        cache.put(new String("catalog5"), new String("Tuning Database"));
        //System.out.println((String) cache.get( "catalog3"));
   
    }

    public void retrieveEntry() {
    System.out.println((String) cache.get( "catalog3"));
    }

    public void eraseEntry() {
    cache.remove(new String("catalog3"));
    }

    public void queryCache() {
        Filter filter = new LikeFilter(IdentityExtractor.INSTANCE, "Tuning%", '\\', true);
        HashSet hashSet=new HashSet();
        hashSet.add(new String("catalog3"));
        hashSet.add(new String("catalog4"));
        hashSet.add(new String("catalog5"));

        Map map=cache.getAll(hashSet);
        //ContinuousQueryCache queryCache = new ContinuousQueryCache(cache, filter);
        //Set results = queryCache.entrySet(filter);
        Set results = cache.entrySet(filter);
       /* Set results = cache.entrySet(filter);*/
        
        

       // if(results.isEmpty())
       // System.out.println("Result Set Empty");
            for (Iterator i = results.iterator(); i.hasNext();)
                {
                Map.Entry e = (Map.Entry) i.next();
                System.out.println("Catalog ID: "+e.getKey() + ", Title: "+e.getValue());
                }
    }
    

    public static void main(String[] args) {
        DatabaseCache databaseCache = new DatabaseCache();
        databaseCache.createCache();
       databaseCache.addEntry();
       //databaseCache.retrieveEntry();
        //databaseCache.eraseEntry();
       databaseCache.queryCache();
    }
}

コードの次の特徴に注目してください。

  • NamedCacheオブジェクトが、CacheFactoryクラスのgetCache()メソッドをcreateCache()メソッド内で使用して作成されています。

    NamedCache cache = CacheFactory.getCache("DBBackedCache");
    
  • DBBackedCacheは、キャッシュ・パターンDBBacked*に一致するため、cache-config.xmlファイル内の分散キャッシング・スキームdistributed-db-backedにマップされます。NamedCacheオブジェクトのput()メソッドを使用してキャッシュ・エントリを追加します。

    cache.put(new String("catalog3"), new String("Tuning Grid Management"));
    
  • ライトスルー・メカニズムが使用されているため、新しいキャッシュ・エントリもデータベースと同期化され、新しい行がCATALOG表に追加されます。createCache()addEntry()を除くすべてのメソッドをコメント・アウトします。

  • put()メソッドを起動すると、JDBCを使用して新しいキャッシュ・エントリをデータベース表CATALOGにマップするstore()メソッドがDBCacheStoreクラスで起動されます。Oracle Coherenceアプリケーションの出力がログ・ウィンドウに表示され、新しいキャッシュ・エントリが追加されます。オペレーション構成のデプロイメント・ディスクリプタがロードされ、キャッシュ構成がロードされ、新しいクラスタが作成されて、DistributedCacheサービスがクラスタに参加したことが、出力からわかります。

  • 新しいキャッシュ・エントリは、NamedCacheオブジェクトのremove()メソッドで削除できます。

    cache.remove(new String("catalog3"));
    
  • キャッシュ・エントリのバルク・アップロードは、putAll()メソッドを使用して実行されます。

  • キャッシュ・エントリを取得するには、NamedCacheオブジェクトのget()メソッドを使用します。たとえば、ID catalog1のキャッシュ・エントリを取得するには、次のように指定します。

    System.out.println((String) cache.get("catalog1"));
    
  • get()メソッドを起動すると、JDBCを使用してデータベース表のデータを取得するload()メソッドが、DBCacheStoreクラスで起動されます。

  • バルク取得は、NamedCacheオブジェクトのgetAll()メソッドを使用して実行されます。

  • Oracle Coherenceでは、フィルタを使用した検索条件に基づくキャッシュ・エントリの検索がサポートされています。Coherenceのフィルタは、com.tangosol.util.filterパッケージにあります。Oracle CoherenceのEnterprise EditionおよびGrid Editionでは、Coherenceキャッシュに索引を追加してパフォーマンスを改善できます。LikeFilterフィルタを使用してデータベース・キャッシュを問い合せると、キャッシュ・エントリは指定したパターンと照合されます。データベース・キャッシュに問い合せるには、問合せ前にキャッシュ・エントリを作成し、フィルタを使用する問合せが実行される前に、get()メソッドまたはgetAll()メソッドを使用してキャッシュ・エントリをキャッシュに取得する必要があります。したがって、getAll()メソッドを使用すると、データベース・データを取得してキャッシュ・エントリのコレクションを作成できます。

    HashSet hashSet=new HashSet(); 
    hashSet.add(new String("catalog1")); 
    hashSet.add(new String("catalog2")); 
    hashSet.add(new String("catalog3")); 
    Map map=cache.getAll(hashSet);
    
  • Tuningで始まるキャッシュ・エントリを検索するLikeFilterフィルタが作成されています。

    Filter filter = new LikeFilter(IdentityExtractor.INSTANCE, "Tuning%", '\\', true);
    
  • データベース・キャッシュの問合せは、entrySet()メソッドとLikeFilterフィルタを使用して行われます。

    Set results = cache.entrySet(filter);
    
  • 問合せの結果を反復して、取得したキャッシュ・エントリを出力します。

    for (Iterator i = results.iterator(); i.hasNext();) {
       Map.Entry e = (Map.Entry) i.next();
       System.out.println("Catalog ID: "+e.getKey() + ", Title: "+e.getValue());
    }
    
  • Oracle Coherenceでは、com.tangosol.net.cache.ContinuousQueryCacheクラスを使用して、連続問合せがサポートされています。連続問合せとは、連続問合せキャッシュを使用して最新の状態に保たれる問合せのことです。ContinuousQueryCacheでは、問合せの結果が変更される可能性があるイベントが発生した場合、問合せの結果はイベント・リスナーを使用して更新されます。ContinuousQueryCacheオブジェクトを作成するには、NamedCacheオブジェクトとLikeFilterオブジェクトを使用します。

    ContinuousQueryCache queryCache = new ContinuousQueryCache(cache, filter );
    
  • entrySet()メソッドを使用して結果セットが作成されます。

    Set results = queryCache.entrySet(filter);
    

9.3.5 データベース・キャッシュ・アプリケーションの実行

次の手順に従い、Oracleデータベース・キャッシュ・アプリケーションを実行します。

  1. -Dtangosol.coherence.distributed.localstorage=falseにより、ローカル記憶域を無効にするようInteractアプリケーションの実行構成を変更します。

    図9-3 ローカル記憶域の無効化

    ローカル記憶域の無効化
  2. 稼働しているキャッシュ・サーバーがあれば停止します。キャッシュ・サーバーを起動します(jpa-cache-server.cmd)。

  3. Oracle JDeveloperでDatabaseCacheアプリケーションを右クリックして「実行」を選択します。図9-4に、予想される結果を示します。

    図9-4 DatabaseCacheアプリケーションの実行結果

    DatabaseCacheアプリケーションの実行結果

    次のような例外が発生したとします。

    java.lang.IllegalArgumentException: No scheme for cache: "cachename, 
    

    このような例外は、cache-config.xmlファイルを編集し、<cache-name>要素内のDBBacked**に置き換えることによって削除できます。ファイルを保存して、Oracle JDeveloperでDatabaseCacheアプリケーションを再実行します。これで例外は表示されなくなります。

  4. ライトスルー・キャッシュを使用しているため、データベース表も更新されます。SQLプロンプトから、次のコードを入力します。

    select * from hr.catalog;
    

    例9-9に結果を示します。

    例9-9 selectコマンドからの出力

    ....
    SQL> select * from hr.catalog;
    
    -------------------------
    VALUE
    -------------------------------------------------------------------
    catalog3
    Tuning Grid Management
    catalog4
    Tuning Coherence
    
    catalog5
    Tuning Database
    
    
    ID
    -------------------------
    VALUE
    -------------------------------------------------------------------
    catalog1
    Tuning Undo Tablespace
    
    catalog2
    Tuning Your View Objects