Agenda
What is Spring Data JPA ?
Spring Data JPA is not a JPA provider. It is a library / framework that adds an extra layer of abstraction on the top of our JPA provider. If we decide to use Spring Data JPA, the repository layer of our application contains three layers that are described in the following:
What components do we need ?
If we want to implement a persistence layer that uses Spring Data JPA, we need the following components:
build.gradle
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'org.hibernate:hibernate-entitymanager:4.1.7.Final'
compile 'mysql:mysql-connector-java:5.1.13'
compile 'org.springframework.data:spring-data-jpa:1.11.4.RELEASE'
}
Configuration
@Configuration
class PersistenceContext {
//Configure the required beans here
}
@Bean
DataSource dataSource(){
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/poc");
driverManagerDataSource.setUsername("root");
return driverManagerDataSource;
}
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource){
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean =
new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan("com.springdata.entity");
Properties jpaProperties= new Properties();
jpaProperties.setProperty("hibernate.dialect","org.hibernate.dialect.MySQLDialect");
jpaProperties.setProperty("hibernate.show_sql","true");
jpaProperties.setProperty("hibernate.hbm2ddl.auto","update");
entityManagerFactoryBean.setJpaProperties(jpaProperties);
return entityManagerFactoryBean;
}
@Bean
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
@Configuration
@EnableJpaRepositories("com.springdata.repositories")
class PersistenceContext {
//The beans are configured here
}
PersistenceContext.java
package com.springdata.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@EnableJpaRepositories("com.springdata.repositories")
public class PersistenceContext {
@Bean
DataSource dataSource(){
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/poc");
driverManagerDataSource.setUsername("root");
return driverManagerDataSource;
}
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource){
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan("com.springdata.entity");
Properties jpaProperties= new Properties();
jpaProperties.setProperty("hibernate.dialect","org.hibernate.dialect.MySQLDialect");
jpaProperties.setProperty("hibernate.show_sql","true");
jpaProperties.setProperty("hibernate.hbm2ddl.auto","update");
entityManagerFactoryBean.setJpaProperties(jpaProperties);
return entityManagerFactoryBean;
}
@Bean
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
}
Creating an entity
We have to create an entity class that contains the information of a single Employee entry.
package com.springdata.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.io.Serializable;
@Entity
public class Employee implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private Integer age;
private Integer salary;
//getters and setters
}
We are now ready to create our first Spring Data JPA repository. We can create the repository that provides CRUD operations for Todo objects by using one of the following methods:
Creating a repository (Cont.)
If we create our repository by extending the CrudRepository interface, we have to provide two type parameters:
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
}
Extending the Repository Interface
package com.springdata.repositories;
import java.util.List;
import java.util.Optional;
interface EmployeeRepository extends Repository<Employee, Integer> {
void delete(Employee deleted);
List<Employee> findAll();
Employee save(Employee persisted);
}
Query Methods
Query methods are methods that find information from the database and are declared on the repository interface.
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
List<Employee> findByName(String name);
Employee findById(Integer id);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
@Query("SELECT name from Employee where id=:id")
String findById(@Param("id") Integer id);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface EmployeeRepository extends Repository<Employee, Integer> {
@Query("SELECT id,name from Employee where id=:id")
List<Object[]> findById(@Param("id") Integer id);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;
public interface EmployeeRepository extends Repository<Employee, Integer> {
@Query("SELECT e from Employee e where id=:id")
Employee findById(@Param("id") Integer id);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;
public interface EmployeeRepository extends Repository<Employee, Integer> {
@Query("SELECT Count(*) from Employee e where name=:name")
Integer countByName(@Param("name") String name);
}
Creating Database queries from method name
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
int countById(Integer id);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
List<Employee> findFirstByName(String name);
List<Employee> findFirst3ByName(String name);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
Employee findDistinctByName(String name);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
List<Employee> findByNameOrAge(String name, Integer age);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
List<Employee> findByNameAndAge(String name, Integer age);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
List<Employee> findByAgeBetween(int min,int max);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
List<Employee> findByAgeLessThan(int age);
}
GreaterThanEquals
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
List<Employee> findByAgeGreaterThanEqual(Integer age);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
List<Employee> findByNameLike(String name);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
List<Employee> findByNameNot(String name);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
List<Employee> findByAgeIn(List<Integer> ageList);
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
List<Employee> findByNameIgnoreCase(String name);
}
If we want to create a SQL query, we must follow these steps:
package com.springdata.entity;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@NamedNativeQuery(name = "Employee.findByNameIs",
query = "SELECT * from Employee where name = :name",
resultClass = Employee.class)
public class Employee implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private Integer age;
private Integer salary;
// getters and setters
}
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
List<Employee> findByNameIs(@Param("name") String name);
}
we can sort the query results of our database queries by using the OrderBy keyword. We can use the OrderBy keyword by following these steps:
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee,Integer> {
List<Employee> findByNameOrderByIdDesc(String name);
}
We can sort our query results by following these steps:
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
List<Employee> findAll(Sort sort);
}
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(PersistenceContext.class);
EmployeeRepository employeeRepository=applicationContext.getBean(EmployeeRepository.class);
List<Employee> list = employeeRepository.findAll(new Sort(Sort.Direction.DESC,"age").and(
new Sort(Sort.Direction.ASC,"name")));
System.out.println(list);
If we want create the Pageable object manually, the service class (or other component) that wants to paginate the query results, which are returned by a Spring Data JPA repository, must create the Pageable object and pass it forward to the invoked repository method.
package com.springdata.repositories;
import com.springdata.entity.Employee;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;
public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
Page<Employee> findAll(Pageable pageable);
}
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(PersistenceContext.class);
EmployeeRepository employeeRepository=applicationContext.getBean(EmployeeRepository.class);
Page<Employee> employeePage= employeeRepository.findAll(new PageRequest(0,3,new Sort(Sort.Direction.DESC,"id")));
List<Employee> employeeList=employeePage.getContent();
System.out.println(employeeList);