There are two ways to integrate Hibernate and Coherence:

  • Coherence can be used as a second level cache provider for Hibernate.
  • Hibernate can be used as a CacheStore provider for Coherence.

In the case Coherence is used as a second level cache provider for Hibernate, Coherence caching is fully controlled by Hibernate; thus a good understanding of Hibernate caching mechanisms is required. This scenario is a good fit for applications that:

  • Use Hibernate APIs for the data access management.
  • Have complex object models.
  • Have fine-grained transactional requirements.
  • Have an application server cluster that run the Hibernate application.

The set-up using Hibernate3 can be found in the post Hibernate and Coherence. Note that in the case of Hibernate3 we provided implementations for the interfaces org.hibernate.cache.Cache and org.hibernate.cache.CacheProvider. In Hibernate4 this concepts has been changed to a more fine grained implementation structure, for example,

  • At the top we have an implementation for the RegionFactory interface. This implementation defines how to start and stop the cache, sets some defaults (such as if minimal puts are enabled and the access type) and defines the region implementation. It is now possible to define separate implementation for entities and collections etcetera.
    • How entities or collections are cached are defined by implementing regions, such as, EntityRegion – Defines the contract for a cache region which will specifically be used to store entity data. CollectionRegion – Defines the contract for a cache region which will specifically be used to store collection data. The region contracts define an access strategy for the requested access type.
      • To define how the caching is handled we implement the following three interfaces:
        • TransactionalDataRegion – Defines the contract for regions which hold transactionally-managed data.
        • GeneralDataRegion – Contract for general-purpose cache regions.
        • Region – Defines a contract for accessing a particular named region within the underlying cache implementation.

Let us look at an example of how to implement the various interfaces in the case we are dealing with an entity. Our entity looks as follows:

package model.entities;

import java.io.Serializable;

public class Department implements Serializable {

    private Integer departmentNumber;
    private String departmentName;
    private String location;

    public Department() {
    }

    public void setDepartmentNumber(Integer departmentNumber) {
        this.departmentNumber = departmentNumber;
    }

    public Integer getDepartmentNumber() {
        return departmentNumber;
    }

    public void setDepartmentName(String departmentName) {
        this.departmentName = departmentName;
    }

    public String getDepartmentName() {
        return departmentName;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String getLocation() {
        return location;
    }

    @Override
    public boolean equals(Object object) {
        System.out.println("DEPARTMENT EQUALS METHOD CALLED " + object);
        if (this == object) {
            return true;
        }

        if (object == null) {
            return false;
        }

        if (!(object instanceof Department)) {
            return false;
        }

        Department department = (Department) object;
        return departmentNumber.equals(department.getDepartmentNumber());
    }

    @Override
    public int hashCode() {
        if (departmentNumber != null) {
            return 31 * departmentNumber.hashCode();
        } else {
            return System.identityHashCode(this);
        }
    }

    @Override
    public String toString() {
        return departmentName + ", " + location;
    }
}

which has the following mapping

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="model.entities">
    <class name="Department" table="DEPT">
        <id name="departmentNumber" type="integer" column="DEPTNO">
            <generator class="assigned"/>
        </id>
        <property name="departmentName" type="string" column="DNAME"/>
        <property name="location" type="string" column="LOC"/>
    </class>
</hibernate-mapping>

We start with defining the contract for accessing a particular named region within the underlying cache implementation, by providing an implementation for the org.hibernate.cache.spi.Region interface

package cache.regions;

import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.Region;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class CoherenceRegion implements Region {

    private final NamedCache cache;

    public CoherenceRegion(NamedCache cache) {
        this.cache = cache;
    }

    public NamedCache getCache() {
        return cache;
    }

    public String getName() {
        return cache.getCacheName();
    }

    public void destroy() throws CacheException {
        cache.release();
    }

    public boolean contains(Object key) {
        System.out.println("LOOK IF DATA IS IN THE CACHE " + key);
        return cache.containsKey(key);
    }

    public long getSizeInMemory() {
        return -1;
    }

    public long getElementCountInMemory() {
        long size = 0;
        try {
            size = cache.size();
        } catch (CacheException ex) {
            throw new CacheException(ex);
        }
        return size;
    }

    public long getElementCountOnDisk() {
        return -1;
    }

    public Map toMap() {
        Map result = new HashMap();
        try {
            Iterator iterator = cache.keySet().iterator();
            while (iterator.hasNext()) {
                Object key = iterator.next();
                result.put(key, cache.get((Serializable) key));
            }
        } catch (Exception ex) {
            throw new CacheException(ex);
        }
        return result;
    }

    public long nextTimestamp() {
        return CacheFactory.getCluster().getTimeMillis();
    }

    public int getTimeout() {
        return 10000;
    }
}

Next, we provide the contract for general-purpose cache regions (i.e. how to get, put and remove data from the cache), by implementing the org.hibernate.cache.spi.GeneralDataRegion interface

package cache.regions;

import com.tangosol.net.NamedCache;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.GeneralDataRegion;

public class CoherenceGeneralDataRegion extends CoherenceRegion implements GeneralDataRegion {

    public CoherenceGeneralDataRegion(NamedCache cache) {
        super(cache);
    }

    public Object get(Object key) throws CacheException {
        System.out.println("GET DATA FROM THE CACHE " + key);
        return getCache().get(key);
    }

    public void put(Object key, Object value) throws CacheException {
        System.out.println("PUT DATA INTO THE CACHE " + key + ", " + value);
        getCache().put(key, value);
    }

    public void evict(Object key) throws CacheException {
        System.out.println("REMOVE DATA FROM THE CACHE " + key);
        getCache().remove(key);
    }

    public void evictAll() throws CacheException {
        getCache().clear();
    }
}

Subsequently, we define the contract for regions which hold transactionally-managed data, by implementing the org.hibernate.cache.spi.TransactionalDataRegion interface

package cache.regions;

import com.tangosol.net.NamedCache;
import org.hibernate.cache.spi.CacheDataDescription;
import org.hibernate.cache.spi.TransactionalDataRegion;

public class CoherenceTransactionalDataRegion extends CoherenceGeneralDataRegion implements TransactionalDataRegion {

    private final CacheDataDescription metadata;

    public CoherenceTransactionalDataRegion(NamedCache cache, CacheDataDescription metadata) {
        super(cache);
        this.metadata = metadata;
    }

    public boolean isTransactionAware() {
        return false;
    }

    public CacheDataDescription getCacheDataDescription() {
        return metadata;
    }
}

As a final step we need to build the contract for a cache region which will specifically be used to store entity data (and define which access type to use), by implementing the org.hibernate.cache.spi.EntityRegion interface

package cache.regions;

import cache.strategy.CoherenceNonStrictReadWriteEntityRegionAccessStrategy;
import com.tangosol.net.NamedCache;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.CacheDataDescription;
import org.hibernate.cache.spi.EntityRegion;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;

public class CoherenceEntityRegion extends CoherenceTransactionalDataRegion implements EntityRegion {

    public CoherenceEntityRegion(NamedCache cache, CacheDataDescription metadata) {
        super(cache, metadata);
    }

    public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
        switch (accessType) {
            case NONSTRICT_READ_WRITE:
                return new CoherenceNonStrictReadWriteEntityRegionAccessStrategy(this);
            default:
                throw new IllegalArgumentException("unrecognized access strategy type [" + accessType + "]");
        }
    }
}

In the implementation above, we assume the access strategy always to be non-strict read-write. There are four access strategies that can be used:

  • Read only – If the application needs to read, but not modify, instances of a persistent class, a read-only cache can be used. This is the simplest and optimal performing strategy. It is even safe for use in a cluster.
  • Read/write – If the application needs to update data, a read-write cache might be appropriate. This cache strategy should never be used if serializable transaction isolation level is required. If the cache is used in a JTA environment, you must specify the property hibernate.transaction.manager_lookup_class and naming a strategy for obtaining the JTA TransactionManager. In other environments, you should ensure that the transaction is completed when Session.close() or Session.disconnect() is called. If you want to use this strategy in a cluster, you should ensure that the underlying cache implementation supports locking.
  • Non-strict read/write – If the application only occasionally needs to update data (i.e. if it is extremely unlikely that two transactions would try to update the same item simultaneously), and strict transaction isolation is not required, a non-strict-read-write cache might be appropriate. If the cache is used in a JTA environment, you must specify hibernate.transaction.manager_lookup_class. In other environments, you should ensure that the transaction is completed when Session.close() or Session.disconnect() is called.
  • Transactional – The transactional cache strategy provides support for fully transactional cache providers. Such a cache can only be used in a JTA environment and you must specify hibernate.transaction.manager_lookup_class.

To define the contract for transactional and concurrent access to cached entity (and collection) data, we start by implementing the RegionAccessStrategy interface

package cache.strategy;

import cache.regions.CoherenceEntityRegion;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.access.RegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;

public class CoherenceEntityRegionAccessStrategy implements RegionAccessStrategy {

    private final CoherenceEntityRegion coherenceEntityRegion;

    public CoherenceEntityRegionAccessStrategy(CoherenceEntityRegion coherenceEntityRegion) {
        this.coherenceEntityRegion = coherenceEntityRegion;
    }

    public CoherenceEntityRegion getCoherenceEntityRegion() {
        return coherenceEntityRegion;
    }

    public Object get(Object key, long transactionTimeStamp) throws CacheException {
        return getCoherenceEntityRegion().get(key);
    }

    public boolean putFromLoad(Object key, Object value, long transactionTimeStamp, Object version) throws CacheException {
        return putFromLoad(key, value, transactionTimeStamp, version, true);
    }

    public boolean putFromLoad(Object key, Object value, long transationTimeStamp, Object version, boolean minimalPutsOverride) throws CacheException {
        if (key == null || value == null) {
            return false;
        }

        // check if item is already in the cache
        if (minimalPutsOverride && getCoherenceEntityRegion().contains(key)) {
            return false;
        }

        // key is cached
        getCoherenceEntityRegion().put(key, value);
        return true;
    }

    public SoftLock lockItem(Object key, Object version) throws CacheException {
        getCoherenceEntityRegion().getCache().lock(key);
        return null;
    }

    public SoftLock lockRegion() throws CacheException {
        return null;
    }

    public void unlockItem(Object key, SoftLock softLock) throws CacheException {
        getCoherenceEntityRegion().getCache().unlock(key);
    }

    public void unlockRegion(SoftLock softLock) throws CacheException {
        evictAll();
    }

    public void remove(Object key) throws CacheException {
        evict(key);
    }

    public void removeAll() throws CacheException {
        evictAll();
    }

    public void evict(Object key) throws CacheException {
        getCoherenceEntityRegion().evict(key);
    }

    public void evictAll() throws CacheException {
        getCoherenceEntityRegion().evictAll();
    }
}

Finally, we define the contract for managing transactional and concurrent access to cached entity data, by implementing the EntityRegionAccessStrategy interface

package cache.strategy;

import cache.regions.CoherenceEntityRegion;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.EntityRegion;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;

public class CoherenceNonStrictReadWriteEntityRegionAccessStrategy extends CoherenceEntityRegionAccessStrategy implements EntityRegionAccessStrategy {

    public CoherenceNonStrictReadWriteEntityRegionAccessStrategy(CoherenceEntityRegion region) {
        super(region);
    }

    public EntityRegion getRegion() {
        return getCoherenceEntityRegion();
    }

    public boolean insert(Object key, Object value, Object version) throws CacheException {
        return false;
    }

    public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
        return false;
    }

    public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException {
        return false;
    }

    public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock softLock) throws CacheException {
        return false;
    }
}

To make sure Hibernate uses a second-level cache, we use the following configuration

<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
        <property name="hibernate.connection.url">jdbc:oracle:thin:@192.168.1.60:1521:orcl11</property>
        <property name="hibernate.connection.username">example</property>
        <property name="hibernate.connection.password">example</property>
        <!-- SQL dialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
        <!-- Enable Hibernate's automatic session context management -->
        <property name="hibernate.current_session_context_class">thread</property>
        <!-- Second-level cache config -->
        <property name="hibernate.cache.region.factory_class">cache.CoherenceRegionFactory</property>
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <!-- Echo all executed SQL to stdout -->
        <property name="hibernate.show_sql">false</property>
        <property name="hibernate.format_sql">false</property>
        <!-- Configure SessionFactory -->
        <mapping resource="model/entities/Department.hbm.xml"/>
        <!-- Cache configuration-->
        <class-cache class="model.entities.Department" usage="nonstrict-read-write"/>
    </session-factory>
</hibernate-configuration>

For the Coherence cache configuration we have used the following

<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
              xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config coherence-cache-config.xsd">
    <caching-scheme-mapping>
        <cache-mapping>
            <cache-name>*</cache-name>
            <scheme-name>hibernate-replicated</scheme-name>
            <init-params>
                <init-param>
                    <param-name>size-limit</param-name>
                    <param-value>1000</param-value>
                </init-param>
            </init-params>
        </cache-mapping>
    </caching-scheme-mapping>
    <caching-schemes>
        <replicated-scheme>
            <scheme-name>hibernate-replicated</scheme-name>
            <service-name>HibernateReplicatedCache</service-name>
            <serializer>
                <instance>
                    <class-name>com.tangosol.io.DefaultSerializer</class-name>
                </instance>
            </serializer>
            <backing-map-scheme>
                <local-scheme>
                    <high-units>{size-limit 0}</high-units>
                </local-scheme>
            </backing-map-scheme>
            <autostart>true</autostart>
        </replicated-scheme>
    </caching-schemes>
</cache-config>

Now let us test the set-up, by using the following

package model.test;

import model.entities.Department;
import model.logic.DepartmentDAO;
import model.logic.DepartmentDAOBean;

import java.util.List;
import java.util.Random;

public class Test {

    public static void main(String[] args) {
        DepartmentDAO departmentDAO = new DepartmentDAOBean();
        //doRandomTest(departmentDAO);
        doPersistenceTest(departmentDAO);
    }

    private static void doRandomTest(DepartmentDAO departmentDAO) {
        Integer[] integers = {10, 20, 30, 40};
        Random random = new Random();
        while (true) {
            departmentDAO.findEntity(integers[random.nextInt(4)]);
        }
    }

    private static void doPersistenceTest(DepartmentDAO departmentDAO) {
        Integer departmentNumber = 12;
        Department newDepartment = createDepartment(departmentNumber, "SOMEDEPARTMENT", "SOMEWHERE");

        System.out.println("ADD DEPARTMENT ENTITY");
        departmentDAO.addEntity(newDepartment);

        System.out.println("FIND DEPARTMENT ENTITY");
        Department department = departmentDAO.findEntity(20);
        System.out.println("FIND ENTITY " + department);

        System.out.println("FIND DEPARTMENT ENTITIES");
        List<Department> departments = departmentDAO.findEntities();
        System.out.println("FIND ENTITIES " + departments);

        System.out.println("UPDATE DEPARTMENT ENTITY");
        newDepartment.setDepartmentName("Else");
        departmentDAO.updateEntity(newDepartment);

        System.out.println("FIND DEPARTMENT ENTITIES");
        departments = departmentDAO.findEntities();
        System.out.println("FIND ENTITIES " + departments);

        System.out.println("REMOVE DEPARTMENT ENTITY");
        departmentDAO.removeEntity(departmentNumber);

        System.out.println("FIND DEPARTMENT ENTITIES");
        departments = departmentDAO.findEntities();
        System.out.println("FIND ENTITIES " + departments);
    }

    private static Department createDepartment(Integer departmentNumber, String departmentName, String location) {
        Department department = new Department();
        department.setDepartmentNumber(departmentNumber);
        department.setDepartmentName(departmentName);
        department.setLocation(location);
        return department;
    }
}

When we run the test (with also the JVM parameters -Dtangosol.coherence.cacheconfig=hibernate-cache-config.xml -Dtangosol.coherence.management=all -Dtangosol.coherence.management.remote=true) the following is observed

ADD DEPARTMENT ENTITY
Jun 21, 2012 2:01:45 PM org.hibernate.annotations.common.Version <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.1.Final}
Jun 21, 2012 2:01:45 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.1.2.Final}
Jun 21, 2012 2:01:45 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Jun 21, 2012 2:01:45 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
Jun 21, 2012 2:01:45 PM org.hibernate.cfg.Configuration configure
INFO: HHH000043: Configuring from resource: /hibernate.cfg.xml
Jun 21, 2012 2:01:45 PM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: HHH000040: Configuration resource: /hibernate.cfg.xml
Jun 21, 2012 2:01:45 PM org.hibernate.internal.util.xml.DTDEntityResolver resolveEntity
WARN: HHH000223: Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/. Use namespace http://www.hibernate.org/dtd/ instead. Refer to Hibernate 3.6 Migration Guide!
Jun 21, 2012 2:01:45 PM org.hibernate.cfg.Configuration addResource
INFO: HHH000221: Reading mappings from resource: model/entities/Department.hbm.xml
Jun 21, 2012 2:01:45 PM org.hibernate.internal.util.xml.DTDEntityResolver resolveEntity
WARN: HHH000223: Recognized obsolete hibernate namespace http://hibernate.sourceforge.net/. Use namespace http://www.hibernate.org/dtd/ instead. Refer to Hibernate 3.6 Migration Guide!
Jun 21, 2012 2:01:45 PM org.hibernate.cfg.Configuration doConfigure
INFO: HHH000041: Configured SessionFactory: null
Jun 21, 2012 2:01:45 PM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000402: Using Hibernate built-in connection pool (not for production use!)
Jun 21, 2012 2:01:45 PM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20
Jun 21, 2012 2:01:45 PM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000006: Autocommit mode: false
Jun 21, 2012 2:01:45 PM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000401: using driver [oracle.jdbc.OracleDriver] at URL [jdbc:oracle:thin:@192.168.1.60:1521:orcl11]
Jun 21, 2012 2:01:45 PM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000046: Connection properties: {user=example, password=****}
Jun 21, 2012 2:01:45 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect
Jun 21, 2012 2:01:45 PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
Jun 21, 2012 2:01:45 PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
2012-06-21 14:01:45.830/0.864 Oracle Coherence 3.7.1.0 <Info> (thread=main, member=n/a): Loaded operational configuration from "jar:file:/C:/temp/frameworks/VoorbeeldSecondLevelCacheHibernate4/lib/coherence/coherence.jar!/tangosol-coherence.xml"
2012-06-21 14:01:45.861/0.895 Oracle Coherence 3.7.1.0 <Info> (thread=main, member=n/a): Loaded operational overrides from "jar:file:/C:/temp/frameworks/VoorbeeldSecondLevelCacheHibernate4/lib/coherence/coherence.jar!/tangosol-coherence-override-dev.xml"
2012-06-21 14:01:45.861/0.895 Oracle Coherence 3.7.1.0 <D5> (thread=main, member=n/a): Optional configuration override "/tangosol-coherence-override.xml" is not specified
2012-06-21 14:01:45.863/0.897 Oracle Coherence 3.7.1.0 <D5> (thread=main, member=n/a): Optional configuration override "/custom-mbeans.xml" is not specified

Oracle Coherence Version 3.7.1.0 Build 27797
 Grid Edition: Development mode
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

2012-06-21 14:01:45.996/1.030 Oracle Coherence GE 3.7.1.0 <Info> (thread=main, member=n/a): Loaded Reporter configuration from "jar:file:/C:/temp/frameworks/VoorbeeldSecondLevelCacheHibernate4/lib/coherence/coherence.jar!/reports/report-group.xml"
2012-06-21 14:01:46.408/1.442 Oracle Coherence GE 3.7.1.0 <D4> (thread=main, member=n/a): TCMP bound to /192.168.238.1:8088 using SystemSocketProvider
2012-06-21 14:01:49.759/4.794 Oracle Coherence GE 3.7.1.0 <Info> (thread=Cluster, member=n/a): Created a new cluster "cluster:0xFCDB" with Member(Id=1, Timestamp=2012-06-21 14:01:46.513, Address=192.168.238.1:8088, MachineId=949, Location=site:,machine:r-PC,process:200, Role=IntellijRtExecutionAppMain, Edition=Grid Edition, Mode=Development, CpuCount=8, SocketCount=8) UID=0xC0A8EE01000001380EEB6E1103B51F98
2012-06-21 14:01:49.767/4.801 Oracle Coherence GE 3.7.1.0 <Info> (thread=main, member=n/a): Started cluster Name=cluster:0xFCDB

Group{Address=224.3.7.0, Port=37000, TTL=4}

MasterMemberSet(
  ThisMember=Member(Id=1, Timestamp=2012-06-21 14:01:46.513, Address=192.168.238.1:8088, MachineId=949, Location=site:,machine:r-PC,process:200, Role=IntellijRtExecutionAppMain)
  OldestMember=Member(Id=1, Timestamp=2012-06-21 14:01:46.513, Address=192.168.238.1:8088, MachineId=949, Location=site:,machine:r-PC,process:200, Role=IntellijRtExecutionAppMain)
  ActualMemberSet=MemberSet(Size=1
    Member(Id=1, Timestamp=2012-06-21 14:01:46.513, Address=192.168.238.1:8088, MachineId=949, Location=site:,machine:r-PC,process:200, Role=IntellijRtExecutionAppMain)
    )
  MemberId|ServiceVersion|ServiceJoined|MemberState
    1|3.7.1|2012-06-21 14:01:49.76|JOINED
  RecycleMillis=1200000
  RecycleSet=MemberSet(Size=0
    )
  )

TcpRing{Connections=[]}
IpMonitor{AddressListSize=0}

2012-06-21 14:01:49.826/4.860 Oracle Coherence GE 3.7.1.0 <D5> (thread=Invocation:Management, member=1): Service Management joined the cluster with senior service member 1
2012-06-21 14:01:49.906/4.940 Oracle Coherence GE 3.7.1.0 <Info> (thread=main, member=1): Loaded cache configuration from "file:/C:/temp/frameworks/VoorbeeldSecondLevelCacheHibernate4/out/production/VoorbeeldSecondLevelCacheHibernate4/hibernate-cache-config.xml"
2012-06-21 14:01:49.943/4.977 Oracle Coherence GE 3.7.1.0 <D5> (thread=ReplicatedCache:HibernateReplicatedCache, member=1): Service HibernateReplicatedCache joined the cluster with senior service member 1
FIND DEPARTMENT ENTITY
GET DATA FROM THE CACHE model.entities.Department#20
LOOK IF DATA IS IN THE CACHE model.entities.Department#20
PUT DATA INTO THE CACHE model.entities.Department#20, CacheEntry(model.entities.Department)[RESEARCH,DALLAS]
FIND ENTITY RESEARCH, DALLAS
FIND DEPARTMENT ENTITIES
LOOK IF DATA IS IN THE CACHE model.entities.Department#10
PUT DATA INTO THE CACHE model.entities.Department#10, CacheEntry(model.entities.Department)[ACCOUNTING,NEW YORK]
LOOK IF DATA IS IN THE CACHE model.entities.Department#20
LOOK IF DATA IS IN THE CACHE model.entities.Department#30
PUT DATA INTO THE CACHE model.entities.Department#30, CacheEntry(model.entities.Department)[SALES,CHICAGO]
LOOK IF DATA IS IN THE CACHE model.entities.Department#40
PUT DATA INTO THE CACHE model.entities.Department#40, CacheEntry(model.entities.Department)[OPERATIONS,BOSTON]
LOOK IF DATA IS IN THE CACHE model.entities.Department#12
PUT DATA INTO THE CACHE model.entities.Department#12, CacheEntry(model.entities.Department)[SOMEDEPARTMENT,SOMEWHERE]
FIND ENTITIES [ACCOUNTING, NEW YORK, RESEARCH, DALLAS, SALES, CHICAGO, OPERATIONS, BOSTON, SOMEDEPARTMENT, SOMEWHERE]
UPDATE DEPARTMENT ENTITY
FIND DEPARTMENT ENTITIES
LOOK IF DATA IS IN THE CACHE model.entities.Department#10
LOOK IF DATA IS IN THE CACHE model.entities.Department#20
LOOK IF DATA IS IN THE CACHE model.entities.Department#30
LOOK IF DATA IS IN THE CACHE model.entities.Department#40
LOOK IF DATA IS IN THE CACHE model.entities.Department#12
FIND ENTITIES [ACCOUNTING, NEW YORK, RESEARCH, DALLAS, SALES, CHICAGO, OPERATIONS, BOSTON, Else, SOMEWHERE]
REMOVE DEPARTMENT ENTITY
GET DATA FROM THE CACHE model.entities.Department#12
REMOVE DATA FROM THE CACHE model.entities.Department#12
FIND DEPARTMENT ENTITIES
LOOK IF DATA IS IN THE CACHE model.entities.Department#10
LOOK IF DATA IS IN THE CACHE model.entities.Department#20
LOOK IF DATA IS IN THE CACHE model.entities.Department#30
LOOK IF DATA IS IN THE CACHE model.entities.Department#40
FIND ENTITIES [ACCOUNTING, NEW YORK, RESEARCH, DALLAS, SALES, CHICAGO, OPERATIONS, BOSTON]
2012-06-21 14:01:50.346/5.380 Oracle Coherence GE 3.7.1.0 <D4> (thread=ShutdownHook, member=1): ShutdownHook: stopping cluster node

When we really want a performance boost it would be better to set-up Coherence as write-behind. This means the application no longer uses the Hibernate API’s, but will typically use the Coherence API’s. In this case Hibernate will be used as a CacheStore implementation for Coherence, we typically have the following application characteristics:

  • Use Coherence APIs for the data access management.
  • Have simple object models appropriate for the CacheStore class.
  • Have simple transactional requirements.
  • Require a very high performance, which can be achieved by the use of the Coherence APIs, such as write behind.

Examples of the write-behind set-up can be found in the posts:

References

[1] Hibernate Reference Documentation.
[2] Hibernate JavaDocs.