Learning Summary of "Easy and Happy Play Turn Spring Data"

Posted by dsaba on Fri, 05 Jul 2019 20:41:43 +0200

Time: Monday, 24 April 2017
Note: Part of the content of this article is from Mucho.com. @ Mu Course Net: http://www.imooc.com
Teaching sample source code: https://github.com/zccodere/s...
Personal learning source code: https://github.com/zccodere/s...

Chapter 1: Course introduction

1-1 Course Introduction

What is Spring Data

Purpose: To provide a familiar and consistent data access framework based on Spring framework.
Simplify database access.
History: Proposed in 2010 by Rod Johnso, Spring Source Project
 Website: http://projects.spring.io/spring-data/#quick-start

Overview of Spring Data

Spring Data contains multiple subprojects

Spring Data JPA
Spring Data Mongo DB
Spring Data Redis
Spring Data Solr

course arrangement

Traditional access to databases
 Spring Data Quick Start
 Spring Data JPA Advancement
 Spring Data JPA Advanced

Chapter 2: Traditional access to databases

2-1 Traditional access to databases

Traditional access to databases

JDBC
Spring JdbcTemplate
 Analysis of Disadvantage

2-2 Preparations

JDBC

Connection
Statement
ResultSet
Test Case

Building Development Environment

Create a maven project
 Adding database drivers and unit test dependencies
 Preparing database tables, using mysql database

Create a Java project with POM files as follows:

<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>com.zccoder</groupId>
  <artifactId>myspringdata</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <!-- spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>4.3.6.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>4.3.6.RELEASE</version>
    </dependency>
    <!-- spring-data-jpa -->
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jpa</artifactId>
      <version>1.11.3.RELEASE</version>
    </dependency>
   <dependency>
      <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>5.2.10.Final</version>
  </dependency>
    <!-- mysql -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.38</version>
    </dependency>
    <!-- junit -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

The completed project structure chart:

2-3 JDBCUtil Development

Developing JDBCUtil Tool Class

Get Connection, close Connection, Statement, ResultSet
 Note: The configuration attributes are placed in the configuration file, and then the data in the configuration file can be loaded by code.

Code example:

package com.myimooc.springdata.jdbc.util;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * JDBC Tool class:
 * 1)Get Connection
 * 2)Releasing resources
 * Created by ZC on 2017/4/24.
 */
public class JDBCUtils {

    /**
     * Get Connection
     * @return The JDBC Connection obtained
     */
    public static Connection getConnection() throws Exception{
        /**
         * It is not recommended that you hard-code the configuration into the code.
         * Best Practices: Configuration Suggestions Written in Configuration Files
         * */
//        String url = "jdbc:mysql:///springdata";
//        String username = "root";
//        String password = "root";
//        String dirverClass = "com.mysql.jdbc.Driver";

        InputStream inputStream =  JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
        Properties properties = new Properties();
        properties.load(inputStream);

        String url = properties.getProperty("jdbc.url");
        String username = properties.getProperty("jdbc.username");
        String password = properties.getProperty("jdbc.password");
        String driverClass = properties.getProperty("jdbc.driverClass");

        Class.forName(driverClass);
        Connection connection = DriverManager.getConnection(url,username,password);
        return connection;
    }

    /**
     * Release DB-related resources
     * @param resultSet
     * @param statement
     * @param connection
     */
    public static void release(ResultSet resultSet, Statement statement,Connection connection){
        if(resultSet != null ){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement != null ){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection != null ){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

2-4 Dao Development

Establish object model and DAO layer development.

Code demonstration:

1. Object Model

package com.myimooc.springdata.jdbc.domain;

/**
 * Student Entity class
 * Created by ZC on 2017/4/24.
 */
public class Student {
    /** Primary key ID */
    private Integer id;
    /** Full name */
    private String name;
    /** Age */
    private int age;

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

2. DAO Interface

package com.myimooc.springdata.jdbc.dao;

import com.myimooc.springdata.jdbc.domain.Student;

import java.util.List;

/**
 * StudentDAO Access Interface
 * Created by ZC on 2017/4/24.
 */
public interface StudentDao {
    /**
     * Acquire all students
     * @return All students
     */
    List<Student> listStudent();

    /**
     * Add a student
     * @param student Students to be added
     */
    void saveStudent(Student student);
}

3. DAO Implementation

package com.myimooc.springdata.jdbc.dao.impl;

import com.myimooc.springdata.jdbc.dao.StudentDao;
import com.myimooc.springdata.jdbc.domain.Student;
import com.myimooc.springdata.jdbc.util.JDBCUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * StudentDAO Access Interface Implementation Class: Operated in the most primitive JDBC way
 * Created by ZC on 2017/4/24.
 */
public class StudentDaoImpl implements StudentDao {

    public List<Student> listStudent() {
        List<Student> studentList = new ArrayList<Student>();

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        String sql = "select id,name,age from student";
        try {
            connection = JDBCUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();

            while(resultSet.next()){
                Integer id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                Integer age = resultSet.getInt("age");

                Student student = new Student();
                student.setId(id);
                student.setName(name);
                student.setAge(age);

                studentList.add(student);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.release(resultSet,preparedStatement,connection);
        }
        return studentList;
    }

    public void saveStudent(Student student) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        String sql = "insert into student(name,age) values(?,?)";
        try {
            connection = JDBCUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,student.getName());
            preparedStatement.setInt(2,student.getAge());

            preparedStatement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.release(resultSet,preparedStatement,connection);
        }
    }
}

4. Unit testing

package com.myimooc.springdata.jdbc.dao;

import com.myimooc.springdata.jdbc.dao.impl.StudentDaoImpl;
import com.myimooc.springdata.jdbc.domain.Student;
import org.junit.Test;

import java.util.List;

/**
 * StudentDao Unit test class
 * Created by ZC on 2017/4/24.
 */
public class StudentDaoImplTest {

    @Test
    public void listStudentTest(){
        StudentDao studentDao = new StudentDaoImpl();

        List<Student>  studentList = studentDao.listStudent();
        for(Student student : studentList){
            System.out.println(student.toString());
        }
    }

    @Test
    public void saveStudentTest(){
        StudentDao studentDao = new StudentDaoImpl();

        Student student = new Student();
        student.setName("test");
        student.setAge(30);

        studentDao.saveStudent(student);
    }

}

2-5 uses JdbcTemplate

Spring JdbcTemplate

Adding maven dependencies
 DataSource & JdbcTemplate injection
Test Case

Code demonstration:

1. Create DB Profile

jdbc.url = jdbc:mysql:///springdata
jdbc.username = root
jdbc.password = root
jdbc.driverClass = com.mysql.jdbc.Driver

2. Create configuration file classes

package com.myimooc.springdata.jdbctemplate.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

/**
 * Configuration parameter class
 * Created by ZC on 2017/4/24.
 */
@PropertySource(value="classpath:db.properties")
@Component
public class Properties {
    @Value("${jdbc.driverClass}")
    private String jdbcDriverClass;
    @Value("${jdbc.url}")
    private String jdbcUrl;
    @Value("${jdbc.username}")
    private String jdbcUser;
    @Value("${jdbc.password}")
    private String jdbcPassword;

    @Override
    public String toString() {
        return "Properties{" +
                "jdbcDriverClass='" + jdbcDriverClass + '\'' +
                ", jdbcUrl='" + jdbcUrl + '\'' +
                ", jdbcUser='" + jdbcUser + '\'' +
                ", jdbcPassword='" + jdbcPassword + '\'' +
                '}';
    }

    public String getJdbcDriverClass() {
        return jdbcDriverClass;
    }

    public String getJdbcUrl() {
        return jdbcUrl;
    }

    public String getJdbcUser() {
        return jdbcUser;
    }

    public String getJdbcPassword() {
        return jdbcPassword;
    }
}

3. Configure DataSource, JdbcTemplate and Spring Annotation Scanning

package com.myimooc.springdata.jdbctemplate.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

/**
 * Created by ZC on 2017/4/24.
 */
@Configuration
@ComponentScan("com.myimooc.springdata.jdbctemplate")
public class SpringConfig {

    @Autowired
    private Properties properties;

    @Bean
    DriverManagerDataSource getDriverManagerDataSource(){
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
        driverManagerDataSource.setDriverClassName(properties.getJdbcDriverClass());
        driverManagerDataSource.setUrl(properties.getJdbcUrl());
        driverManagerDataSource.setUsername(properties.getJdbcUser());
        driverManagerDataSource.setPassword(properties.getJdbcPassword());
        return driverManagerDataSource;
    }

    @Bean
    JdbcTemplate getJdbcTemplate(){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(getDriverManagerDataSource());
        return jdbcTemplate;
    }
}

4. Writing Entity Classes

package com.myimooc.springdata.jdbctemplate.domain;

/**
 * Student Entity class
 * Created by ZC on 2017/4/24.
 */
public class Student {
    /** Primary key ID */
    private Integer id;
    /** Full name */
    private String name;
    /** Age */
    private int age;

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

5. DAO Interface

package com.myimooc.springdata.jdbctemplate.dao;

import com.myimooc.springdata.jdbctemplate.domain.Student;

import java.util.List;

/**
 * StudentDAO Access Interface
 * Created by ZC on 2017/4/24.
 */
public interface StudentDao {
    /**
     * Acquire all students
     * @return All students
     */
    List<Student> listStudent();

    /**
     * Add a student
     * @param student Students to be added
     */
    void saveStudent(Student student);
}

6. DAO Implementation

package com.myimooc.springdata.jdbctemplate.dao.impl;

import com.myimooc.springdata.jdbctemplate.dao.StudentDao;
import com.myimooc.springdata.jdbctemplate.domain.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * StudentDAO Access Interface Implementation Class: Operated by JdbcTemplate
 * Created by ZC on 2017/4/24.
 */
@Repository
public class StudentDaoImpl implements StudentDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public List<Student> listStudent() {
        List<Student> studentList = new ArrayList<Student>();
        String sql = "select id, name, age from student";
        List<Map<String,Object>>  mapList = jdbcTemplate.queryForList(sql);
        for (Map<String,Object> mapTemp : mapList) {
            Integer id = Integer.parseInt(mapTemp.get("id").toString());
            String name = mapTemp.get("name").toString();
            Integer age = Integer.parseInt(mapTemp.get("age").toString());

            Student student = new Student();
            student.setId(id);
            student.setName(name);
            student.setAge(age);

            studentList.add(student);
        }
        return studentList;
    }

    public void saveStudent(Student student) {
        String sql = "insert into student(name, age) value(?,?)";
        jdbcTemplate.update(sql,student.getName(),student.getAge());
    }
}

7. Unit test class

package com.myimooc.springdata.jdbctemplate;

import com.myimooc.springdata.jdbctemplate.config.SpringConfig;
import com.myimooc.springdata.jdbctemplate.dao.StudentDao;
import com.myimooc.springdata.jdbctemplate.domain.Student;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.sql.DataSource;
import java.util.List;

/**
 *  Implementing StudentDao Unit Test Class with JdbcTemplate
 * Created by ZC on 2017/4/24.
 */
public class StudentDaoTest {

    private ApplicationContext ctx = null;
    private StudentDao studentDao;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        studentDao = ctx.getBean(StudentDao.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    @Test
    public void listStudentTest(){
        List<Student> studentList = studentDao.listStudent();
        for (Student student : studentList){
            System.out.println(student.toString());
        }
    }

    @Test
    public void saveTest(){
        Student student = new Student();
        student.setName("test-spring-jdbcTemplate");
        student.setAge(25);
        studentDao.saveStudent(student);
    }

}

2-6 Disadvantage Analysis

Analysis of Disadvantage

There is too much code in DAO
 DAO implementations have a lot of duplicate code
 Paging and other functions need to be re-encapsulated

Chapter 3: Quick Start to Spring Data

3-1 Development Environment Construction

Spring Data JPA Quick Start

Construction of Development Environment
 Spring Data JPA HelloWorld Development

Code demonstration:

1. Create DB Profile

jdbc.url = jdbc:mysql:///springdata
jdbc.username = root
jdbc.password = root
jdbc.driverClass = com.mysql.jdbc.Driver

2. Create configuration file classes

package com.myimooc.springdata.jpa.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

/**
 * Created by ZC on 2017/4/24.
 */
@PropertySource(value="classpath:db.properties")
@Component
public class PropertiesConfig {
    @Value("${jdbc.driverClass}")
    private String jdbcDriverClass;
    @Value("${jdbc.url}")
    private String jdbcUrl;
    @Value("${jdbc.username}")
    private String jdbcUser;
    @Value("${jdbc.password}")
    private String jdbcPassword;

    @Override
    public String toString() {
        return "Properties{" +
                "jdbcDriverClass='" + jdbcDriverClass + '\'' +
                ", jdbcUrl='" + jdbcUrl + '\'' +
                ", jdbcUser='" + jdbcUser + '\'' +
                ", jdbcPassword='" + jdbcPassword + '\'' +
                '}';
    }

    public String getJdbcDriverClass() {
        return jdbcDriverClass;
    }

    public String getJdbcUrl() {
        return jdbcUrl;
    }

    public String getJdbcUser() {
        return jdbcUser;
    }

    public String getJdbcPassword() {
        return jdbcPassword;
    }
}

3. Configure Transaction Manager, EntityManagerFactory and Spring Auto Scan Injection

package com.myimooc.springdata.jpa.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
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.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.Properties;

/**
 * Spring Configuration class
 * Created by ZC on 2017/4/24.
 */
// Declare as configuration class
@Configuration
// Enabling transaction management
@EnableTransactionManagement
// Enable automatic scanning of classes inheriting the JpaRepository interface.
// Note that this annotation requires configuration of entity ManagerFactory and transaction Manager
// Way 1: Define the fetch Bean methods named entityManagerFactory and transactionManager
// Mode 2: Configure the entityManagerFactoryRef attribute of the @EnableJpaRepositories annotation to customize the method name of the Bean.
@EnableJpaRepositories(basePackages = "com.myimooc.springdata.jpa")
// Bean with automatic scanning @Component annotation enabled
@ComponentScan(basePackages = "com.myimooc.springdata.jpa")
public class SpringConfig{

    @Autowired
    private PropertiesConfig propertiesConfig;

    /**
     * Configuring data sources
     * @return
     */
    @Bean
    public DriverManagerDataSource dataSource(){
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
        driverManagerDataSource.setDriverClassName(propertiesConfig.getJdbcDriverClass());
        driverManagerDataSource.setUrl(propertiesConfig.getJdbcUrl());
        driverManagerDataSource.setUsername(propertiesConfig.getJdbcUser());
        driverManagerDataSource.setPassword(propertiesConfig.getJdbcPassword());
        return driverManagerDataSource;
    }


    /**
     * Configuration transaction manager JpaTransaction Manager
     * @return
     */
    @Bean(name="transactionManager")
    public PlatformTransactionManager transactionManager(){
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setDataSource(this.dataSource());
        transactionManager.setEntityManagerFactory(this.entityManagerFactory().getObject());
        return transactionManager;
//        return new DataSourceTransactionManager(this.dataSource());
//        return new JpaTransactionManager(this.entityManagerFactory().getObject());
    }

    /**
     * Configure JPA's EntityManagerFactory
     * @return
     */
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setDataSource(dataSource());

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);
        jpaVendorAdapter.setDatabase(Database.MYSQL);
        entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);

        entityManagerFactory.setPackagesToScan("com.myimooc.springdata.jpa");

        Properties jpaProperties = new Properties();
//        jpaProperties.setProperty("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy");
        jpaProperties.setProperty("hibernate.dialect","org.hibernate.dialect.MySQL5InnoDBDialect");
        jpaProperties.setProperty("hibernate.show_sql","true");
        jpaProperties.setProperty("hibernate.format_sql","true");
        jpaProperties.setProperty("hibernate.hbm2ddl.auto","update");

        entityManagerFactory.setJpaProperties(jpaProperties);

        return entityManagerFactory;
    }

}

4. Writing Entity Classes: Employee

package com.myimooc.springdata.jpa.domain;

import javax.persistence.*;

/**
 * Employee: First develop entity classes, then automatically generate entity tables
 * Created by ZC on 2017/4/24.
 */
@Entity
@Table(name = "test_employee")
public class Employee {
    @Id
    @GeneratedValue
    private Integer id;

    @Column(length = 20)
    private String name;

    private Integer age;

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

3-2 Start Program Development

Code demonstration:

1. Writing Employee Repository Interface

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.domain.Employee;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Using Repository Interface
 * Created by ZC on 2017/4/25.
 */
// Mode 2: Use the @Repository Definition annotation
//  @RepositoryDefinition(domainClass = Employee.class,idClass = Integer.class)
public interface EmployeeRepository extends Repository<Employee,Integer> {//Mode 1: Inherit Repository Interface

    /**
     * Get the employee object by name
     * @param name
     * @return
     */
    Employee findByName(String name);
}

2. Writing unit test classes: Employee Repository Test

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.domain.Employee;
import com.myimooc.springdata.jpa.repository.EmployeeRepository;
import com.myimooc.springdata.jpa.service.EmployeeService;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

import java.util.ArrayList;
import java.util.List;

/**
 * EmployeeRepository Unit test class
 * Created by ZC on 2017/4/24.
 */
public class EmployeeRepositoryTest {

    private ApplicationContext ctx = null;
    private EmployeeRepository employeeRepository = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeeRepository = ctx.getBean(EmployeeRepository.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    @Test
    public void entityManageFactoryTest(){
        LocalContainerEntityManagerFactoryBean entityManagerFactory = (LocalContainerEntityManagerFactoryBean)ctx.getBean(LocalContainerEntityManagerFactoryBean.class);
        Assert.assertNotNull(entityManagerFactory);
    }

    @Test
    public void findByNameTest(){
        System.out.println(employeeRepository);
        Employee employee = employeeRepository.findByName("cc");
        if( null == employee){
            System.out.println("Query data is empty");
        }else{
            System.out.println(employee.toString());
        }
    }
}

Repository

Repository: Spring Data Core Class
 Repository Definition: Configuration with this annotation
 Repository Query Specification: When querying, method names cannot be scribbled
 Query Annotation: With this annotation, native SQL queries can be implemented
 Update/Delete/Transaction: Update and delete operations to support transactions

Repository Hierarchy

CrudRepository: Built-in add, update, delete, query methods
PagingAndSortingRespository: Paging and sorting
JpaRepository
JpaSpecificationExcutor

Chapter 4: Spring Data JPA Advancement

4-1 About Repository Interface

Repository Interface Details

Repository The interface is Spring Data Core interface, no method
public interface Repository<T, ID extends Serializable>{}
@RepositoryDefinition Use of annotations

Definition of Repository class:

1) Repository is an empty interface, marking the interface. Interfaces that do not contain method declarations
 2) If we define the interface Employee Repository extends Repository, it will be managed by Spring.
    If our own interface does not have extends Repository, the runtime will report an error without this Bean.

4-2 Repository Subinterface Details

Repository Subinterface Details

CrudRepository: Inheriting Repository, implements CRUD-related methods
 PagingAndSorting Repository: Inheriting CrudRepository, implements paging sorting related methods
 JpaRepository: Inheriting PagingAndSorting Repositor, Implementing JPA Specification-related Approaches

4-3 Query Method Definition Rules and Use

Query Method Definition Rules and Use in Repository

Understanding the definition rules of query method names in Spring Data
 Using Spring Data to Name Complex Query Method Names

Query Method Definition Rules

Code demonstration:

1. Write the following code in the Employee Repository interface

    // Query using JPA specification

    // where name like ?% and age < ?
    List<Employee> findByNameStartingWithAndAgeLessThan(String name,Integer age);

    // where name like %? and age < ?
    List<Employee> findByNameEndingWithAndAgeLessThan(String name,Integer age);

    // where name in (?,?...) or age < ?
    List<Employee> findByNameInOrAgeLessThan(List<String> name,Integer age);

    // where name in (?,?...) and age < ?
    List<Employee> findByNameInAndAgeLessThan(List<String> name,Integer age);

2. Testing in Employee Repository Test Unit Test Class

@Test
    public void findByNameStartingWithAndAgeLessThanTest(){
        System.out.println(employeeRepository);
        List<Employee> employees = employeeRepository.findByNameStartingWithAndAgeLessThan("test",22);

        if( null != employees){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("Query data is empty");
        }
    }

    @Test
    public void findByNameEndingWithAndAgeLessThanTest(){
        System.out.println(employeeRepository);
        List<Employee> employees = employeeRepository.findByNameEndingWithAndAgeLessThan("6",23);

        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("Query data is empty");
        }
    }

    @Test
    public void findByNameInOrAgeLessThanTest(){
        List<String> names = new ArrayList<String>();
        names.add("test1");
        names.add("test2");
        names.add("test3");
        List<Employee> employees = employeeRepository.findByNameInOrAgeLessThan(names,22);

        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("Query data is empty");
        }
    }

    @Test
    public void findByNameInAndAgeLessThanTest(){
        List<String> names = new ArrayList<String>();
        names.add("test1");
        names.add("test2");
        names.add("test3");
        List<Employee> employees = employeeRepository.findByNameInAndAgeLessThan(names,22);

        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("Query data is empty");
        }
    }

There are drawbacks in using method naming rules:

1) The method name is longer: the agreement is greater than the configuration
 2) For some complex queries, it is very difficult to implement.

Use the @Query annotation to solve this problem.

4-4 Query annotation use

Query annotation use

In the Respository method, there is no need to follow the query method command rules
 Just define @Query above the methods in Respository
 Named parameters and the use of index parameters
 Local query

Code demonstration:

1. Write the following code in the Employee Repository interface

// Query with @Query annotation

    /**
     * Custom Query SQL
     * */
    @Query("select o from Employee o where id=(select max(id) from Employee t1)")
    Employee getEmployeeByMaxId();

    /**
     * Using placeholders for parameter binding
     * */
    @Query("select o from Employee o where o.name=?1 and o.age=?2")
    List<Employee> listEmployeeByNameAndAge(String name, Integer age);

    /**
     * Binding parameters with named parameters
     * */
    @Query("select o from Employee o where o.name=:name and o.age=:age")
    List<Employee> listEmployeeByNameAndAge2(@Param("name") String name, @Param("age")Integer age);

    /**
     * Custom query SQL, like, placeholder for parameter binding
     * */
    @Query("select o from Employee o where o.name like %?1%")
    List<Employee> listEmployeeByLikeName(String name);

    /**
     * Custom query SQL, like, named parameters for parameter binding
     * */
    @Query("select o from Employee o where o.name like %:name%")
    List<Employee> listEmployeeByLikeName2(@Param("name") String name);

    /**
     * Using native SQL query
     * @return
     */
    @Query(nativeQuery = true,value = "select count(1) from employee")
    long getCount();

2. Testing in Employee Repository Test Unit Test Class

//  Query with @Query annotation
    @Test
    public void getEmployeeByMaxIdTest(){

        Employee employee = employeeRepository.getEmployeeByMaxId();

        if( null != employee ){
                System.out.println(employee.toString());
        }else{
            System.out.println("Query data is empty");
        }
    }

    @Test
    public void listEmployeeByNameAndAgeTest(){
        List<Employee> employees = employeeRepository.listEmployeeByNameAndAge("zhangsan",20);
        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("Query data is empty");
        }
    }

    @Test
    public void listEmployeeByNameAndAge2Test(){
        List<Employee> employees = employeeRepository.listEmployeeByNameAndAge2("zhangsan",20);
        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("Query data is empty");
        }
    }

    @Test
    public void listEmployeeByLikeNameTest(){
        List<Employee> employees = employeeRepository.listEmployeeByLikeName("test1");
        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("Query data is empty");
        }
    }

    @Test
    public void listEmployeeByLikeName2Test(){
        List<Employee> employees = employeeRepository.listEmployeeByLikeName2("test");
        if( null != employees && employees.size() > 0){
            for (Employee employee : employees) {
                System.out.println(employee.toString());
            }
        }else{
            System.out.println("Query data is empty");
        }
    }

    @Test
    public void getCountTest(){
        long count = employeeRepository.getCount();
        System.out.println(count);
    }

4-5 Update Operations Integrate Transaction Usage

Update and Delete Operations Integrate the Use of Transactions

@ Modifying annotation use
 @ Modifying performs update operations with the @Query annotation
 @ Use of Transaction in Spring Data

The use of transactions in Spring data:

1) Transactions are generally at Service level
 2) Comprehensive use of @Query,@Modifying,@Transaction

Code demonstration:

1. Transaction configuration based on javaconfig in SpringConfig class

package com.myimooc.springdata.jpa.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
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.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.Properties;

/**
 * Spring Configuration class
 * Created by ZC on 2017/4/24.
 */
// Declare as configuration class
@Configuration
// Enabling transaction management
@EnableTransactionManagement
// Enable automatic scanning of classes inheriting the JpaRepository interface.
// Note that this annotation requires configuration of entity ManagerFactory and transaction Manager
// Way 1: Define the fetch Bean methods named entityManagerFactory and transactionManager
// Mode 2: Configure the entityManagerFactoryRef attribute of the @EnableJpaRepositories annotation to customize the method name of the Bean.
@EnableJpaRepositories(basePackages = "com.myimooc.springdata.jpa")
// Bean with automatic scanning @Component annotation enabled
@ComponentScan(basePackages = "com.myimooc.springdata.jpa")
public class SpringConfig{

    @Autowired
    private PropertiesConfig propertiesConfig;

    /**
     * Configuring data sources
     * @return
     */
    @Bean
    public DriverManagerDataSource dataSource(){
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
        driverManagerDataSource.setDriverClassName(propertiesConfig.getJdbcDriverClass());
        driverManagerDataSource.setUrl(propertiesConfig.getJdbcUrl());
        driverManagerDataSource.setUsername(propertiesConfig.getJdbcUser());
        driverManagerDataSource.setPassword(propertiesConfig.getJdbcPassword());
        return driverManagerDataSource;
    }


    /**
     * Configuration transaction manager JpaTransaction Manager
     * @return
     */
    @Bean(name="transactionManager")
    public PlatformTransactionManager transactionManager(){
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setDataSource(this.dataSource());
        transactionManager.setEntityManagerFactory(this.entityManagerFactory().getObject());
        return transactionManager;
//        return new DataSourceTransactionManager(this.dataSource());
//        return new JpaTransactionManager(this.entityManagerFactory().getObject());
    }

    /**
     * Configure JPA's EntityManagerFactory
     * @return
     */
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setDataSource(dataSource());

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);
        jpaVendorAdapter.setDatabase(Database.MYSQL);
        entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);

        entityManagerFactory.setPackagesToScan("com.myimooc.springdata.jpa");

        Properties jpaProperties = new Properties();
//        jpaProperties.setProperty("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy");
        jpaProperties.setProperty("hibernate.dialect","org.hibernate.dialect.MySQL5InnoDBDialect");
        jpaProperties.setProperty("hibernate.show_sql","true");
        jpaProperties.setProperty("hibernate.format_sql","true");
        jpaProperties.setProperty("hibernate.hbm2ddl.auto","update");

        entityManagerFactory.setJpaProperties(jpaProperties);

        return entityManagerFactory;
    }

}

2. Write the following code in the Employee Repository interface

    // Update data
    @Transactional
    @Modifying
    @Query("update Employee o set o.age = :age where o.id = :id")
    void updateAgeById(@Param("id")Integer id,@Param("age")Integer age);

3. Define Service Layer. In actual development, we need to define interfaces. In order to demonstrate conveniently, we use classes directly.

package com.myimooc.springdata.jpa.service;

import com.myimooc.springdata.jpa.domain.Employee;
import com.myimooc.springdata.jpa.repository.EmployeeCrudRepository;
import com.myimooc.springdata.jpa.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;


/**
 * Created by ZC on 2017/4/25.
 */
@Service
public class EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Autowired
    private EmployeeCrudRepository employeeCrudRepository;

    @Transactional
    public void updateAgeById(Integer id, Integer age){
        this.employeeRepository.updateAgeById(id,age);
    };

    @Transactional
    public void save(List<Employee> employees){
        this.employeeCrudRepository.save(employees);
    }
}

4. Writing EmployeeService Unit Test Class

package com.myimooc.springdata.jpa.service;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.repository.EmployeeRepository;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;

/**
 * EmployeeService Unit test class
 * Created by ZC on 2017/4/25.
 */
public class EmployeeServiceTest {

    private ApplicationContext ctx = null;
    private EmployeeService employeeService = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeeService = ctx.getBean(EmployeeService.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    @Test
    public void transactionManagerTest(){
        PlatformTransactionManager transactionManager = (PlatformTransactionManager)ctx.getBean(PlatformTransactionManager.class);
        Assert.assertNotNull(transactionManager);
    }

    // update operation

    @Test
    public void updateAgeByIdTest(){
        employeeService.updateAgeById(1,55);
    }

}

Chapter 5: Spring Data JPA Advanced

5-1 CrudRepository Interface Use Details

CrudRepository Interface Use Details

save(entity): Save an entity
 save(entities): Save multiple entities
 findOne(id): Find an object
 exists(id): Determine whether an object exists based on ID
 findAll(): Find all entity objects
 delete(id): Delete entity objects based on ID
 delete(entity): Delete entity objects based on entity objects
 delete(entities): Delete multiple entity objects
 deleteAll(): Delete all entity objects

Code demonstration:

1. Writing Employee CrudRepository Interface

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.domain.Employee;
import org.springframework.data.repository.CrudRepository;

/**
 * Using CrudRepository Interface
 * Created by ZC on 2017/4/26.
 */
public interface EmployeeCrudRepository extends CrudRepository<Employee,Integer>{

}

2. Writing the Employee CrudRepository Test Unit Test Class

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.domain.Employee;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.ArrayList;
import java.util.List;

/**
 * EmployeeRepository Unit test class
 * Created by ZC on 2017/4/24.
 */
public class EmployeeCrudRepositoryTest {

    private ApplicationContext ctx = null;
    private EmployeeCrudRepository employeeCrudRepository = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeeCrudRepository = ctx.getBean(EmployeeCrudRepository.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    @Test
    public void saveTest(){
        List<Employee> employees = new ArrayList<Employee>();
        Employee employee = null;
        for(int i=0;i<100;i++){
            employee = new Employee();
            employee.setName("test"+i);
            employee.setAge(100 - i);
            employees.add(employee);
        }
        employeeCrudRepository.save(employees);
    }

}

5-2 PagingAndSorting Respository Interface Use Details

PagingAndSorting Respository Interface Use Details

This interface includes paging and sorting functions
 Queries with sorting: findAll(Sort sort)
Paging queries with sorting: findAll(Pageable pageable)

Code demonstration:

1. Write Employee PagingAndSorting Repository Interface

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.domain.Employee;
import org.springframework.data.repository.PagingAndSortingRepository;

/**
 * Paging and sorting using PagingAndSorting Repository
 * Created by ZC on 2017/4/26.
 */
public interface EmployeePagingAndSortingRepository extends PagingAndSortingRepository<Employee,Integer> {
}

2. Write the Employee PagingAndSorting Repository Test Unit Test Class

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.domain.Employee;
import com.myimooc.springdata.jpa.repository.EmployeePagingAndSortingRepository;
import com.myimooc.springdata.jpa.service.EmployeeService;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

import java.util.ArrayList;
import java.util.List;

/**
 * PagingAndSortingRepository Unit test class
 * Created by ZC on 2017/4/26.
 */
public class EmployeePagingAndSortingRepositoryTest {

    private ApplicationContext ctx = null;
    private EmployeePagingAndSortingRepository employeePagingAndSortingRepository = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeePagingAndSortingRepository = ctx.getBean(EmployeePagingAndSortingRepository.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    /**
     * Paging Function Testing
     */
    @Test
    public void pageTest(){
        // page: index starts at 0, not from 1
        Pageable pageable = new PageRequest(0,9);
        Page<Employee> employeePage = employeePagingAndSortingRepository.findAll(pageable);

        System.out.println("Total number of pages queried:"+employeePage.getTotalPages());
        System.out.println("Total number of records queried:"+employeePage.getTotalElements());
        System.out.println("The current page of the query:"+(employeePage.getNumber() + 1));
        System.out.println("A collection of the current pages of the query:"+employeePage.getContent());
        System.out.println("Number of records on the current page of the query:"+employeePage.getNumberOfElements());

    }

    /**
     * Paging and Sorting Function Testing
     */
    @Test
    public void pageAndSort(){
        Sort.Order order = new Sort.Order(Sort.Direction.ASC,"id");
        Sort sort = new Sort(order);
        // page: index starts at 0, not from 1
        Pageable pageable = new PageRequest(0,5,sort);
        Page<Employee> employeePage = employeePagingAndSortingRepository.findAll(pageable);

        System.out.println("Total number of pages queried:"+employeePage.getTotalPages());
        System.out.println("Total number of records queried:"+employeePage.getTotalElements());
        System.out.println("The current page of the query:"+(employeePage.getNumber() + 1));
        System.out.println("A collection of the current pages of the query:"+employeePage.getContent());
        System.out.println("Number of records on the current page of the query:"+employeePage.getNumberOfElements());
    }

}

5-3 JpaRepository Interface Use Details

JpaRepository Interface Use Details

finaAll: Query all records
findAll(Sort sort): Query all records and sort them
save(entities): Save multiple entity objects
fiush: 
deleteInBatch(entities): Delete those entities in a batch

Code demonstration:

1. Writing Employee Jpa Repository Interface

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.domain.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.PagingAndSortingRepository;

/**
 * Using the JpaRepository interface
 * Created by ZC on 2017/4/26.
 */
public interface EmployeeJpaRepository extends JpaRepository<Employee,Integer> {
}

2. Writing Employee Jpa Repository Test Unit Test Class

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.domain.Employee;
import com.myimooc.springdata.jpa.repository.EmployeeJpaRepository;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.PagingAndSortingRepository;

/**
 * EmployeeJpaRepository Unit test class
 * Created by ZC on 2017/4/26.
 */
public class EmployeeJpaRepositoryTest {

    private ApplicationContext ctx = null;
    private EmployeeJpaRepository employeeJpaRepository = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeeJpaRepository = ctx.getBean(EmployeeJpaRepository.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    @Test
    public void findTest(){
        Employee employee = employeeJpaRepository.findOne(99);
        System.out.println("employee"+employee.toString());

        System.out.println("employee(10)"+employeeJpaRepository.exists(10));
        System.out.println("employee(102)"+employeeJpaRepository.exists(102));
    }

}

5-4 Jpa Specification Executor Interface Use Details

Jpa Specification Executor Interface Use Details

Specification encapsulates JPA Criteria query conditions

Code demonstration:

1. Writing Employee Jpa Specification Executor Interface

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.domain.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

/**
 * Using the JpaSpecification Executor interface
 * Created by ZC on 2017/4/26.
 */
public interface EmployeeJpaSpecificationExecutor extends JpaRepository<Employee,Integer> ,
        JpaSpecificationExecutor<Employee>{
}

2. Write the Employee Jpa Specification ExecutorTest unit test class

package com.myimooc.springdata.jpa.repository;

import com.myimooc.springdata.jpa.config.SpringConfig;
import com.myimooc.springdata.jpa.domain.Employee;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.*;

/**
 * EmployeeJpaSpecificationExecutor Unit test class
 * Created by ZC on 2017/4/26.
 */
public class EmployeeJpaSpecificationExecutorTest {

    private ApplicationContext ctx = null;
    private EmployeeJpaSpecificationExecutor employeeJpaSpecificationExecutor = null;

    @Before
    public void init(){
        ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        employeeJpaSpecificationExecutor = ctx.getBean(EmployeeJpaSpecificationExecutor.class);
    }

    @After
    public void destroy(){
        ctx = null;
    }

    /**
     * 1,paging
     * 2,sort
     * 3,Query condition: age > 50
     */
    @Test
    public void queryTest(){
        Sort.Order order = new Sort.Order(Sort.Direction.DESC,"id");
        Sort sort = new Sort(order);
        // page: index starts at 0, not from 1
        Pageable pageable = new PageRequest(0,5,sort);

        /**
         * root : That's the type we want to query (Employee)
         * query : Adding query conditions
         * cb : Building Predicate
         */
        Specification<Employee> specification = new Specification<Employee>() {
            // query criteria
            public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                // root (employee (age))
                Path path = root.get("age");
                return cb.gt(path,50);
            }
        };

        Page<Employee> employeePage = employeeJpaSpecificationExecutor.findAll(specification,pageable);

        System.out.println("Total number of pages queried:"+employeePage.getTotalPages());
        System.out.println("Total number of records queried:"+employeePage.getTotalElements());
        System.out.println("The current page of the query:"+(employeePage.getNumber() + 1));
        System.out.println("A collection of the current pages of the query:"+employeePage.getContent());
        System.out.println("Number of records on the current page of the query:"+employeePage.getNumberOfElements());

    }

}

Chapter Six: Summary of Courses

6-4 Course Summary

Course summary

Overview of Spring Data
 Traditional access to databases
 Spring Data Quick Start
 Spring Data JPA Advancement
 Spring Data JAP Advanced

Topics: Java JDBC Spring Junit