Friday, 6 September 2013

Hibernate Madness

Hibernate is db agnostic(=db generalised) Java ORM invented by Gavin King being frustrated working with EJB 2 style entity beans and brittle handwritten persistence layers. (Interview with Gavin King, founder of Hibernate, 2009)


automatic dirty checking
a feature of hibernate that saves time and effort to update the database when states of objects are modified inside a transaction.
All persistent objects are monitored by hibernate. It detects which objects have been modified and then calls update statements on all updated objects.

Example at Automatic Dirty Checking

[1] hql join @CollectionTable

For an @Entity Service having a property tags (as a @CollectionTable), 

@Entity
public class Service extends AbstractEntity<Long> {
            private static final long serialVersionUID = 9116959642944725990L;

        @ElementCollection(fetch = FetchType.EAGER, targetClass = java.lang.String.class)
        @CollectionTable(name = "service_tags", joinColumns = @JoinColumn(name = "s_id"))
        @Column(name = "tag")
        private Set<String> tags;
    }

To get Services with tags.tag="Telecome", 

select s from Service s INNER JOIN s.tags t where s.status=0 and and VALUE(s.tags) in ('Telecome'))


[2] hibernate spring query_cache

STEP 1 ADD EhCache 3.3.1 dependency as a cache provider
Add repository to artifactory.






Then add dependency to build.gradle as below : 
description 'eccount-core'


configurations {
all*.exclude module: 'commons-logging'
all*.exclude module: 'log4j'
all*.exclude module: 'icu4j'
all*.exclude module: 'catalina'

}
dependencies {

       compile 'org.hibernate:hibernate-ehcache:3.3.1.GA'
}



STEP 2 ADD hibernate query caching conf to resources/hibernate.cfg.xml


<?xml version='1.0' encoding='utf-8'?>
<!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="hibernate.default_batch_fetch_size">16</property>
        <property name="hibernate.max_fetch_depth">5</property>

        <property name="hibernate.cache.use_query_cache">true</property>
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="hibernate.generate_statistics">true</property>
        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> 
<property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property>
        <property name="hibernate.c3p0.timeout">300</property>

    </session-factory>
</hibernate-configuration>

STEP 3 ADD resources/ehcache.xml


<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

<diskStore path="/home/prayag/cache_"/>
<defaultCache
        eternal="false"
        maxElementsInMemory="1000"
        overflowToDisk="true"
        diskPersistent="true"
        timeToLiveSeconds="300"
        />
</ehcache>



STEP 4 ADD Spring's CacheManager conf to WEB-INF/jpa-context.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:cache="http://www.springframework.org/schema/cache" 
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache.xsd"
default-autowire="byName">

<!-- Scans within the base package of the application for @Components to 
configure as beans -->

<bean id="entityManagerFactory"
class="com.zazzercode.server.jpa.monitor.JavamelodyContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="${db.showSql}" />
<property name="generateDdl" value="${db.generateDdl}"/>
<property name="databasePlatform" value="${db.dialect}" />
</bean>
</property>
<property name="persistenceUnitName" value="${db.persistenceUnit}"/>
</bean>

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${db.driver}"/>
<property name="jdbcUrl" value="${db.url}"/>
<property name="user" value="${db.username}"/>
<property name="password" value="${db.password}"/>
<property name="minPoolSize" value="${db.poolsize.min}"/>
<property name="maxPoolSize" value="${db.poolsize.max}"/>
<property name="maxStatementsPerConnection" value="15"/>
<property name="idleConnectionTestPeriod" value="3000"/>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>

<tx:annotation-driven />
<cache:annotation-driven />

<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

     <!-- generic cache manager -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
 <property name="caches">
    <set>
     <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="merchantServices"/>
   </set>
      </property>
</bean>

</beans>


STEP 5 ADD Spring's @Cacheable to the Springdata Repository method 


@Cacheable("merchantServices")
@Query("select s from Service s JOIN s.statusList sas where s.status=?1 and s.priviligedUser.priviligedUserType IN (2,4) and s.id IN (?2) and sas.active=true and sas.transactorType=?3 ORDER BY s.name")
List<Service> getAllMerchantServicesByStatusAndServiceId(ServiceStatus status, List<Long> services, TransactorType transactor);


STEP 6 Check diskStore
Cache elements are stored with a key.
In diskStore, I see following files

prayag@prayag:~/cache_$ ls -l
total 0
-rw-rw-r-- 1 prayag prayag 0 Sep 20 13:31 org.hibernate.cache.StandardQueryCache.data
-rw-rw-r-- 1 prayag prayag 0 Sep 20 13:31 org.hibernate.cache.StandardQueryCache.index
-rw-rw-r-- 1 prayag prayag 0 Sep 20 13:31 org.hibernate.cache.UpdateTimestampsCache.data
-rw-rw-r-- 1 prayag prayag 0 Sep 20 13:31 org.hibernate.cache.UpdateTimestampsCache.index


Reference
Spring Data Repository caching results, http://stackoverflow.com/q/17896118/432903

How to configure Hibernate statistics in Spring 3.0 application, http://stackoverflow.com/a/6708644/432903

No comments:

Post a Comment