SyntaxHighlighter

Wednesday, August 8, 2012

Spring Data JPA & Hibernate & EhCache

Spring Data JPA & Hibernate & EhCache

here's a simple setup to run an EhCache configuration on Spring Data JPA

first the maven



  4.0.0
  org.incomplete.spring
  spring-jpa-cache
  0.0.1-SNAPSHOT
  war
  spring-jpa-cache
  
  	
	  
	    org.apache.maven.plugins
	    maven-compiler-plugin
	    2.3.2
	    
	        1.6
	        1.6
	    
	    	
  	
  
  
  	
  		org.springframework.data
  		spring-data-jpa
  		1.1.0.RELEASE
  	
  	
  		org.hibernate
  		hibernate-entitymanager
  		4.1.4.Final
  	
  	
  		org.hibernate
  		hibernate-validator
  		4.3.0.Final
  	
  	
  		org.hsqldb
  		hsqldb
  		2.2.8
  		test
  	
  	
  		org.springframework
  		spring-test
  		3.1.0.RELEASE
  		test
  	
  	
  		junit
  		junit
  		4.8.2
  		test
  	
  	
  		log4j
  		log4j
  		1.2.14
  	
  	
  		org.slf4j
  		slf4j-log4j12
  		1.6.0
  	
  	
  		net.sf.ehcache
  		ehcache-core
  		2.6.0
  	
  	
  		org.hibernate
  		hibernate-ehcache
  		4.1.4.Final
  	
  


then our basic entity

package org.incompletecode.spring.domain;
 
import java.io.Serializable;
 
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
 
@Cacheable
@Entity
@Table(name="simple_entity")
public class SimpleEntity implements Serializable {
 
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
 
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Long id;
	
	@Column
	private String name;
	
	@Column
	private String description;
 
	public Long getId() {
		return id;
	}
 
	public void setId(Long id) {
		this.id = id;
	}
 
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	public String getDescription() {
		return description;
	}
 
	public void setDescription(String description) {
		this.description = description;
	}
 
	@Override
	@Transient
	public String toString() {
		return "SimpleEntity [id=" + id + ", name=" + name + ", description="
				+ description + "]";
	}
	
	
	
}

our DAO

package org.incompletecode.spring.dao;
 
import org.incompletecode.spring.domain.SimpleEntity;
import org.springframework.data.jpa.repository.JpaRepository;
 
public interface SimpleEntityDAO extends JpaRepository< SimpleEntity, Long > {
 
}

now our Spring Config for the key parts (Spring Data, JPA, Transaction Manager)



 
	
	
	
 
	
		
		
		
			
				
					
		
		
			
				org.hibernate.cache.SingletonEhCacheProvider
				/META-INF/cache/ehcache.xml
				true
				true
				org.hibernate.cache.ehcache.EhCacheRegionFactory
			
		
	
 
	
		
		
	
	


and of course our database stuff



 
	
 


the cache config




and now for a unit test

package org.incompletecode.spring.dao;
 
import static org.junit.Assert.assertNotNull;
 
import java.util.ArrayList;
import java.util.List;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hsqldb.jdbc.JDBCDataSource;
import org.incompletecode.spring.domain.SimpleEntity;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.StopWatch;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/META-INF/spring/data-context.xml",
	"classpath:/META-INF/spring/datasource-context.xml"})
public class SimpleEntityDAOTest {
 
	private static final Log logger = LogFactory.getLog(SimpleEntityDAOTest.class);
	
	public static final int count = 10000;
	
	@Autowired
	private SimpleEntityDAO simpleEntityDAO;
	
	private StopWatch stopWatch = new StopWatch();
	
	@BeforeClass
	public static void beforeClass() throws Exception {
		SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
		//build
		JDBCDataSource dataSource = new JDBCDataSource();
		dataSource.setUrl("jdbc:hsqldb:mem:a");
		//bind
		builder.bind("jdbc/datasource", dataSource);
	}
	
	@Before
	public void before() throws Exception {
		List< SimpleEntity > simpleEntities = new ArrayList< SimpleEntity >(count);
		//create a list
		stopWatch.start();
		for (int i=0; i< count; i++) {
			SimpleEntity simpleEntity = new SimpleEntity();
			simpleEntity.setName("code" + i);
			simpleEntities.add(simpleEntity);
		}//end for
		stopWatch.stop();
		logger.info("time to create: " + stopWatch.getLastTaskTimeMillis() + "ms");
		//save
		stopWatch.start();
		simpleEntityDAO.save(simpleEntities);
		stopWatch.stop();
		logger.info("time to save: " + stopWatch.getLastTaskTimeMillis() + "ms");
	}
	
	@After
	public void after() throws Exception {
		stopWatch.start();
		simpleEntityDAO.deleteAllInBatch();
		stopWatch.stop();
		logger.info("time to delete in batch: " + stopWatch.getLastTaskTimeMillis() + "ms");
	}
	
	@Test
	public void test() throws Exception {
		//create an entity
		SimpleEntity simpleEntity = new SimpleEntity();
		simpleEntity.setName("hi");
		//save
		simpleEntityDAO.save(simpleEntity);
		//check
		assertNotNull(simpleEntity.getId());
	}
	
	@Test
	public void testRetrieveAll() throws Exception {
		stopWatch.start();
		simpleEntityDAO.findAll();
		stopWatch.stop();
		logger.info("time to retrieve all: " + stopWatch.getLastTaskTimeMillis() + "ms");
	}
	
	@Test
	public void testMultipleRetrieveAll() throws Exception {
		for (int i=0;i<10;i++) {
			testRetrieveAll();
		}
	}
	
}



here's some stats on the unit test above; running it on my local machine inside STS, i can squeeze a 20% performance improvement with caching enabled.  not too shabby

4 comments:

  1. Replies
    1. sorry, what code were you looking for? the gists?

      Delete
  2. is there any chance you could post a zipped project file? I am having diabolical trouble getting this to work. I am managing cache puts but no hits...

    ReplyDelete
  3. Great for me.
    but.. how to proof that code is working with caching data?

    ReplyDelete