Hibernate Integration
GigaSpaces comes with a built in implementation of Space Persistency APIs for Hibernate. This implementation is an extension of the SpaceDataSource
and SpaceSynchronizationEndpoint
classes. The implementation allows a custom objects persistency using Hibernate mappings.
There are two available implementations.
Default Hibernate Space Persistency Implementation
DefaultHibernateSpaceDataSource
and Default
based on Hibernate Session.
Stateless Hibernate Space Persistency Implementation
StatelessHibernateSpaceDataSource
and Stateless
based on Hibernate StatelessSession. This implementation is faster than the Default Hibernate Space Where GigaSpaces data is stored. It is the logical cache that holds data objects in memory and might also hold them in layered in tiering. Data is hosted from multiple SoRs, consolidated as a unified data model. Persistency Implementation
, but it does not have first level cache, as well as does not perform any cascading operations (both in read operations as well as dirty operations).
The Hibernate Space Persistency Implementation
is used both with the Synchronous and the Asynchronous Persistency modes.
Configuration
See below example for Hibernate Space Persistency
that is configured having a Space connected to a central data source using Hibernate configuration files decorating the Space Classes:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate16.3.0.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>Person.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>
</props>
</property>
</bean>
<bean id="hibernateSpaceDataSource" class="org.openspaces.persistency.hibernate.DefaultHibernateSpaceDataSourceFactoryBean">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="initialLoadChunkSize" value="2000"/>
</bean>
<bean id="hibernateSpaceSynchronizationEndpoint" class="org.openspaces.persistency.hibernate.DefaultHibernateSpaceSynchronizationEndpointFactoryBean">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<os-core:embedded-space id="space" space-name="space" schema="persistent" space-data-source="hibernateSpaceDataSource"
space-sync-endpoint="hibernateSpaceSynchronizationEndpoint" />
<os-core:properties>
<props>
<prop key="cluster-config.cache-loader.external-data-source">true</prop>
<prop key="cluster-config.cache-loader.central-data-source">true</prop>
</props>
</os-core:properties>
</os-core:embedded-space>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate16.3.0.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>Person.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>
</props>
</property>
</bean>
<bean id="hibernateSpaceDataSource" class="org.openspaces.persistency.hibernate.DefaultHibernateSpaceDataSourceFactoryBean">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="initialLoadChunkSize" value="2000"/>
</bean>
<bean id="hibernateSpaceSynchronizationEndpoint" class="org.openspaces.persistency.hibernate.DefaultHibernateSpaceSynchronizationEndpointFactoryBean">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="space" class="org.openspaces.core.space.EmbeddedSpaceFactoryBean">
<property name="name" value="space" />
<property name="schema" value="persistent" />
<property name="spaceDataSource" ref="hibernateSpaceDataSource" />
<property name="spaceSynchronizationEndpoint" ref="hibernateSpaceSynchronizationEndpoint" />
<property name="properties">
<props>
<prop key="cluster-config.cache-loader.external-data-source">true</prop>
<prop key="cluster-config.cache-loader.central-data-source">true</prop>
</props>
</property>
</bean>
When using annotations to decorate the Space Classes the sessionFactory
would have the following:
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="annotatedClasses">
<list>
<value>com.mycompany.app.common.Data</value>
</list>
</property>
<property name="hibernateProperties">
<props>
....
</props>
</property>
</bean>
The external-data-source
element within the persistent schema allows for further configuration of the external data source. The values can be injected using the properties tag within the Space tag using the "xpath" notation.
Here is an example for a Space Domain class with its Hibernate decorations. See the @SpaceId
and the @SpaceRouting
used to include the Space Class meta Data.
Make sure your POJO Plain Old Java Object.
A regular Java object with no special restrictions other than those forced by the Java Language Specification and does not require any classpath. @SpaceId
is defined on the same property as the Hibernate @Id
. This is necessary for proper object mapping.
See the POJO Metadata for details about these decorations.
package com.mycompany.app.common;
import com.gigaspaces.annotation.pojo.SpaceClass;
import com.gigaspaces.annotation.pojo.SpaceId;
import com.gigaspaces.annotation.pojo.SpaceRouting;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Id;
@Entity
@Table(name="DATA")
@SpaceClass
public class Data {
@Id
private String id;
private Long type;
// need no arg constr
public Data() {}
@SpaceId(autoGenerate=false)
public String getId() {return id;}
public void setId(String id) {this.id = id;}
@SpaceRouting
public Long getType() {return type;}
public void setType(Long type) {this.type = type;}
...
}
}
When mapping a Collection Data types or any other variable size field make sure the relevant database table column has a sufficient size that can accommodate the largest collection/variable size field you may have within your space object.
Properties
The Hibernate Space Persistency implementation includes the following properties:
Property | Description | Default |
---|---|---|
fetchSize | Sets the fetch size that will be used when working with scrollable results. | 100 |
initialLoadChunkSize | By default, the initial load process will chunk large tables and will iterate over the table (entity) per chunk (concurrently). This setting allows to control the chunk size to split the table by. Batching can be disabled by setting -1 The initialLoadChunkSize property allows you to have multiple threads loading data from the same table into the space - each thread loading different rows from the same table. Having the initialLoadChunkSize as 100,000 will break a 1 million rows table into ten chunks. All the chunks, from all the tables, are processes by the amount of initialLoadThreadPoolSize configured. |
100,000 |
initialLoadEntries | Sets a list of entries that will be used to perform the ManagedDataSource.initialLoad() operation. |
By default, will try and build a sensible list based on Hibernate meta data. |
managedEntries | Sets all the entries this Hibernate data source will work with. By default, will use Hibernate meta data API in order to get the list of all the given entities it handles. This list is used to filter out entities when performing all data source operations except for the ManagedDataSource.initialLoad() operation. Usually, there is no need to explicitly set this. |
|
sessionFactory | Injects the Hibernate SessionFactory to be used with this data source. | |
initialLoadThreadPoolSize | The initial load operation uses the ConcurrentMultiDataIterator . This property allows to control the thread pool size of the concurrent multi data iterator.Note, this usually will map one to one to the number of open connections / cursors against the database. |
10 |
performOrderById | When performing initial load, this flag indicates if the generated query will order to results by the id. | true (as it most times results in better initial load performance). |
useScrollableResultSet | Controls if scrollable resultsets will be used with inital load operation. | true |
useMerge | If set to true, will use Hibernate merge to perform the create/update, and will merge before calling delete. This might be required for complex mappings (depends on Hibernate) at the expense of slower performance. Available only for the Default Hibernate Space Persistency Implementation |
false |
deleteById | Since 7.1. If set to true, will delete objects by their id, otherwise the object itself will be used in delete. This is necessary for objects with not-nullable fields. Available only for the Default Hibernate Space Persistency Implementation |
true |
augmentInitialLoadEntries | Since 10.0. Feature flag for intelligent partition-specific initial load of entries. Read here for more details. | true |
initialLoadQueryScanningBasePackages | Since 10.0. A list of base packages to be scanned for special initial load query methods. Read here for more details. |
Tuning the fetchSize
, initialLoadChunkSize
, initialLoadThreadPoolSize
and performOrderById
will allow you to control the initial load time. In addition, the StatelessHibernateSpaceDataSource
should give you better performance on startup.
See example below:
<bean id="hibernateSpaceDataSource" class="org.openspaces.persistency.hibernate.DefaultHibernateSpaceDataSourceFactoryBean">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="fetchSize" value="100"/>
<property name="initialLoadChunkSize" value="2000"/>
<property name="initialLoadEntries" value="MyClass1,MyClass2"/>
<property name="managedEntries" value="MyClass1,MyClass2"/>
<property name="initialLoadThreadPoolSize" value="10"/>
<property name="performOrderById" value="true"/>
<property name="useScrollableResultSet" value="true"/>
<property name="useMerge" value="true"/>
<property name="augmentInitialLoadEntries" value="true"/>
<property name="initialLoadQueryScanningBasePackages">
<list>
<value>com.example.domain</value>
</list>
</property>
</bean>