821-轻松愉快之玩转SpringData
https://www.imooc.com/learn/821
简介:在企业级JavaEE应用开发中,对数据库的访问和操作是必须的。Spring Data作为SpringSource的其中一个子项目,旨在统一和简化对各类型持久化存储和访问,而不拘泥于是关系型数据库还是NoSQL数据存储,使得对数据库的访问变得方便快捷,并支持MapReduce框架及云计算服务;对于拥有海量数据的项目,可以用Spring Data来简化项目的开发,就如Spring Framework对JDBC、ORM的支持一样,Spring Data会让数据的访问变得更加方便,极大提高开发效率、提升程序员的幸福指数!
第1章 课程介绍
课程介绍
1-1 课程介绍
什么是Spring Data
主旨:provide a familiar and consistent,Spring-based programming model for data access
提供一个熟悉的、一致的,基于Spring框架的数据访问框架。简化数据库的访问。
历史:2010年提出,作者Rod Johnso,Spring Source项目
网址:http://projects.spring.io/spring-data/#quick-start
Spring Data概览

Spring Data包含多个子项目
Spring Data JPA
减少数据访问层的开发量Spring Data Mongo DB
基于分布于存储的数据库Spring Data Redis
开源、C语言开发、支持网络内存、可持久化的Key-Value的数据库Spring Data Solr
Solr是高性能的、Java语言开发、基于Lucence的全文搜索服务器
课程安排
- 传统方式访问数据库
原生JDBC、Spring JdbcTemplate- Spring Data快速起步
- Spring Data JPA进阶
- Spring Data JPA高级
第2章 使用传统方式访问数据库
先使用传统的JDBC方法操作数据库,进而再使用Spring JdbcTemplate方式操作数据库,并对比现存操作方式的优缺点
2-1 使用传统方式访问数据库
- JDBC
- Spring JdbcTemplate
- 弊端分析
2-2 准备工作
JDBC
Connection
Statement
ResultSet
Test Case
搭建开发环境
创建maven项目
Maven工程的目录结构添加数据库驱动和单元测试依赖
<!-- 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>
数据库表的准备,使用mysql数据库
# 创建数据库 create database spring_data; # 创建数据表 create table student( id int not null auto_increment, name varchar(20)not null, age int not null, primary key(id) ); # 查看表结构 desc student; # 插入数据 insert into student(name,age)values("zhangsan", 20); insert into student(name,age)values("lisi", 21); insert into student(name,age)values("wangwu", 22); # 查询数据 select * from student;
2-3 JDBCUtil开发
开发JDBCUtil工具类:
获取Connection,关闭Connection、Statement、ResultSet
注意事项:配置的属性放置配置文件中,然后通过代码的方式将配置文件中的数据加载进来即可。
代码示例:
package com.myimooc.springdata.jdbc.util;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* JDBC工具类:
* 1)获取Connection
* 2)释放资源
*/
public class JDBCUtils {
/**
* 获取Connection
* @return 所获得到的JDBC的Connection
*/
public static Connection getConnection() throws Exception {
/**
* 不建议大家把配置硬编码到代码中
* 最佳实践:配置性的建议写到配置文件中
* */
// String url = "jdbc:mysql:///spring_data";
// 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);
return DriverManager.getConnection(url,username,password);
}
/**
* 释放DB相关资源
*/
public static void release(ResultSet resultSet, Statement statement, Connection connection) throws Exception {
if(resultSet != null ){
resultSet.close();
}
if(statement != null ){
statement.close();
}
if(connection != null ){
connection.close();
}
}
}
数据库连接配置文件:
# db.properties
jdbc.url = jdbc:mysql:///spring_data
jdbc.user = root
jdbc.password = root
jdbc.driverClass = com.mysql.jdbc.Driver
注:
- 配置的属性放在配置文件中,然后通过代码的方式将配置文件中的数据加载进来即可。
单元测试:
@Test
public void testGetConnection() throws Exception {
Connection connection = JDBCUtil.getConnection();
Assert.assertNotNull(connection);
}
2-4 Dao开发
建立对象模型及DAO层开发。
代码演示:
对象模型
package com.myimooc.springdata.jdbc.domain; /** * Student实体类 */ @Data public class Student { /** 主键ID */ private Integer id; /** 姓名 */ private String name; /** 年龄 */ private int age; }
DAO接口
package com.myimooc.springdata.jdbc.dao; import com.myimooc.springdata.jdbc.domain.Student; import java.util.List; /** * Student DAO访问接口 */ public interface StudentDao { /** * 获取所有学生 * @return 所有学生 */ List<Student> listStudent(); /** * 添加一个学生 * @param student 待添加的学生 */ void saveStudent(Student student); }
DAO实现
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; /** * Student DAO访问接口实现类:通过最原始的JDBC的方式操作 */ public class StudentDaoImpl implements StudentDao { public List<Student> listStudent() { List<Student> studentList = new ArrayList<Student>(); String sql = "select id,name,age from student"; try (Connection connection = JDBCUtils.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement(sql); ResultSet resultSet = preparedStatement.executeQuery();) { while(resultSet.next()) { Student student = new Student(); student.setId(resultSet.getInt("id")); student.setName(resultSet.getString("name")); student.setAge(resultSet.getInt("age")); studentList.add(student); } } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtils.release(resultSet, preparedStatement, connection); } return studentList; } public void saveStudent(Student student) { String sql = "insert into student(name,age) values(?, ?)"; try (Connection connection = JDBCUtils.getConnection(); PreparedStatement 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); } } }
单元测试
@Test public void listStudentTest(){ StudentDao studentDao = new StudentDaoImpl(); List<Student> studentList = studentDao.listStudent(); for(Student student : studentList){ System.out.println(student); } } @Test public void saveStudentTest(){ StudentDao studentDao = new StudentDaoImpl(); Student student = new Student("test", 30); studentDao.saveStudent(student); }
2-5 使用JdbcTemplate
Spring JdbcTemplate
添加maven依赖
<!--spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.5.RELEASE</version> </dependency>
DataSource & JdbcTemplate注入
Spring配置文件
<!-- beans.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="username" value="root"/> <property name="password" value="root"/> <property name="url" value="jdbc:mysql:///spring_data"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="studentDAO" class="com.imooc.dao.StudentDAOSpringJdbcImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"/> </bean> </beans>
Test Case
public class DataSourceTest { private ApplicationContext ctx = null; @Before public void setup(){ System.out.println("setup"); ctx = new ClassPathXmlApplicationContext("beans.xml"); } @After public void tearDown(){ System.out.println("tearDown"); ctx = null; } @Test public void testDataSource(){ System.out.println("testDataSource"); DataSource dataSource = (DataSource)ctx.getBean("dataSource"); Assert.notNull(dataSource); } @Test public void testJdbcTemplate(){ System.out.println("testJdbcTemplate"); JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getBean("jdbcTemplate"); Assert.notNull(jdbcTemplate); } }
Dao实现
package com.imooc.dao; import com.imooc.domain.Student; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowCallbackHandler; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** * StudentDAO访问接口实现类:通过Spring jdbc的方式操作 */ @Data public class StudentDAOSpringJdbcImpl implements StudentDAO { @Autowired private JdbcTemplate jdbcTemplate; @Override public List<Student> query() { final List<Student> students = new ArrayList<Student>(); String sql = "SELECT id, name, age FROM student"; jdbcTemplate.query(sql, new RowCallbackHandler() { @Override public void processRow(ResultSet rs) throws SQLException { Student student = new Student(); student.setId(rs.getInt("id")); student.setName(rs.getString("name")); student.setAge(rs.getInt("age")); students.add(student); } }); return students; } @Override public void save(Student student) { String sql = "INSERT INTO student(name, age) VALUES(?, ?)"; jdbcTemplate.update(sql, student.getName(), student.getAge()); } }
单元测试
public class StudentDAOSpringJdbcImplTest { private ApplicationContext ctx = null; private StudentDAO studentDAO = null; @Before public void setup(){ System.out.println("setup"); ctx = new ClassPathXmlApplicationContext("beans.xml"); studentDAO = (StudentDAO)ctx.getBean("studentDAO"); } @After public void tearDown(){ System.out.println("tearDown"); ctx = null; } @Test public void testQuery() { List<Student> students = studentDAO.query(); for (Student student : students) { System.out.println("student:" + student); } } @Test public void testSave() { Student student = new Student("test-spring-jdbc", 40); studentDAO.save(student); } }
END
代码演示:
创建DB配置文件
jdbc.url = jdbc:mysql:///springdata jdbc.username = root jdbc.password = root jdbc.driverClass = com.mysql.jdbc.Driver
创建配置文件类
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; /** * 配置参数类 */ @Data @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; }
配置DataSource、JdbcTemplate和Spring注解扫描
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; @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; } }
编写实体类
package com.myimooc.springdata.jdbctemplate.domain; /** * Student实体类 */ @Data public class Student { /** 主键ID */ private Integer id; /** 姓名 */ private String name; /** 年龄 */ private int age; }
DAO接口
package com.myimooc.springdata.jdbctemplate.dao; import com.myimooc.springdata.jdbctemplate.domain.Student; import java.util.List; /** * StudentDAO访问接口 */ public interface StudentDao { /** * 获取所有学生 * @return 所有学生 */ List<Student> listStudent(); /** * 添加一个学生 * @param student 待添加的学生 */ void saveStudent(Student student); }
DAO实现
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访问接口实现类:通过 JdbcTemplate 的方式操作 */ @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()); } }
单元测试类
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; /** * 使用 JdbcTemplate 实现 StudentDao 单元测试类 */ 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("test-spring-jdbcTemplate", 25); studentDao.saveStudent(student); } }
2-6 弊端分析
- DAO里面代码量太多
- DAO的实现有很多重复代码
- 开发分页和其它功能,需要重新进行封装
第3章 Spring Data快速入门
完成该框架的开发环境搭建及单元测试,本课我们将使用IDEA开发并使用Maven构建项目;
3-1 开发环境搭建
Spring Data JPA快速起步
- 开发环境搭建
- Spring Data JPA HelloWorld开发
添加maven依赖:
<!--spring data jpa--> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>1.8.0.RELEASE</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>4.3.6.Final</version> </dependency>
DataSource & JdbcTemplate注入
Spring配置文件:
<!-- beans-new.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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="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.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- Spring扫描 --> <context:component-scan base-package="com.imooc"/> </beans>
配置数据源
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="username" value="root"/> <property name="password" value="root"/> <property name="url" value="jdbc:mysql:///spring_data"/> </bean>
配置EntityManagerFactory
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> </property> <property name="packagesToScan" value="com.imooc"/> <property name="jpaProperties"> <props> <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> </bean>
配置事务管理器
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean>
配置支持注解的事务
<tx:annotation-driven transaction-manager="transactionManager"/>
配置spring data
<jpa:repositories base-package="com.imooc" entity-manager-factory-ref="entityManagerFactory"/>
创建实体类
/** * 雇员: 先开发实体类===>自动生成数据表 */ @Data @Entity public class Employee { @Id @GeneratedValue private Integer id; @Column(length = 20, nullable = false) private String name; private Integer age; }
单元测试
public class SpringDataTest { private ApplicationContext ctx = null; @Before public void setup(){ System.out.println("setup"); ctx = new ClassPathXmlApplicationContext("beans-new.xml"); } @After public void tearDown(){ System.out.println("tearDown"); ctx = null; } @Test public void testEntityManagerFactory(){ // 运行单元测试,检查是否有生成一张数据表。有则成功,无则失败。 } }
END
代码演示:
创建DB配置文件
jdbc.url = jdbc:mysql:///springdata jdbc.username = root jdbc.password = root jdbc.driverClass = com.mysql.jdbc.Driver
创建配置文件类
package com.myimooc.springdata.jpa.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component; @Data @Component @PropertySource(value="classpath:db.properties") 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; }
配置TransactionManager、EntityManagerFactory和Spring自动扫描注入
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 // 启用事务管理 @EnableTransactionManagement // 启用自动扫描继承 JpaRepository 接口的类。 // 注意,此注解需要配置 entityManagerFactory 和 transactionManager // 方式一:定义获取Bean方法名为 entityManagerFactory 和 transactionManager // 方式二:配置 @EnableJpaRepositories注解的 entityManagerFactoryRef 属性 为自定义获取Bean的方法名。 @EnableJpaRepositories(basePackages = "com.myimooc.springdata.jpa") // 启用自动扫描 @Component 注解的Bean @ComponentScan(basePackages = "com.myimooc.springdata.jpa") public class SpringConfig { @Autowired private PropertiesConfig propertiesConfig; /** * 配置数据源 * @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; } /** * 配置事务管理器 JpaTransactionManager * @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()); } /** * 配置JPA的 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; } }
编写实体类:Employee
package com.myimooc.springdata.jpa.domain; import javax.persistence.*; /** * 雇员:先开发实体类,然后自动生成实体表 */ @Data @Entity @Table(name = "test_employee") public class Employee { @Id @GeneratedValue private Integer id; @Column(length = 20) private String name; private Integer age; }
3-2 起步程序开发
编写EmployeeRepository接口
package com.myimooc.springdata.jpa.repository; import com.myimooc.springdata.jpa.domain.Employee; import org.springframework.data.repository.Repository; /** * 使用 Repository 接口 */ // 方式二:使用 @RepositoryDefinition 注解 // @RepositoryDefinition(domainClass = Employee.class,idClass = Integer.class) public interface EmployeeRepository extends Repository<Employee,Integer> { //方式一:继承 Repository 接口 /** * 获取雇员对象通过名称 */ Employee findByName(String name); }
编写单元测试类:EmployeeRepositoryTest
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单元测试类 */ 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 findByNameTest(){ // org.springframework.data.ipa.repository.support.SimpleJpaRepository@566 System.out.println(employeeRepository); Employee employee = employeeRepository.findByName("cc"); System.out.println(employee.toString()); } }
Repository
Repository:Spring Data核心类
RepositoryDefinition:使用该注解进行配置
Repository Query Specification:查询时,方法命名不能乱写
Query Annotation:使用该注解,可以实现原生SQL查询
Update/Delete/Transaction:更新、删除操作,支持事务
Repository Hierarchy:层次结构
CrudRepository:内置了新增、更新、删除、查询方法
PagingAndSortingRespository:分页和排序
JpaRepository:
JpaSpecificationExcutor
第4章 Spring Data JPA进阶
使用Spring Data JPA完成CRUD操作
4-1 关于Repository接口
Repository接口详解
Repository接口是Spring Data的核心接口,不提供任何方法
public interface Repository<T, ID extends Serializable>{}@RepositoryDefinition注解的使用
@RepositoryDefinition(domainClass = Employee.class, idClass = Integer.class)
Repository类的定义:
Repository是一个空接口,标记接口。没有包含方法声明的接口
如果我们定义的接口EmployeeRepository extends Repository,会被Spring管理。
如果我们自己的接口没有extends Repository,运行时会报错,没有这个Bean:org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.imooc.repository.EmployeeRepository' available
添加RepositoryDefinition注解能到达到不用extends Repository的功能
4-2 Repository子接口详解
Repository子接口详解
CrudRepository:继承Repository,实现了CRUD相关的方法
PagingAndSortingRepository:继承CrudRepository,实现了分页排序相关的方法
JpaRepository:继承PagingAndSortingRepositor,实现JPA规范相关的方法
4-3 查询方法定义规则和使用
Repository中查询方法定义规则和使用
了解Spring Data中查询方法名称的定义规则
使用Spring Data完成复杂查询方法名称的命名
查询方法定义规则
Keyword | Sample | JPQL snippet |
---|---|---|
And | findByLastnameAndFirstname | where x.lastname=?1 and x.firstname=?2 |
Or | findByLastnameOrFirstname | where x.lastname=?1 or x.firstname=?2 |
Between | findByStartDateBetween | where x.startDate between 1? and ?2 |
LessThan | findByAgeLessThan | where x.age<?1 |
GreaterThan | findByAgeGreaterThan | where x.age>?1 |
After | findByStartDateAfter | where x.startDate>?1 |
Before | findByStartDateBefore | where x.startDate<?1 |
IsNull | findByAgelsNull | where x.age is null |
IsNotNul, NotNull | findByAge(Is)NotNull | where x.age not null |
Like | findByFirstnameLike | where x.firstname like ?1 |
Notlike | findByFirstnameNotlike | where x. firstname not like ?1 |
StartingWith | findByFirstnameStartingWith | where x.firstname like ?1(parameter bound with appended %) |
EndingWith | findByFirstnameEndingWith | where x.firstname like ?1(parameter bound with prepended %) |
Containing | findByFirstnameContaining | where x.firstname like ?1(parameter bound wrapped in %) |
OrderBy | findByAgeOrderByLastnameDesc | where x.age=?1 order by x.lastname desc |
Not | findByLastnameNot | where x.lastname<>?1 |
In | findByAgeln(Collection |
where x.age in ?1 |
Notln | findByAgeNotin(Collection |
where x.age not in ?1 |
TRUE | findByActiveTrue | where x.active=true |
FALSE | findByActiveFalse | where x.active=false |
代码演示:
-- 测试数据
insert into employee (name, age) values ("test1",20);
insert into employee (name, age) values ("test2",21);
insert into employee (name, age) values ("test3",22);
insert into employee (name, age) values ("test4",20);
insert into employee (name, age) values ("test5",21);
insert into employee (name, age) values ("test6",22);
insert into employee (name, age) values ("test16",22);
在EmployeeRepository接口编写以下代码
// --- 使用JPA规范查询 --- // 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);
在EmployeeRepositoryTest单元测试类进行测试
@Test public void findByNameStartingWithAndAgeLessThanTest(){ List<Employee> employees = employeeRepository.findByNameStartingWithAndAgeLessThan("test",22); for (Employee employee : employees) { System.out.println(employee.toString()); } } @Test public void findByNameEndingWithAndAgeLessThanTest(){ List<Employee> employees = employeeRepository.findByNameEndingWithAndAgeLessThan("6",23); for (Employee employee : employees) { System.out.println(employee.toString()); } } @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); for (Employee employee : employees) { System.out.println(employee.toString()); } } @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); for (Employee employee : employees) { System.out.println(employee.toString()); } }
对于按照方法命名规则来使用的话,有弊端:
1)方法名比较长:约定大于配置
2)对于一些复杂的查询,是很难实现。
使用@Query注解来解决以上弊端。
4-4 Query注解使用
Query注解使用
- 在Respository方法中使用,不需要遵循查询方法命令规则
- 只需要将@Query定义在Respository中的方法之上即可
- 命名参数及索引参数的使用
- 本地查询
在EmployeeRepository接口编写以下代码
// --- 使用@Query注解查询 --- // 自定义查询SQL。Employee为类名,不是表名 @Query("select o from Employee o where id=(select max(id) from Employee t1)") Employee getEmployeeByMaxId(); // 使用占位符进行参数绑定 @Query("select o from Employee o where o.name=?1 and o.age=?2") List<Employee> listEmployeeByNameAndAge(String name, Integer age); // 使用命名参数进行参数绑定 @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); // 自定义查询SQL,like,占位符进行参数绑定 @Query("select o from Employee o where o.name like %?1%") List<Employee> listEmployeeByLikeName(String name); // 自定义查询SQL,like,命名参数进行参数绑定 @Query("select o from Employee o where o.name like %:name%") List<Employee> listEmployeeByLikeName2(@Param("name") String name); // 使用原生态SQL查询。employee为表名 @Query(nativeQuery = true,value = "select count(1) from employee") long getCount();
在EmployeeRepositoryTest单元测试类进行测试
// 使用 @Query 注解查询 @Test public void getEmployeeByMaxIdTest(){ Employee employee = employeeRepository.getEmployeeByMaxId(); System.out.println(employee); } @Test public void listEmployeeByNameAndAgeTest(){ List<Employee> employees = employeeRepository.listEmployeeByNameAndAge("zhangsan",20); for (Employee employee : employees) { System.out.println(employee); } } @Test public void listEmployeeByNameAndAge2Test(){ List<Employee> employees = employeeRepository.listEmployeeByNameAndAge2("zhangsan",20); for (Employee employee : employees) { System.out.println(employee); } } @Test public void listEmployeeByLikeNameTest(){ List<Employee> employees = employeeRepository.listEmployeeByLikeName("test1"); for (Employee employee : employees) { System.out.println(employee); } } @Test public void listEmployeeByLikeName2Test(){ List<Employee> employees = employeeRepository.listEmployeeByLikeName2("test"); for (Employee employee : employees) { System.out.println(employee); } } @Test public void getCountTest(){ long count = employeeRepository.getCount(); System.out.println(count); }
4-5 更新操作整合事务使用
更新及删除操作整合事务的使用
- @Modifying注解使用
- @Modifying结合@Query注解执行更新操作
- @Transaction在Spring Data中的使用
基于javaconfig在SpringConfig类进行事务配置
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 // 启用事务管理 @EnableTransactionManagement // 启用自动扫描继承 JpaRepository 接口的类。 // 注意,此注解需要配置 entityManagerFactory 和 transactionManager // 方式一:定义获取Bean方法名为 entityManagerFactory 和 transactionManager // 方式二:配置 @EnableJpaRepositories注解的 entityManagerFactoryRef 属性 为自定义获取Bean的方法名。 @EnableJpaRepositories(basePackages = "com.myimooc.springdata.jpa") // 启用自动扫描 @Component 注解的Bean @ComponentScan(basePackages = "com.myimooc.springdata.jpa") public class SpringConfig{ @Autowired private PropertiesConfig propertiesConfig; // 配置数据源 @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; } // 配置事务管理器 JpaTransactionManager @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()); } // 配置JPA的 EntityManagerFactory @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; } }
在EmployeeRepository接口编写以下代码
// 更新数据,需添加@Modifying、@Transactional @Modifying @Query("update Employee o set o.age = :age where o.id = :id") void updateAgeById(@Param("id")Integer id,@Param("age")Integer age);
定义Service层,实际开发中,需要定义接口,这里为了演示方便,直接使用类。
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; @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); } }
编写EmployeeService单元测试类
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单元测试类 */ 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); } // 更新操作 @Test public void updateAgeByIdTest(){ employeeService.updateAgeById(1,55); } }
事务在Spring data中的使用:
- 事务一般是在Service层
- @Query、@Modifying、@Transaction的综合使用
第5章 Spring Data JPA高级
详解Spring Data JPA的Repository核心接口的各种子类的使用
5-1 CrudRepository接口使用详解
CrudRepository接口使用详解
save(entity):保存一个实体
save(entities):保存多个实体
findOne(id):找到一个对象
exists(id):根据ID判断对象是否存在
findAll():找到所有实体对象
delete(id):根据ID删除实体对象
delete(entity):根据实体对象删除实体对象
delete(entities):删除多个实体对象
deleteAll():删除所有实体对象
编写EmployeeCrudRepository接口
package com.myimooc.springdata.jpa.repository; import com.myimooc.springdata.jpa.domain.Employee; import org.springframework.data.repository.CrudRepository; /** * 使用 CrudRepository 接口 */ public interface EmployeeCrudRepository extends CrudRepository<Employee,Integer>{ }
编写EmployeeCrudRepositoryTest单元测试类
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单元测试类 */ public class EmployeeCrudRepositoryTest { private ApplicationContext ctx = null; private EmployeeService employeeService = null; @Before public void init(){ ctx = new AnnotationConfigApplicationContext(SpringConfig.class); employeeCrudRepository = ctx.getBean(EmployeeService.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); } employeeService.save(employees); } }
5-2 PagingAndSortingRespsitory接口使用详解 (14:48)
PagingAndSortingRespository接口使用详解
- 该接口包含分页和排序的功能
- 带排序的查询:findAll(Sort sort)
- 带排序的分页查询:findAll(Pageable pageable)
编写EmployeePagingAndSortingRepository接口
package com.myimooc.springdata.jpa.repository; import com.myimooc.springdata.jpa.domain.Employee; import org.springframework.data.repository.PagingAndSortingRepository; /** * 使用 PagingAndSortingRepository 实现分页和排序功能 */ public interface EmployeePagingAndSortingRepository extends PagingAndSortingRepository<Employee,Integer> { }
编写EmployeePagingAndSortingRepositoryTest单元测试类
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 单元测试类 */ 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; } /** * 分页功能测试 */ @Test public void pageTest(){ // page: index是从0开始的,不是从1开始的 Pageable pageable = new PageRequest(0,9);// page,size Page<Employee> employeePage = employeePagingAndSortingRepository.findAll(pageable); System.out.println("查询的总页数:"+employeePage.getTotalPages()); System.out.println("查询的总记录数:"+employeePage.getTotalElements()); System.out.println("查询的当前第几页:"+(employeePage.getNumber() + 1)); System.out.println("查询的当前页面的集合:"+employeePage.getContent()); System.out.println("查询的当前页面的记录数:"+employeePage.getNumberOfElements()); } /** * 分页和排序功能测试 */ @Test public void pageAndSort(){ Sort.Order order = new Sort.Order(Sort.Direction.DESC,"id");// 升/降序,规则字段 Sort sort = new Sort(order); // page: index是从0开始的,不是从1开始的 Pageable pageable = new PageRequest(0,5,sort);// 先排序,再分页 Page<Employee> employeePage = employeePagingAndSortingRepository.findAll(pageable); System.out.println("查询的总页数:"+employeePage.getTotalPages()); System.out.println("查询的总记录数:"+employeePage.getTotalElements()); System.out.println("查询的当前第几页:"+(employeePage.getNumber() + 1)); System.out.println("查询的当前页面的集合:"+employeePage.getContent()); System.out.println("查询的当前页面的记录数:"+employeePage.getNumberOfElements()); } }
5-3 JpaRepository接口使用详解
JpaRepository接口使用详解
finaAll:查询所有记录
findAll(Sort sort):查询所有记录并排序
save(entities):保存多个实体对象
fiush:
deleteInBatch(entities):一个批次里面删除那些实体
编写EmployeeJpaRepository接口
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; /** * 使用 JpaRepository 接口 */ public interface EmployeeJpaRepository extends JpaRepository<Employee,Integer> { }
编写EmployeeJpaRepositoryTest单元测试类
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 单元测试类 */ 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); System.out.println("employee(10)" + employeeJpaRepository.exists(10));// true System.out.println("employee(102)" + employeeJpaRepository.exists(102));// false } }
5-4 JpaSpecificationExecutor接口使用详解
JpaSpecificationExecutor接口使用详解(JPA规范执行者)
Specification封装了JPA Criteria(JAP标准)查询条件
Repository接口体系无法携带一些查询条件
代码演示:
编写EmployeeJpaSpecificationExecutor接口
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; /** * 使用 JpaSpecificationExecutor 接口 */ public interface EmployeeJpaSpecificationExecutor extends JpaRepository<Employee,Integer> , JpaSpecificationExecutor<Employee>{ }
编写EmployeeJpaSpecificationExecutorTest单元测试类
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 单元测试类 */ 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、分页 * 2、排序 * 3、查询条件:age > 50 */ @Test public void queryTest(){ Sort.Order order = new Sort.Order(Sort.Direction.DESC,"id"); Sort sort = new Sort(order); // page: index是从0开始的,不是从1开始的 Pageable pageable = new PageRequest(0,5,sort); /** * root : 就是我们要查询的类型 (Employee) * query : 添加查询条件 * cb : 构建 Predicate */ Specification<Employee> specification = new Specification<Employee>() { // 查询条件 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("查询的总页数:" + employeePage.getTotalPages()); System.out.println("查询的总记录数:" + employeePage.getTotalElements()); System.out.println("查询的当前第几页:" + (employeePage.getNumber() + 1)); System.out.println("查询的当前页面的集合:" + employeePage.getContent()); System.out.println("查询的当前页面的记录数:" + employeePage.getNumberOfElements()); } }
第6章 课程总结
课程总结
6-1 课程总结
Spring Data概览
传统方式访问数据库
Spring Data快速起步
Spring Data JPA进阶
Spring Data JAP高级
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 tuyrk@qq.com
文章标题:821-轻松愉快之玩转SpringData
文章字数:8.1k
本文作者:神秘的小岛岛
发布时间:2019-06-15, 23:14:34
最后更新:2019-11-05, 19:19:31
原始链接:https://www.tuyrk.cn/imooc/821-SpringData/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。