Search This Blog

Showing posts with label spring data. Show all posts
Showing posts with label spring data. Show all posts

Wednesday, 2 October 2013

Spring Data GemFire GemfireTemplate

As with many other high-level abstractions provided by the Spring projects, Spring Data GemFire provides a template that simplifies GemFire data access. The class provides several one-line methods, for common region operations but also the ability to execute code against the native GemFire API without having to deal with GemFire checked exceptions for example through the GemfireCallback. The template class requires a GemFire Region instance and once configured is thread-safe and should be reused across multiple classes:

Example:

In this example we are using and existing GemFire cluster which has DEPT / EMP objects already existing in the distributed system as shown below.
  
gfsh>query --query="select * from /departments";

Result     : true
startCount : 0
endCount   : 20
Rows       : 4

deptno | name
------ | ----------
40     | OPERATIONS
30     | SALES
10     | ACCOUNTING
20     | RESEARCH

NEXT_STEP_NAME : END

gfsh>query --query="select * from /employees";

Result     : true
startCount : 0
endCount   : 20
Rows       : 13

empno | deptno |   name   | job
----- | ------ | -------- | ---------
7380  | 40     | BLACK    | CLERK
7373  | 40     | SIENA    | CLERK
7377  | 20     | ADAM     | CLERK
7370  | 10     | APPLES   | MANAGER
7381  | 40     | BROWN    | SALESMAN
7379  | 10     | FRANK    | CLERK
7375  | 30     | ROB      | CLERK
7371  | 10     | APICELLA | SALESMAN
7374  | 10     | LUCAS    | SALESMAN
7378  | 20     | SALLY    | MANAGER
7372  | 30     | LUCIA    | PRESIDENT
7376  | 20     | ADRIAN   | CLERK
7369  | 20     | SMITH    | CLERK

NEXT_STEP_NAME : END 

1. client.xml (GemFire Client cache XML file)
  
<!DOCTYPE client-cache PUBLIC 
"-//GemStone Systems, Inc.//GemFire Declarative Caching 7//EN" 
"http://www.gemstone.com/dtd/cache7_0.dtd">
<client-cache> 
  
    <pdx>
  <pdx-serializer>
    <class-name>com.gemstone.gemfire.pdx.ReflectionBasedAutoSerializer</class-name>
    <parameter name="classes">
      <string>pivotal\.au\.se\.deptemp\.beans\..*</string>
    </parameter>
  </pdx-serializer>
    </pdx>
  
 <!-- No cache storage in the client region because of the PROXY client region shortcut setting. -->

    <region name="departments">
      <region-attributes refid="PROXY" pool-name="gfPool" />
    </region>   
  
    <region name="employees">
  <region-attributes refid="PROXY" pool-name="gfPool" />
    </region>
</client-cache>

2. application-context.xml
  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:gfe-data="http://www.springframework.org/schema/data/gemfire"
 xmlns:gfe="http://www.springframework.org/schema/gemfire"
 xmlns:util="http://www.springframework.org/schema/util"
 xsi:schemaLocation="http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire-1.3.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
  http://www.springframework.org/schema/data/gemfire http://www.springframework.org/schema/data/gemfire/spring-data-gemfire-1.3.xsd">

 <gfe:client-cache 
     id="client-cache" 
     cache-xml-location="classpath:client.xml" 
     pool-name="gfPool"
     properties-ref="props" />
 
 <gfe:pool id="gfPool" max-connections="10">
  <gfe:locator host="localhost" port="10334"/>
 </gfe:pool>
 
 <gfe:lookup-region id="departments" name="departments" cache-ref="client-cache"/>
    <gfe:lookup-region id="employees" name="employees" cache-ref="client-cache"/>
     
    <gfe-data:repositories base-package="pivotal.au.se.deptemp.repos"  />
    
    <util:properties id="props" location="classpath:gemfire.properties"/>
    
</beans> 
Here we simply import the client.xml file and then define the regions we wish to access from GemFire.

3. TestGemFireTemplate.java
  
package pivotal.au.se.deptemp.test;

import java.util.Collection;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.gemfire.GemfireTemplate;

import pivotal.au.se.deptemp.beans.Employee;

import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.query.SelectResults;

public class TestGemFireTemplate 
{

 private ConfigurableApplicationContext ctx = null;
 
 public TestGemFireTemplate() 
 {
  ctx = new ClassPathXmlApplicationContext("application-context.xml");
 }

 public void run ()
 {
  @SuppressWarnings("unchecked")
  GemfireTemplate empTemplate = new GemfireTemplate((Region) ctx.getBean("employees"));
  
  System.out.println("-> template.query() test \n ");
  
  SelectResults<?> results = empTemplate.query("deptno = 40");
  Collection<Employee> emps = (Collection<Employee>) results.asList();
  
  for (Employee e: emps)
  {
   System.out.println(e.toString());
  }
  
  System.out.println("\n-> template.get(key) test \n ");
  
  Employee emp = empTemplate.get("7373");
  
  System.out.println(emp.toString());
  
  System.out.println("\n-> template.find() test \n ");
  
  SelectResults<Employee> clerkEmpResults = 
    empTemplate.find("SELECT * from /employees WHERE job=$1", "CLERK");
  
  Collection<Employee> clerkEmps = (Collection<Employee>) clerkEmpResults.asList();
  
  for (Employee e: clerkEmps)
  {
   System.out.println(e.toString());
  }
  
 }
 
 public static void main(String[] args) 
 {
  // TODO Auto-generated method stub
  TestGemFireTemplate test = new TestGemFireTemplate();
  System.out.println("\nStarting Spring Data GemFire Template Test.... \n");
  test.run();
  System.out.println("\nAll done.... ");
  
 }
}

Output as shown below.

Starting Spring Data GemFire Template Test.... 

-> template.query() test 

Employee [empno=7380, name=BLACK, job=CLERK, deptno=40]
Employee [empno=7381, name=BROWN, job=SALESMAN, deptno=40]
Employee [empno=7373, name=SIENA, job=CLERK, deptno=40]

-> template.get(key) test 

Employee [empno=7373, name=SIENA, job=CLERK, deptno=40]

-> template.find() test 

Employee [empno=7369, name=SMITH, job=CLERK, deptno=20]
Employee [empno=7375, name=ROB, job=CLERK, deptno=30]
Employee [empno=7376, name=ADRIAN, job=CLERK, deptno=20]
Employee [empno=7380, name=BLACK, job=CLERK, deptno=40]
Employee [empno=7377, name=ADAM, job=CLERK, deptno=20]
Employee [empno=7379, name=FRANK, job=CLERK, deptno=10]
Employee [empno=7373, name=SIENA, job=CLERK, deptno=40]

All done.... 



Wednesday, 19 December 2012

Spring Data JPA Repository with vFabric SQLFire

Spring JPA is part of the umbrella Spring Data project that makes it easy to easily implement JPA based repositories. In this example below we use Hibernate 4.1 as the JPA implementation along with with our Spring Data JPA repository to get up and running as quickly as possible. Finally in this example we use the SQLFire Hibernate Dialect given we are connecting to a SQLFire distributed database system. More info on the SQLFire Hibernate Dialect can be found here.

The project I have created in STS is as follows.


In no particular order lets show how we defined this project. Like most other blog entries this is based on the classic DEPT/EMP RDBMS tables. Before we start the maven STS project has the following defined. This will ensure you can use this code without compilation errors as all libraries required are defined with maven dependencies.

pom.xml
  
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>spring-hibernate-jpa-sqlfire</groupId>
  <artifactId>spring-hibernate-jpa-sqlfire</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>spring-hibernate-jpa-sqlfire</name>
   <properties>
       <spring.version>3.1.2.RELEASE</spring.version>
   </properties>
  <dependencies>
   <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.1.6.Final</version>
   </dependency>
   <dependency>
    <groupId>org.hibernate.javax.persistence</groupId>
    <artifactId>hibernate-jpa-2.0-api</artifactId>
    <version>1.0.0.Final</version>
   </dependency>   
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
   </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
   </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>${spring.version}</version>
   </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${spring.version}</version>
   </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
   </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${spring.version}</version>
   </dependency>
   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jpa</artifactId>
    <version>2.0.8</version>
   </dependency>
   <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.8.2</version>
   </dependency>
     <dependency>
     <groupId>org.springframework.data</groupId>
     <artifactId>spring-data-jpa</artifactId>
     <version>1.2.0.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>com.vmware</groupId>
      <artifactId>sqlf-client</artifactId>
      <version>1.0.3</version>
      <scope>system</scope>
      <systemPath>/Users/papicella/sqlfire/vFabric_SQLFire_103/lib/sqlfireclient.jar</systemPath>
    </dependency>
    <dependency>
      <groupId>com.vmware</groupId>
      <artifactId>sqlf-dialect</artifactId>
      <version>1.0.3</version>
      <scope>system</scope>
      <systemPath>/Users/papicella/sqlfire/vFabric_SQLFire_103/lib/sqlfHibernateDialect.jar</systemPath>
    </dependency>
  </dependencies>   
    
</project>
1. Create a persistence.xml file in META-INF as shown below.

persistence.xml
  
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
             version="1.0">

 <persistence-unit name="application" transaction-type="RESOURCE_LOCAL">
     <mapping-file>META-INF/persistence-query.xml</mapping-file>
        <class>pas.au.spring.hibernate.sqlfire.model.Dept</class>
        <class>pas.au.spring.hibernate.sqlfire.model.Emp</class>
  <exclude-unlisted-classes>true</exclude-unlisted-classes>
 </persistence-unit>

</persistence> 

2. Optionally created named queries in it's own XML. I prefer to do this then add annotations as this gives you the ability to tweak the queries without altering the code.

persistence-query.xml
  
<?xml version="1.0" encoding="UTF-8" ?>
 
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
        version="1.0">

    <named-query name="Dept.findByDeptnoNamedQuery">
        <query>
            from Dept
            where deptno = ?1
        </query>
    </named-query>
        
</entity-mappings>

3. Create the Dept and Emp domain model classes as shown below. These are referenced in persistence.xml above.

Dept.java
  
package pas.au.spring.hibernate.sqlfire.model;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

@Entity
public class Dept 
{
 @Id
 @GeneratedValue (strategy=GenerationType.IDENTITY)
 @Column(name="deptno")
 private Long deptno;
 
 @Column(length = 20, unique = true)
 private String dname;
 
 private String loc;

    @OneToMany(mappedBy = "dept", fetch = FetchType.EAGER)
    private List<Emp> empList;

 public Dept()
 { 
 }
 
 public Dept(Long deptno, String dname, String loc) 
 {
  super();
  this.deptno = deptno;
  this.dname = dname;
  this.loc = loc;
 }

 public Long getDeptno() {
  return deptno;
 }

 public void setDeptno(Long deptno) {
  this.deptno = deptno;
 }

 public String getDname() {
  return dname;
 }

 public void setDname(String dname) {
  this.dname = dname;
 }

 public String getLoc() {
  return loc;
 }

 public void setLoc(String loc) {
  this.loc = loc;
 }

 
    public List<Emp> getEmpList() {
  return empList;
 }

 public void setEmpList(List<Emp> empList) {
  this.empList = empList;
 }

 public Emp addEmp(Emp emp) {
        getEmpList().add(emp);
        emp.setDept(this);
        return emp;
    }

    public Emp removeEmp(Emp emp) {
        getEmpList().remove(emp);
        emp.setDept(null);
        return emp;
    }

 @Override
 public String toString() {
  return "Dept [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc
    + "]";
 }
 
} 
Emp.java
  
package pas.au.spring.hibernate.sqlfire.model;

import java.sql.Timestamp;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class Emp 
{
 @Id
 @GeneratedValue (strategy=GenerationType.IDENTITY)
 @Column(name="empno")
 private Long empno;
 
 @Column(length = 20)
 private String ename;

 private Timestamp hiredate;
    private String job;
    private Long mgr;
    private Double sal;
    @ManyToOne
    @JoinColumn(name = "DEPTNO")
    private Dept dept;
    
    public Emp()
    {
    }

 public Emp(Long empno, String ename, String job, Long mgr, Double sal, Timestamp hiredate, Dept dept) {
  super();
  this.empno = empno;
  this.ename = ename;
  this.job = job;
  this.mgr = mgr;
  this.sal = sal;
  this.hiredate = hiredate;
  this.dept = dept;
 }

 public Long getEmpno() {
  return empno;
 }

 public void setEmpno(Long empno) {
  this.empno = empno;
 }

 public String getEname() {
  return ename;
 }

 public void setEname(String ename) {
  this.ename = ename;
 }

 public String getJob() {
  return job;
 }

 public void setJob(String job) {
  this.job = job;
 }

 public Long getMgr() {
  return mgr;
 }

 public void setMgr(Long mgr) {
  this.mgr = mgr;
 }

 public Double getSal() {
  return sal;
 }

 public void setSal(Double sal) {
  this.sal = sal;
 }

 public Dept getDept() {
  return dept;
 }

 public void setDept(Dept dept) {
  this.dept = dept;
 }

 public Timestamp getHiredate() {
  return hiredate;
 }

 public void setHiredate(Timestamp hiredate) {
  this.hiredate = hiredate;
 }

 @Override
 public String toString() {
  return "Emp [empno=" + empno + ", ename=" + ename + ", hiredate="
    + hiredate + ", job=" + job + ", mgr=" + mgr + ", sal=" + sal
    + ", dept=" + dept + "]";
 }
 
} 
4. Create a spring XML file in the META-INF/spring directory named "applicationContext-persistence.xml"

applicationContext-persistence.xml
  
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:repository="http://www.springframework.org/schema/data/repository"
 xmlns:jpa="http://www.springframework.org/schema/data/jpa"
 xsi:schemaLocation="http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository-1.4.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.2.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
 
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </property>
        <property name="persistenceUnitName" value="application" />
        <property name="persistenceUnitManager">
            <bean class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager" />
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">com.vmware.sqlfire.hibernate.SQLFireDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
    <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.connection.driver_class">com.vmware.sqlfire.jdbc.ClientDriver</prop>
                <prop key="hibernate.connection.url">jdbc:sqlfire://localhost:1527</prop>
                <prop key="hibernate.connection.username">APP</prop>
                <prop key="hibernate.connection.password">APP</prop>
            </props>
        </property>
        <property name="packagesToScan" value="pas.au.spring.hibernate.sqlfire.repository" />
    </bean>
 
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
 
    <tx:annotation-driven/>

 
 <!-- CRUD JPA Repositories Here loaded by default  -->
 <jpa:repositories base-package="pas.au.spring.hibernate.sqlfire.repository" />
 
</beans>

5. Create a JPA CRUD repository as shown below. This will automatically be picked up by spring JPA repository component scanner as defined in "applicationContext-persistence.xml" above.

JPADeptRepository.java
  
package pas.au.spring.hibernate.sqlfire.repository;

import java.util.List;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;

import pas.au.spring.hibernate.sqlfire.model.Dept;

/*
 * Define a repository with all CRUD methods written for you
 */
public interface JPADeptRepository extends CrudRepository<Dept, Long>
{
 /*
  * Method which will invoke the JPQL required for a find by the attribute name
  */
 public Dept findByDeptno (Long deptno);
 
 /* 
  * Shows how to access  a named query using a method name to identify it
  * The method name must match the defined query name
  * 
  */
 public Dept findByDeptnoNamedQuery (Long deptno);

 /*
  * Method that allows us to supply a JPQL query to execute for the method
  */
 @Query("SELECT d FROM Dept d WHERE d.dname LIKE '%'")
    public List<Dept> findDeptsWithCustomJPQLQuery();

 /*
  * Method that allows us to supply a JPQL query to execute for the method with a parameter
  */
 @Query("SELECT d FROM Dept d WHERE d.loc = ?1")
    public Dept findDeptWithCustomJPQLQueryWithParam(String loc);
 
 @Query("SELECT d FROM Dept d WHERE d.deptno = ?1")
 public Dept findEmpsInDeptno (Long deptno);
 
 @Query(value = "SELECT * FROM DEPT where deptno = ?1", nativeQuery = true)
 public Dept findDeptByNativeQuery(Long deptno);
 
 @Query(value = "SELECT d, e FROM Dept d, Emp e where e.dept = d and d.deptno = ?1")
 public List<Object[]> findWithJoin(Long deptno);

} 

6. Finally create a test class to verify the repository. It's assumed you have SQLFire running and the DEPT/EMP table already exist. You can use this previous blog entry to get that setup.

http://theblasfrompas.blogspot.com.au/2011/12/sqlfire-in-few-minutes.html

JPAReposDeptTest.java
  
package pas.au.spring.hibernate.sqlfire.test.repository;

import static org.junit.Assert.*;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import pas.au.spring.hibernate.sqlfire.repository.JPADeptRepository;
import pas.au.spring.hibernate.sqlfire.model.Dept;
import pas.au.spring.hibernate.sqlfire.model.Emp;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:META-INF/spring/applicationContext-persistence.xml")
public class JPAReposDeptTest 
{
 @Autowired
 JPADeptRepository deptRespository;
 
 @Test
 public void invokeFindAll() 
 {
  List<Dept> deps = (List<Dept>) deptRespository.findAll();
  
  System.out.println("deps size = " + deps.size());
  assertNotNull(deps);
 }

 @Test
 public void invokeFindOne() 
 {
  Dept dept = deptRespository.findOne(new Long(20));
  
  System.out.println(dept);
  assertNotNull(dept);
  assertEquals(new Long(20), dept.getDeptno());
 }
 
 @Test
 public void invokeFindByDeptno() 
 {
  Dept dept = deptRespository.findByDeptno(new Long(10));
  
  System.out.println(dept);
  assertNotNull(dept);
  assertEquals(new Long(10), dept.getDeptno());
 }

 @Test
 public void invokeNamedQuery() 
 {
  Dept dept = deptRespository.findByDeptnoNamedQuery(new Long(30));
  
  System.out.println(dept);
  assertNotNull(dept);
  assertEquals(new Long(30), dept.getDeptno());
 }

 @Test
 public void invokefindDeptsWithCustomJPQLQuery() 
 {
  List<Dept> deps = (List<Dept>) deptRespository.findDeptsWithCustomJPQLQuery();
  
  System.out.println("deps size = " + deps.size());
  assertNotNull(deps);
 }

 @Test
 public void invokefindDeptsWithCustomJPQLQueryWithParam() 
 {
  Dept dept = deptRespository.findDeptWithCustomJPQLQueryWithParam("CHICAGO");
  
  System.out.println(dept);
  assertNotNull(dept);
  assertEquals(new Long(30), dept.getDeptno());
 }

 @Test
 public void invokefindEmpInDeptno() 
 {
  Dept dept = deptRespository.findEmpsInDeptno(new Long(20));
  
  System.out.println(dept);
  assertNotNull(dept);
  
  List<Emp> emps = dept.getEmpList();
  for (Emp e: emps)
  {
   System.out.println(e);
  }
  
  assertEquals(5, emps.size());
 }
 
 @Test
 public void invokeFindDeptByNativeQuery()
 {
  Dept dept = deptRespository.findDeptByNativeQuery(new Long(40));
  
  System.out.println(dept);
  assertNotNull(dept);
  assertEquals(new Long(40), dept.getDeptno());  
 }
 
 @Test
 public void invokeFindWithJoin()
 {
  List<Object[]> results = deptRespository.findWithJoin(new Long(10));
  
  System.out.println("Size of results = " + results.size());
  assertEquals(3, results.size());
  
  for (Object[] result: results)
  {
   System.out.println("Dept: " + result[0] + ", Emp: " + result[1]);
  }
  
 }
}

7. Run the test class above.

Verify output as shown below.



Dec 19, 2012 9:11:41 PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory
Dec 19, 2012 9:11:41 PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory
INFO: HHH000397: Using ASTQueryTranslatorFactory
Hibernate:
    select
        dept0_.deptno as deptno0_,
        dept0_.dname as dname0_,
        dept0_.loc as loc0_
    from
        Dept dept0_
Hibernate:
    select
        emplist0_.DEPTNO as DEPTNO0_1_,
        emplist0_.empno as empno1_,
        emplist0_.empno as empno1_0_,
        emplist0_.DEPTNO as DEPTNO1_0_,
        emplist0_.ename as ename1_0_,
        emplist0_.hiredate as hiredate1_0_,
        emplist0_.job as job1_0_,
        emplist0_.mgr as mgr1_0_,
        emplist0_.sal as sal1_0_
    from
        Emp emplist0_
    where
        emplist0_.DEPTNO=?

.......
Size of results = 3
Dept: Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK], Emp: Emp [empno=7934, ename=MILLER, hiredate=1982-01-23 00:00:00.0, job=CLERK, mgr=7782, sal=1300.0, dept=Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK]]
Dept: Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK], Emp: Emp [empno=7782, ename=CLARK, hiredate=1981-06-09 00:00:00.0, job=MANAGER, mgr=7839, sal=2450.0, dept=Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK]]
Dept: Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK], Emp: Emp [empno=7839, ename=KING, hiredate=1981-11-17 00:00:00.0, job=PRESIDENT, mgr=null, sal=5000.0, dept=Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK]]


More Information on Spring data JPA and SQLFire Hibernate Dialect can be can be found here.

Spring Data JPA
http://www.springsource.org/spring-data/jpa

vFabric SQLFire Hibernate Dialect
http://communities.vmware.com/docs/DOC-20294


Thursday, 22 November 2012

Spring data repository for GemFire 7

The example below shows the various config and code required to use Spring Data Repository with GemFire7. It is assumed we have a GemFire distributed system up and running with some department and employee data. For this example we will connect as a client proxy where all requests go to the server side for processing.

client.xml - client cache file for access to the remote servers
  
<!DOCTYPE client-cache PUBLIC 
"-//GemStone Systems, Inc.//GemFire Declarative Caching 7//EN" 
"http://www.gemstone.com/dtd/cache7_0.dtd">
<client-cache>	
	<!-- No cache storage in the client region because of the PROXY client region shortcut setting. -->

    <region name="departments">
      <region-attributes refid="PROXY" pool-name="gfPool"/>
    </region>   
		
    <region name="employees">
		<region-attributes refid="PROXY" pool-name="gfPool" />
    </region>
</client-cache>

application-context.xml - spring application context file using spring gemfire. It's here where we make a connection to GemFire through a locator to load balance between the servers.
  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:gfe="http://www.springframework.org/schema/gemfire"
	xmlns:gfe-data="http://www.springframework.org/schema/data/gemfire"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire-1.2.xsd
		http://www.springframework.org/schema/data/gemfire http://www.springframework.org/schema/data/gemfire/spring-data-gemfire-1.2.xsd">
		
	<gfe:client-cache id="client-cache" cache-xml-location="classpath:client.xml" pool-name="gfPool"/>
	
	<gfe:pool id="gfPool" max-connections="10">
		<gfe:locator host="localhost" port="10334"/>
	</gfe:pool>
	
	<gfe:lookup-region id="departments" name="departments" cache-ref="client-cache"/>
   	<gfe:lookup-region id="employees" name="employees" cache-ref="client-cache"/>

	<gfe-data:repositories base-package="vmware.au.se.gf7.deptemp.repos"  />
   
</beans>

Department.java - domain object with spring data repository annotation referencing "departments" region in gemFire
  
package vmware.au.se.gf7.deptemp.beans;

import java.io.Serializable;
import java.util.Properties;

import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.Region;

import com.gemstone.gemfire.cache.Declarable;

@Region("departments")
public class Department implements Declarable, Serializable
{

	private static final long serialVersionUID = -9097335119586059309L;

	@Id
	private int deptno;
	private String name;
	
	public void init(Properties props) 
	{
		// TODO Auto-generated method stub
		this.deptno = Integer.parseInt(props.getProperty("deptno"));
		this.name = props.getProperty("name");
	}

	public int getDeptno() {
		return deptno;
	}

	public void setDeptno(int deptno) {
		this.deptno = deptno;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Department [deptno=" + deptno + ", name=" + name + "]";
	}
  
}

Employee.java - domain object with spring data repository annotation referencing "employees" region in GemFire
  
package vmware.au.se.gf7.deptemp.beans;

import java.io.Serializable;
import java.util.Properties;

import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.Region;

import com.gemstone.gemfire.cache.Declarable;

@Region("employees")
public class Employee implements Declarable, Serializable
{

	private static final long serialVersionUID = -8229531542107983344L;
	
	@Id
	private int empno;
	private String name;
	private String job;
	private int deptno;

	public void init(Properties props) 
	{
		// TODO Auto-generated method stub
		this.empno = Integer.parseInt(props.getProperty("empno"));
		this.name = props.getProperty("name");
		this.job = props.getProperty("job");
		this.deptno = Integer.parseInt(props.getProperty("deptno"));
		
	}

	public int getEmpno() {
		return empno;
	}

	public void setEmpno(int empno) {
		this.empno = empno;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getJob() {
		return job;
	}

	public void setJob(String job) {
		this.job = job;
	}

	public int getDeptno() {
		return deptno;
	}

	public void setDeptno(int deptno) {
		this.deptno = deptno;
	}

	@Override
	public String toString() {
		return "Employee [empno=" + empno + ", name=" + name + ", job=" + job
				+ ", deptno=" + deptno + "]";
	}
	
	
	
} 

At this point we create two repositories as shown below.

DeptRepository.java
  
package vmware.au.se.gf7.deptemp.repos;

import java.util.Collection;

import org.springframework.data.gemfire.repository.Query;
import org.springframework.data.repository.CrudRepository;
import vmware.au.se.gf7.deptemp.beans.Department;

public interface DeptRepository extends CrudRepository<Department, String> 
{
	Department findByName(String name);
	
	@Query("SELECT * FROM /departments")
	Collection<Department> myFindAll();
} 

EmpRepository.java
  
package vmware.au.se.gf7.deptemp.repos;

import java.util.Collection;

import org.springframework.data.gemfire.repository.Query;
import org.springframework.data.repository.CrudRepository;

import vmware.au.se.gf7.deptemp.beans.Employee;

public interface EmpRepository extends CrudRepository<Employee, String>
{
	@Query("SELECT * FROM /employees where deptno = $1")
	Collection<Employee> empsInDeptno(int deptno);
	
	@Query("SELECT * FROM /employees")
	Collection<Employee> myFindAll();
}

Finally we have a Test client as follows.
  
package spring.gemfire.repository.test;

import java.util.Collection;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import vmware.au.se.gf7.deptemp.beans.Department;
import vmware.au.se.gf7.deptemp.beans.Employee;
import vmware.au.se.gf7.deptemp.repos.DeptRepository;
import vmware.au.se.gf7.deptemp.repos.EmpRepository;

public class Test 
{

	private ConfigurableApplicationContext ctx = null;
	
	public Test()
	{
		ctx = new ClassPathXmlApplicationContext("application-context.xml");		
	}
	
	public void run()
	{
		
		DeptRepository deptRepos = (DeptRepository) ctx.getBean(DeptRepository.class);
        
		// get quick size
		System.out.println("** Size of dept repository **");
		System.out.println("Size = " + deptRepos.count());
		
		// call findOne crud method by key
		System.out.println("** calling  deptRepos.findOne(\"20\") **");
		Department dept = (Department) deptRepos.findOne("20");
		System.out.println(dept);

		// call findOne crud method for an attribute
		System.out.println("** calling  deptRepos.findByName(\"ACCOUNTING\") **");
		Department dept2 = (Department) deptRepos.findByName("ACCOUNTING");
		System.out.println(dept2);
		
		// call my own findAll
		Collection<Department> deps = (Collection<Department>) deptRepos.myFindAll(); 
		
		System.out.println("\n** All Departments using -> deptRepos.myFindAll()");
		System.out.println("Defined as : @Query(\"SELECT * FROM /departments\") ");
		System.out.println("Collection<Department> myFindAll(); ** ");
		
		for (Department d: deps)
		{
			System.out.println(d.toString());
		}
		
		EmpRepository empRepos = (EmpRepository) ctx.getBean(EmpRepository.class);

		// get quick size
		System.out.println("** Size of emp repository **");
		System.out.println("Size = " + empRepos.count());
		
		Collection<Employee> emps = empRepos.empsInDeptno(40);
		System.out.println("\n ** All Employees in dept 40 using -> Collection<Employee> empsInDeptno(int deptno) **");
		for (Employee e: emps)
		{
			System.out.println(e.toString());
		}
		
	}
	
	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) 
	{
		// TODO Auto-generated method stub
		Test t = new Test();
		t.run();
		System.out.println("all done..");
		
	}

}


Output is as follows

[info 2012/11/22 16:39:03.626 EST tid=0xf] AutoConnectionSource discovered new locators [192-168-1-3.tpgi.com.au/192.168.1.3:10334]

[config 2012/11/22 16:39:03.628 EST tid=0x10] Updating membership port.  Port changed from 0 to 59,207.
** Size of dept repository **
Size = 4
** calling  deptRepos.findOne("20") **
Department [deptno=20, name=RESEARCH]
** calling  deptRepos.findByName("ACCOUNTING") **
Department [deptno=10, name=ACCOUNTING]

** All Departments using -> deptRepos.myFindAll()
Defined as : @Query("SELECT * FROM /departments")
Collection myFindAll(); **
Department [deptno=30, name=SALES]
Department [deptno=40, name=OPERATIONS]
Department [deptno=10, name=ACCOUNTING]
Department [deptno=20, name=RESEARCH]
** Size of emp repository **
Size = 13

 ** All Employees in dept 40 using -> Collection empsInDeptno(int deptno) **
Employee [empno=7380, name=BLACK, job=CLERK, deptno=40]
Employee [empno=7381, name=BROWN, job=SALESMAN, deptno=40]
Employee [empno=7373, name=SIENA, job=CLERK, deptno=40]
all done..


For more information see the link below.

http://static.springsource.org/spring-gemfire/docs/current/reference/html/gemfire-repositories.html