ヘッダーをスキップ
Oracle Coherence開発者ガイド
リリース3.5
B56039-01
  目次
目次

戻る
戻る
 
次へ
次へ
 

G CacheStoreのサンプル

キャッシュ・ストアは、データベースなどの外部ストアとの間でキャッシュ・エントリの読取りおよび書込みを行うために、キャッシュによって使用されます。このページの例では、キャッシュ・ストアの操作に使用できるいくつかの方法を紹介します。


注意:

キャッシュをバルク・ロードすることによって、処理作業を軽減できます。次の例では、putメソッドを使用して、キャッシュ・ストアに値を書き込みます。多くの場合、putAllメソッドを使用してバルク・ロードを実行すると、処理作業およびネットワーク・トラフィックが軽減されます。バルク・ロードの詳細は、第12章「キャッシュの事前ロード」を参照してください。

CacheStoreのサンプル

この項では、com.tangosol.net.cache.CacheStoreインタフェースの非常に基本的な実装について説明します。例G-1の実装では、JDBCによる単一のデータベース接続を使用し、バルク操作は使用しません。完全な実装では接続プールが使用されます。また、ライトビハインドが使用される場合は、CacheStore.storeAll()を実装してJDBCのバルク挿入およびバルク更新を行います。データベースのキャッシュ・コンフィギュレーションのサンプルについては、「データベースのキャッシュ」を参照してください。

例G-1 CacheStoreインタフェースの実装

package com.tangosol.examples.coherence;


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;


/**
* An example implementation of CacheStore
* interface.
*
* @author erm 2003.05.01
*/
public class DBCacheStore
        extends Base
        implements CacheStore
    {
    // ----- constructors ---------------------------------------------------
    /**
    * Constructs DBCacheStore for a given database table.
    *
    * @param sTableName the db table name
    */
    public DBCacheStore(String sTableName)
        {
        m_sTableName = sTableName;
        configureConnection();
        }

        /**
        * Set up the DB connection.
        */
        protected void configureConnection()
                {
                try
                        {
                        Class.forName("org.gjt.mm.mysql.Driver");
                        m_con = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD);
                        m_con.setAutoCommit(true);
                        }
                catch (Exception e)
                        {
                        throw ensureRuntimeException(e, "Connection failed");
                        }
                }


        // ---- accessors -------------------------------------------------------

    /**
    * Obtain the name of the table this CacheStore is persisting to.
    *
    * @return the name of the table this CacheStore is persisting to
    */
    public String getTableName()
        {
        return m_sTableName;
        }

    /**
    * Obtain the connection being used to connect to the database.
    *
    * @return the connection used to connect to the database
    */
    public Connection getConnection()
        {
        return m_con;
        }


    // ----- CacheStore Interface --------------------------------------------

    /**
    * Return the value associated with the specified key, or null if the
    * key does not have an associated value in the underlying store.
    *
    * @param oKey  key whose associated value is to be returned
    *
    * @return the value associated with the specified key, or
    *         <tt>null</tt> if no value is available for that key
    */
    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;
        }

    /**
    * Store the specified value under the specific key in the underlying
    * store. This method is intended to support both key/value creation
    * and value update for a specific key.
    *
    * @param oKey    key to store the value under
    * @param oValue  value to be stored
    *
    * @throws UnsupportedOperationException  if this implementation or the
    *         underlying store is read-only
    */
    public void store(Object oKey, Object oValue)
        {
        Connection con     = getConnection();
        String     sTable  = getTableName();
        String     sSQL;

        // the following is very inefficient; it is recommended to use DB
        // specific functionality that is, REPLACE for MySQL or MERGE for Oracle
 if (load(oKey) != null)
                {
                // key exists - update
         sSQL = "UPDATE " + sTable + " SET value = ? where id = ?";
                }
        else
                {
                // new key - insert
         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);
                }
        }

    /**
    * Remove the specified key from the underlying store if present.
    *
    * @param oKey key whose mapping is to be removed from the map
    *
    * @throws UnsupportedOperationException  if this implementation or the
    *         underlying store is read-only
    */
    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);
            }
        }

        /**
        * Remove the specified keys from the underlying store if present.
        *
        * @param colKeys  keys whose mappings are being removed from the cache
        *
        * @throws UnsupportedOperationException  if this implementation or the
        *         underlying store is read-only
        */
        public void eraseAll(Collection colKeys)
                {
                throw new UnsupportedOperationException();
                }

        /**
        * Return the values associated with each the specified keys in the
        * passed collection. If a key does not have an associated value in
        * the underlying store, then the return map will not have an entry
        * for that key.
        *
        * @param colKeys  a collection of keys to load
        *
        * @return a Map of keys to associated values for the specified keys
        */
        public Map loadAll(Collection colKeys)
                {
                throw new UnsupportedOperationException();
                }

        /**
        * Store the specified values under the specified keys in the underlying
        * store. This method is intended to support both key/value creation
        * and value update for the specified keys.
        *
        * @param mapEntries   a Map of any number of keys and values to store
        *
        * @throws UnsupportedOperationException  if this implementation or the
        *         underlying store is read-only
        */
        public void storeAll(Map mapEntries)
                {
                throw new UnsupportedOperationException();
                }

    /**
    * Iterate all keys in the underlying store.
    *
    * @return a read-only iterator of the keys in the underlying store
    */
    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();
        }


    // ----- data members ---------------------------------------------------

    /**
    * The connection.
    */
    protected Connection m_con;

    /**
    * The db table name.
    */
    protected String m_sTableName;

        /**
        * Driver class name.
        */
        private static final String DB_DRIVER   = "org.gjt.mm.mysql.Driver";

        /**
        * Connection URL.
        */
        private static final String DB_URL      = "jdbc:mysql://localhost:3306/CacheStore";

        /**
        * User name.
        */
        private static final String DB_USERNAME = "root";

        /**
        * Password.
        */
        private static final String DB_PASSWORD = null;
    }

制御可能なCacheStoreのサンプル

この項では、制御可能なキャッシュ・ストアの実装を紹介します。このシナリオでは、キャッシュ内で更新された値をデータ・ストアに書き込む時点をアプリケーションによって制御できます。このシナリオは、起動時にデータ・ストアからキャッシュへの初期移入を行う際に最も一般的に使用されます。起動時には、キャッシュの値を元のデータ・ストアに書き込む必要がありません。このような書込みはリソースの浪費になります。

例G-2Main.javaファイルは、制御可能なキャッシュ・ストアの次の2種類の操作方法を示しています。

ControllableCacheStore1ControllableCacheStore2は両方とも、com.tangosol.net.cache.AbstractCacheStoreクラスを拡張したものです。このヘルパー・クラスによって、storeAll操作およびeraseAll操作の非最適実装が行われます。

CacheStoreAware.javaファイルは、キャッシュに追加されるオブジェクトをデータベースに格納しないことを示す場合に使用できるインタフェースです。

キャッシュ・コンフィギュレーションのサンプルについては、「データベースのキャッシュ」を参照してください。

例G-2には、Main.javaインタフェースが一覧表示されています。

例G-2 Main.java: 制御可能なCacheStoreとの相互作用

import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
import com.tangosol.net.cache.AbstractCacheStore;
import com.tangosol.util.Base;

import java.io.Serializable;
import java.util.Date;

public class Main extends Base
    {

    /**
     * CacheStore implementation which is controlled by a control cache
     */
    public static class ControllableCacheStore1 extends AbstractCacheStore
        {
        public static final String CONTROL_CACHE = "cachestorecontrol";

        String m_sName;

        public static void enable(String sName)
            {
            CacheFactory.getCache(CONTROL_CACHE).put(sName, Boolean.TRUE);
            }

        public static void disable(String sName)
            {
            CacheFactory.getCache(CONTROL_CACHE).put(sName, Boolean.FALSE);
            }

        public void store(Object oKey, Object oValue)
            {
            Boolean isEnabled = (Boolean) CacheFactory.getCache(CONTROL_CACHE).get(m_sName);
            if (isEnabled != null && isEnabled.booleanValue())
                {
                log("controllablecachestore1: enabled " + oKey + " = " + oValue);
                }
            else
                {
                log("controllablecachestore1: disabled " + oKey + " = " + oValue);
                }
            }

        public Object load(Object oKey)
            {
            log("controllablecachestore1: load:" + oKey);
            return new MyValue1(oKey);
            }

        public ControllableCacheStore1(String sName)
            {
            m_sName = sName;
            }

        }

    /**
     * CacheStore implementation which is controlled by values
     * implementing the CacheStoreAware interface
     */
    public static class ControllableCacheStore2 extends AbstractCacheStore
        {

        public void store(Object oKey, Object oValue)
            {
            boolean isEnabled = oValue instanceof CacheStoreAware ? !((CacheStoreAware) oValue).isSkipStore() : true;
            if (isEnabled)
                {
                log("controllablecachestore2: enabled " + oKey + " = " + oValue);
                }
            else
                {
                log("controllablecachestore2: disabled " + oKey + " = " + oValue);
                }
            }

        public Object load(Object oKey)
            {
            log("controllablecachestore2: load:" + oKey);
            return new MyValue2(oKey);
            }

        }

    public static class MyValue1 implements Serializable
        {
        String m_sValue;

        public String getValue()
            {
            return m_sValue;
            }

        public String toString()
            {
            return "MyValue1[" + getValue() + "]";
            }

        public MyValue1(Object obj)
            {
            m_sValue = "value:" + obj;
            }
        }

    public static class MyValue2 extends MyValue1 implements CacheStoreAware
        {
        boolean m_isSkipStore = false;

        public boolean isSkipStore()
            {
            return m_isSkipStore;
            }

        public void skipStore()
            {
            m_isSkipStore = true;
            }

        public String toString()
            {
            return "MyValue2[" + getValue() + "]";
            }

        public MyValue2(Object obj)
            {
            super(obj);
            }

        }

    public static void main(String[] args)
        {
        try
            {

            // example 1

            NamedCache cache1 = CacheFactory.getCache("cache1");

            // disable cachestore
            ControllableCacheStore1.disable("cache1");
            for(int i = 0; i < 5; i++)
                {
                cache1.put(new Integer(i), new MyValue1(new Date()));
                }

            // enable cachestore
            ControllableCacheStore1.enable("cache1");
            for(int i = 0; i < 5; i++)
                {
                cache1.put(new Integer(i), new MyValue1(new Date()));
                }

            // example 2

            NamedCache cache2 = CacheFactory.getCache("cache2");

            // add some values with cachestore disabled
            for(int i = 0; i < 5; i++)
                {
                MyValue2 value = new MyValue2(new Date());
                value.skipStore();
                cache2.put(new Integer(i), value);
                }

            // add some values with cachestore enabled
            for(int i = 0; i < 5; i++)
                {
                cache2.put(new Integer(i), new MyValue2(new Date()));
                }


            }
        catch(Throwable oops)
            {
            err(oops);
            }
        finally
            {
            CacheFactory.shutdown();
            }
        }

    }

例G-3には、CacheStoreAware.javaインタフェースが一覧表示されています。

例G-3 CacheStoreAware.javaインタフェース

public interface CacheStoreAware
    {
    public boolean isSkipStore();
    }