一、概述

  JPA : Java Persistence API, Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

  Spring Data JPA 是Spring基于ORM框架、JPA规范封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用SpringDataJPA可以极大提高开发效率! 除了CRUD外,还包括如分页、排序等一些常用的功能。下面的示例代码即可完成数据保存的操作,而无需具体实现类.

public interface UserDao extends Repository<AccountInfo, Long> { 
  public AccountInfo save(AccountInfo accountInfo);
}

二、Spring Data JPA的核心接口

  • Repository:最顶层的接口,是一个空的接口,目的是为了统一所有Repository的类型,且能让组件扫描的时候自动识别。

  • CrudRepository :是Repository的子接口,提供CRUD的功能

  • PagingAndSortingRepository:是CrudRepository的子接口,添加分页和排序的功能

  • JpaRepository:是PagingAndSortingRepository的子接口,增加了一些实用的功能,比如:批量操作等。

  • JpaSpecificationExecutor:用来做负责查询的接口

  • Specification:是Spring Data JPA提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件即可

三、快速入门

1、构建demo环境

  • 使用maven建立jar项目,下图为项目文件目录

  • 导入依赖

 <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.cenobitor</groupId>
<artifactId>JPADemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<description>统一管理依赖</description> <properties>
<spring.version>4.2.4.RELEASE</spring.version>
<hibernate.version>5.0.7.Final</hibernate.version>
<slf4j.version>1.6.6</slf4j.version>
<springdatajpa.version>1.10.4.RELEASE</springdatajpa.version>
<c3p0.version>0.9.1.2</c3p0.version>
<junit.version>4.11</junit.version>
</properties> <dependencies>
<!-- spring 框架 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency> <!-- spring data jpa 数据库持久层 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${springdatajpa.version}</version>
</dependency> <!-- hibernate 框架 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency> <!-- 数据库连接池 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency> <!-- 日志框架 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency> <!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies> </project>
  • 在applicationContext.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:jdbc="http://www.springframework.org/schema/jdbc" 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/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <!--指定连接池配置-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql:///ssh01?useSSL=false" />
<property name="user" value="root" />
<property name="password" value="" />
</bean>
<!-- spring整合JPA -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--指定JPA扫描的实体类所在的包-->
<property name="packagesToScan" value="com.cenobitor.domain" />
<!-- 指定持久层提供者为Hibernate -->
<property name="persistenceProvider">
<bean class="org.hibernate.ejb.HibernatePersistence" />
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!-- 自动建表 -->
<property name="generateDdl" value="true" />
<property name="database" value="MYSQL" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
<property name="showSql" value="true" />
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</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要进行扫描的包,该包中的类框架会自动为其创建代理-->
<jpa:repositories base-package="com.cenobitor.dao" /> </beans>
  • 项目中新建com.cenobitor.domain包,创建实体类
 @Entity
@Table
public class User {
@Id
@GeneratedValue
@Column
private Integer id;
@Column
private String name;
@Column
private String password; 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 String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} @Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}
  • 项目中新建com.cenobitor.dao包,创建dao
 // 泛型参数1 : 实体类
// 泛型参数2 : 实体类中主键的类型
@Repository
public interface JpaRepository extends org.springframework.data.jpa.repository.JpaRepository<User,Integer>{ }
  • 在com.cenobitor.test创建测试类,进行测试用例,如果在控制台看到Hibernate输出sql语句,说明操作成功

 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataJPATest {
@Autowired
private JpaRepository jpaRepository; @Test
public void testQuery() {
// 查询操作
List<User> list = jpaRepository.findAll();
for (User user : list) {
System.out.println(user);
}
}
}

2、增删改查操作

 @Test
public void testSave() {
// 保存数据
User user = new User();
user.setName("赵六");
user.setPassword("1234"); jpaRepository.save(user);
} @Test
public void testUpdate() {
// 更新操作,传入主键ID
User user = new User();
user.setId(3);
user.setName("李四");
// 调用该方法时,首先进行查询操作,如果数据不存在,执行插入
// 如果数据存在,执行修改
jpaRepository.save(user);
} @Test
public void testDelete() {
//删除操作
jpaRepository.delete(3);
} @Test
public void testFindOne() {
//根据主键进行查询
User user = jpaRepository.findOne(4);
System.out.println(user);
}

3、自定义查询操作

  JpaRepository支持接口规范方法名查询。意思是如果在接口中定义的查询方法符合它的命名规则,就可以不用写实现。

  例如:findByName这个方法表示从数据库中查询Name这个属性等于XXX的所有记 录,类似于SQL语句:select*from xTablewherename=x这种形式 这段话有两个重点:

①方法名需要在接口中设定

②必须符合一定的命名规范

  • 方法名构造方法

  find+全局修饰+By+实体的属性名称+限定词+连接词+.(其它实体属性)+OrderBy+ 排序属性+排序方向
  例如:

findDistinctByFirstNameIgnoreCaseAndLastNameOrderByAgeDesc(String
firstName,StringlastName){.}

  其中:Distinct是全局修饰(非必须),FirstName和LastName是实体的属性名, And是连接词,IgnoreCase是限定词,Age是排序属性,Desc是排序方向,限定词 和连接词统称为“关键词”

  • 常用词如下:
    • 全局修饰:Distinct,Top,First
    • 关键词:IsNull,IsNotNull,Like,NotLike,Containing,In,NotIn, IgnoreCase,Between,Equals,LesThan,GreaterThan,After,Before
    • 排序方向:Asc,Desc
    • 连接词:And,Or
  • 示例
 // 泛型参数1 : 实体类
// 泛型参数2 : 实体类中主键的类型
@Repository
public interface JpaRepository extends org.springframework.data.jpa.repository.JpaRepository<User,Integer>{
// =============标准命名方式===============
// 根据名字进行精准查询,Standard类中有name字段
User findByName(String name);
// 根据名字进行模糊查询
User findByNameLike(String name);
// 查询名字为空的数据
List<User> findByNameIsNull();
// 多条件查询
User findByNameAndPassword(String name,String password);
// ==============非标准命名方式=============
// 使用JPQL进行非标准命名查询
@Query("from User u where u.name like ?")
User findByNamexxxxxLikeJPQL(String name);
// 使用JPQL进行非标准多条件查询
// 默认情况下,问号的顺序和传入的参数顺序是一致的
// 可以在问号后面追加数字,改变和参数的匹配顺序
// 下面的示例中,传入的第一个参数匹配到第二个问号,传入的第二个参数匹配到第一个问号
@Query("from User u where u.name like ?2 and password = ?1")
User findByNameAndOperatorJPQL(String password,String name);
// 使用标准SQL进行非标准命名查询
@Query(value = "select * from user u where u.name like ?", nativeQuery = true)
User findByNamexxxxxLikeSQL(String name);
}
   @Test
public void testFindByName(){
User user = jpaRepository.findByName("赵六");
System.out.println(user);
} @Test
public void testFindByNameLike(){
User user = jpaRepository.findByNameLike("%六");
System.out.println(user);
} @Test
public void testFindByNameIsNull(){
List<User> users = jpaRepository.findByNameIsNull();
System.out.println(users);
} @Test
public void testFindByNameAndPassword(){
User user = jpaRepository.findByNameAndPassword("赵六","1234");
System.out.println(user);
} @Test
public void testFindByNamexxxxxLikeJPQL(){
User user = jpaRepository.findByNamexxxxxLikeJPQL("赵六");
System.out.println(user);
} @Test
public void testFindByNameAndOperatorJPQL(){
User user = jpaRepository.findByNameAndOperatorJPQL("1234","赵六");
System.out.println(user);
} @Test
public void testFindByNamexxxxxLikeSQL(){
User user = jpaRepository.findByNamexxxxxLikeSQL("赵六");
System.out.println(user);
}

4、自定义更新删除操作

 // ================自定义增删改操作==========
@Transactional // 使用事务
@Modifying // 执行修改操作
@Query("delete from User u where u.name = ?")
void deleteByName(String name); @Transactional
@Modifying // 执行修改操作
@Query("update User u set u.password = ?2 where u.name = ?1")
void updatePasswordByName(String name, String password);
     @Test
public void testDeleteByName() {
// 使用JPQL进行自定义删除操作
jpaRepository.deleteByName("赵六");
} @Test
public void testUpdatePasswordByName() {
// 使用JPQL进行自定义更新操作
jpaRepository.updatePasswordByName("赵六","333");
}
5、分页查询与条件分页查询
  • 分页查询
     //分页查询
@Test
public void TestPageQuery() throws IOException {
int page = 1 ; //当前页面
int rows = 10 ; //每页数据条数
//创建分页条件
Pageable pageable = new PageRequest(page - 1, rows);
Page<User> page1 = jpaRepository.findAll(pageable);
//获取总数据条数
long totalElements = page1.getTotalElements();
//获取结果集
List<User> list = page1.getContent();
System.out.println(list); }
  • 条件分页查询
@Repository
public interface JpaRepository extends JpaRepository<User,Integer>,
JpaSpecificationExecutor<User> {
}
 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDataJPATest {
@Autowired
private JpaRepository jpaRepository; @Test
public void testConditionPageQuery() throws IOException { User user = new User();
user.setName("李%");
user.setPassword("1234"); int page = 1 ; //当前页面
int rows = 10 ; //每页数据条数 //构造查询条件
Specification<User> specification = new Specification<User>() {
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
/**
* 创建一个查询的where语句
* @param root : 根对象.可以简单的认为就是泛型对象
* @param cb : 构建查询条件
* @return a {@link Predicate}, must not be {@literal null}.
*/
String name = user.getName();
String password = user.getPassword();
// 存储条件的集合
ArrayList<Predicate> list = new ArrayList<>();
if (! name.isEmpty()){
//构建模糊查询条件,参数2为具体的比较的值
Predicate p1 = cb.like(root.get("name").as(String.class),name);
list.add(p1);
}
if (! password.isEmpty()){
Predicate p2 = cb.equal(root.get("password").as(String.class), password);
list.add(p2);
}
if (list.size() == 0 ){
return null;
}
Predicate[] arr = new Predicate[list.size()];
list.toArray(arr);
return cb.and(arr);
} };
Pageable pageable = new PageRequest(page-1,rows);
Page<User> page1 = jpaRepository.findAll(specification,pageable);
List<User> content = page1.getContent();
System.out.println(content);
}
}

Spring Data JPA —— 快速入门的更多相关文章

  1. Spring data JPA 快速入门

    1需求 ​ 向客户中插入一条数据 ​ 如果使用Jpa框架可以不用先建表 可以使用框架生成表 ​ 2 实现步骤 ​ a 创建工程 使用maven管理工程 <properties>       ...

  2. Spring Data Redis —— 快速入门

    环境要求:Redis 2.6及以上,javase 8.0及以上: 一.Spring Data Redis 介绍 Spring-data-redis是spring的一部分,提供了在srping应用中通过 ...

  3. Spring Data Solr —— 快速入门

    Solr是基于Lucene(全文检索引擎)开发,它是一个独立系统,运行在Tomcat或Jetty(solr6以上集成了jetty,无需再部署到servlet容器上),但其原生中文的分词词功能不行,需要 ...

  4. Spring Data JPA -1-CRUD入门

    1) 引入jar包支持 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...

  5. 整合Spring Data JPA与Spring MVC: 分页和排序

    之前我们学习了如何使用Jpa访问关系型数据库.比较完整Spring MVC和JPA教程请见Spring Data JPA实战入门,Spring MVC实战入门. 通过Jpa大大简化了我们对数据库的开发 ...

  6. 整合Spring Data JPA与Spring MVC: 分页和排序pageable

    https://www.tianmaying.com/tutorial/spring-jpa-page-sort Spring Data Jpa对于分页以及排序的查询也有着完美的支持,接下来,我们来学 ...

  7. 【Spring Data 系列学习】Spring Data JPA 自定义查询,分页,排序,条件查询

    Spring Boot Jpa 默认提供 CURD 的方法等方法,在日常中往往时无法满足我们业务的要求,本章节通过自定义简单查询案例进行讲解. 快速上手 项目中的pom.xml.application ...

  8. 【Spring Data 系列学习】了解 Spring Data JPA 、 Jpa 和 Hibernate

    在开始学习 Spring Data JPA 之前,首先讨论下 Spring Data Jpa.JPA 和 Hibernate 之前的关系. JPA JPA 是 Java Persistence API ...

  9. Spring Data Jpa 入门学习

    本文主要讲解 springData Jpa 入门相关知识, 了解JPA规范与Jpa的实现,搭建springboot+dpringdata jpa环境实现基础增删改操作,适合新手学习,老鸟绕道~ 1. ...

随机推荐

  1. windows文件名太长无法删除的解决办法

    安装nodejs 的模块hexo后,由于香重新安装,在删除的时候却提示文件名太长无法删除,dos命令.回收站各种都无法搞定,后来找到解决办法: 1.进入这些文件的所在目录的上层目录,右键这些文件的所在 ...

  2. [Objective-C语言教程]内存管理(36)

    内存管理是任何编程语言中最重要的过程之一.它是在需要时分配对象的内存并在不再需要时取消分配的过程. 管理对象内存是一个性能问题; 如果应用程序不释放不需要的对象,则应用程序会因内存占用增加并且性能受损 ...

  3. mxonline实战8,机构列表分页功能,以及按条件筛选功能

    对应github地址:列表分页和按条件筛选     一. 列表分页   1. pip install django-pure-pagination   2. settings.py中 install ...

  4. 【Quartz】解密properties配置文件中的账号密码

    在配置quartz时,为了保密某些信息(特别是账号密码),通常会使用密文.那么在实际使用这些配置信息时,需要进行解密.本文提供一种解密方法如下: (1)假设在properties文件中加密了账号密码 ...

  5. C#-WebForm JS定时器

    JS定时器: 1.window.setTimeout(function(){},3000) 延迟3秒执行 2.window.setInterval(function(){},3000) 也叫重复器,每 ...

  6. 为什么要重写hashcode方法和equals方法

    我们可能经常听到说重写equals方法必须重写hashcode方法,这是为什么呢?java中所有的类都是Object的子类,直接上object源码 /* * Copyright (c) 1994, 2 ...

  7. HttpURLConnection发送GET、POST请求

    HttpURLConnection发送GET.POST请求 /** * GET请求 * * @param requestUrl 请求地址 * @return */ public String get( ...

  8. MySQL自定义排序

    存在表A 按名字倒序排 SELECT  *  FROM  A  ORDER  BY  name  DESC 结果如下: 若需要按照王五.张三.李四的顺序排序,使用自定义排序:FIELD() SELEC ...

  9. [转] 使用HTTPS在Nexus Repository Manager 3.0上搭建私有Docker仓库

    FROM: https://www.hifreud.com/2018/06/06/03-nexus-docker-repository-with-ssl/ 搭建方式 搭建SSL的Nexus官方提供两种 ...

  10. [转] org.scalatest.FunSuite Scala Examples - Scala FunSuite 测试的例子

    [From]  https://www.programcreek.com/scala/org.scalatest.FunSuite org.scalatest.FunSuite Scala Examp ...