Spring Data Jpa

最近博主越来越懒了,深知这样不行。还是决定努力奋斗,如此一来,就有了一下一波复习

演示代码都基于Spring Boot + Spring Data JPA

传送门: 博主的测试代码

------------------------------------------------------------------------------------------------------------------------------

什么是Spring Data JPA?

Spring Data 是Spring提供的操作数据的框架在Spring data JPA是Spring data的一个模块,通过Spring data 基于jpa标准操作数据的模块。

Spring Data的核心能力,就是基于JPA操作数据,并且可以简化操作持久层的代码。

Spring Data JPA提供的核心接口

前提数据:

-- MySQL dump 10.13  Distrib 5.6.16, for debian-linux-gnu (x86_64)
--
-- Host: localhost Database: amber
-- ------------------------------------------------------
-- Server version 5.6.16-1~exp1 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; --
-- Table structure for table `table_user`
-- DROP TABLE IF EXISTS `table_user`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `table_user` (
`id` int(11) NOT NULL DEFAULT '',
`name` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */; --
-- Dumping data for table `table_user`
-- LOCK TABLES `table_user` WRITE;
/*!40000 ALTER TABLE `table_user` DISABLE KEYS */;
INSERT INTO `table_user` VALUES (4,'tony',NULL,'shanghai',18),(5,'amber',NULL,'shanghai',18),(2,'amber1',NULL,'shanghai',18),(3,'tony',NULL,'shanghai',18),(0,'amber1',NULL,'shanghai',18),(6,'amber',NULL,'shanghai',18);
/*!40000 ALTER TABLE `table_user` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -- Dump completed on 2019-01-13 13:43:57

SQL

package com.amber.pojo;

import lombok.Data;
import javax.persistence.*; @Entity
@Table(name = "table_user")
@Data
public class User { @Id
@GeneratedValue
private Integer id;
private String name;
private Integer age;
private String address; }

User

<?xml version="1.0" encoding="UTF-8"?>
<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>groupId</groupId>
<artifactId>SpringBoot-JPA</artifactId>
<version>1.0-SNAPSHOT</version> <properties>
<java.version>1.8</java.version>
<lombok.version>1.16.20</lombok.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/>
</parent> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

pom.xml

Repository:

@org.springframework.stereotype.Repository
public interface UserRepository extends Repository<User, Integer> {
}
  • 提供了方法名成查询方式: 

    方法的名称要遵循 findBy + 属性名(首字母大写) + 查询条件(首字母大写 Is Equals)

    findByNameLike(String name)

    findByName(String name)

    findByNameAndAge(String name, Integer age)

    findByNameOrAddress(String name) 等...

  • 基于@Query注解的查询和更新
 /**
* SQL nativeQuery的值是true 执行的时候不用再转化
* @param name
* @return
*/
@Query(value = "SELECT * FROM table_user WHERE name = ?1", nativeQuery = true)
List<User> findByUsernameSQL(String name);

  //基于HQL

    /**
* 基于HQL
* @param name
* @param id
* @return
*/
@Query("Update User set name = ?1 WHERE id = ?2")
@Modifying
int updateNameAndId(String name, Integer id);

CrudReposiroty : 继承了Repository

/*
* Copyright 2008-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.repository; import java.util.Optional; /**
* Interface for generic CRUD operations on a repository for a specific type.
*
* @author Oliver Gierke
* @author Eberhard Wolff
*/
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> { /**
* Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
* entity instance completely.
*
* @param entity must not be {@literal null}.
* @return the saved entity will never be {@literal null}.
*/
<S extends T> S save(S entity); /**
* Saves all given entities.
*
* @param entities must not be {@literal null}.
* @return the saved entities will never be {@literal null}.
* @throws IllegalArgumentException in case the given entity is {@literal null}.
*/
<S extends T> Iterable<S> saveAll(Iterable<S> entities); /**
* Retrieves an entity by its id.
*
* @param id must not be {@literal null}.
* @return the entity with the given id or {@literal Optional#empty()} if none found
* @throws IllegalArgumentException if {@code id} is {@literal null}.
*/
Optional<T> findById(ID id); /**
* Returns whether an entity with the given id exists.
*
* @param id must not be {@literal null}.
* @return {@literal true} if an entity with the given id exists, {@literal false} otherwise.
* @throws IllegalArgumentException if {@code id} is {@literal null}.
*/
boolean existsById(ID id); /**
* Returns all instances of the type.
*
* @return all entities
*/
Iterable<T> findAll(); /**
* Returns all instances of the type with the given IDs.
*
* @param ids
* @return
*/
Iterable<T> findAllById(Iterable<ID> ids); /**
* Returns the number of entities available.
*
* @return the number of entities
*/
long count(); /**
* Deletes the entity with the given id.
*
* @param id must not be {@literal null}.
* @throws IllegalArgumentException in case the given {@code id} is {@literal null}
*/
void deleteById(ID id); /**
* Deletes a given entity.
*
* @param entity
* @throws IllegalArgumentException in case the given entity is {@literal null}.
*/
void delete(T entity); /**
* Deletes the given entities.
*
* @param entities
* @throws IllegalArgumentException in case the given {@link Iterable} is {@literal null}.
*/
void deleteAll(Iterable<? extends T> entities); /**
* Deletes all entities managed by the repository.
*/
void deleteAll();
}

CrudRepository

Crud主要是添加了对数据的增删改查的方法

PagingAndSortingRepository: 继承了CrudRepository

/*
* Copyright 2008-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.repository; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort; /**
* Extension of {@link CrudRepository} to provide additional methods to retrieve entities using the pagination and
* sorting abstraction.
*
* @author Oliver Gierke
* @see Sort
* @see Pageable
* @see Page
*/
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> { /**
* Returns all entities sorted by the given options.
*
* @param sort
* @return all entities sorted by the given options
*/
Iterable<T> findAll(Sort sort); /**
* Returns a {@link Page} of entities meeting the paging restriction provided in the {@code Pageable} object.
*
* @param pageable
* @return a page of entities
*/
Page<T> findAll(Pageable pageable);
}

PagingAndSortingRepository

/**
* 继承了Repository,缺点只能对所有的数据进行排序或者分页
*/
@Repository
public interface UserPagingAndSortingReposiroty extends PagingAndSortingRepository<User, Integer> {
}
package com.amber;

import com.amber.pojo.User;
import com.amber.repository.UserPagingAndSortingReposiroty;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.junit4.SpringJUnit4ClassRunner; import java.util.List; @RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = JPAApplication.class)
public class UserPagingAndSortingReposirotyTest { @Autowired
UserPagingAndSortingReposiroty userPagingAndSortingReposiroty; /**
* 排序
*/
@Test
public void TestSort(){
//定义排序规则
Sort.Order order = new Sort.Order(Sort.Direction.DESC, "name");
Sort.Order order1 = new Sort.Order(Sort.Direction.DESC, "id");
//Sort
Sort sort = new Sort(order, order1);
List<User> users = (List<User>)userPagingAndSortingReposiroty.findAll(sort);
System.out.println(users);
} /**
* 分页Pageable封装了分页的参数,当前页,每一页显示的条数,注意当前页是从0开始的
*/
@Test
public void TestPaging(){
//Pageable是个接口
Pageable pageable = new PageRequest(0, 10);
//返回Page对象
Page<User> uses = userPagingAndSortingReposiroty.findAll(pageable);
System.out.println(uses.getTotalElements());
System.out.println(uses.getTotalPages());
System.out.println(uses.getNumberOfElements());
} /**
* 分页 + 排序
*/
@Test
public void TestPagingAndSort(){
//定义排序规则
Sort.Order order = new Sort.Order(Sort.Direction.DESC, "name");
Sort.Order order1 = new Sort.Order(Sort.Direction.DESC, "id");
//Sort
Sort sort = new Sort(order, order1);
//Pageable是个接口
Pageable pageable = new PageRequest(0, 10, sort);
//返回Page对象
Page<User> uses = userPagingAndSortingReposiroty.findAll(pageable);
System.out.println(uses.getTotalElements());
System.out.println(uses.getTotalPages());
System.out.println(uses.getNumberOfElements());
} }

UserPagingAndSortingReposirotyTest

JPARepository: 继承了PagingAndSortingRepository接口

在开发中常用JPARepository

优点: 对继承父接口中方法的返回值进行了适配,因为在父类接口中通常都返回迭代器,需要我们自己进行强制类型转化。而在JpaRepository中,直接返回了List

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package org.springframework.data.jpa.repository; import java.util.List;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor; @NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll(); List<T> findAll(Sort var1); List<T> findAllById(Iterable<ID> var1); <S extends T> List<S> saveAll(Iterable<S> var1); void flush(); <S extends T> S saveAndFlush(S var1); void deleteInBatch(Iterable<T> var1); void deleteAllInBatch(); T getOne(ID var1); <S extends T> List<S> findAll(Example<S> var1); <S extends T> List<S> findAll(Example<S> var1, Sort var2);
}

JpaRepository

JpaSpecificationExecutor: 这个接口单独存在,没有继承以上说的接口

主要提供了多条件查询的支持,并且可以在查询中添加分页和排序。

因为这个接口单独存在,因此需要配合以上说的接口使用,如:

/**
* JpaSpecificationExecutor是单独存在的,需要配合这JpaRepository一起使用
*/
@Repository
public interface UserJpaSpecificationExecutor extends JpaSpecificationExecutor<User>, JpaRepository<User, Integer> {
}

package com.amber;

import com.amber.pojo.User;
import com.amber.repository.UserJpaSpecificationExecutor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List; @RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = JPAApplication.class)
public class UserJpaSecificationExecutorTest { @Autowired
UserJpaSpecificationExecutor userJpaSpecificationExecutor; /**
* 多条件查询的另外一种写法
*/
@Test
public void testUser2(){
//Specification是个接口,封装了查询信息
Specification<User> specification = new Specification<User>() {
/**
* Predicate封装了单个查询条件
* @param root 对查询对象属性的封装,比如我们这里是查询User,因此root可以看成是User
* @param query CriteriaQuery封装了查询中的各部分信息, Select from order
* @param cb CB查询条件的构造器
* @return
*/
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate p1 = cb.equal(root.get("name"), "amber");
Predicate p2 = cb.equal(root.get("age"), "18");
return cb.and(p1,p2);
}
};
List<User> users = userJpaSpecificationExecutor.findAll(specification);
System.out.println(users);
} /**
* 多条件查询
*/
@Test
public void testUser1(){
//Specification是个接口,封装了查询信息
Specification<User> specification = new Specification<User>() {
/**
* Predicate封装了单个查询条件
* @param root 对查询对象属性的封装,比如我们这里是查询User,因此root可以看成是User
* @param query CriteriaQuery封装了查询中的各部分信息, Select from order
* @param cb CB查询条件的构造器
* @return
*/
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicates = new ArrayList<>();
Predicate p1 = cb.equal(root.get("name"), "amber");
Predicate p2 = cb.equal(root.get("age"), "18");
predicates.add(p1);
predicates.add(p2);
Predicate[] predicateArr = new Predicate[predicates.size()];
return cb.and(predicates.toArray(predicateArr));
}
};
List<User> users = userJpaSpecificationExecutor.findAll(specification);
System.out.println(users);
} /**
* 单条件查询
*/
@Test
public void testUser(){
//Specification是个接口,封装了查询信息
Specification<User> specification = new Specification<User>() {
/**
* Predicate封装了单个查询条件
* @param root 对查询对象属性的封装,比如我们这里是查询User,因此root可以看成是User
* @param query CriteriaQuery封装了查询中的各部分信息, Select from order
* @param cb CB查询条件的构造器
* @return
*/
@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) { Predicate p1 = cb.equal(root.get("name"), "amber");
return p1;
}
};
List<User> users = userJpaSpecificationExecutor.findAll(specification);
System.out.println(users);
}
}

总结:

  Spring Data Jpa中一共提供了

  • Repository:

    •   提供了findBy + 属性方法
    •   @Query 
      •   HQL: nativeQuery 默认false
      •   SQL: nativeQuery 默认true
        • 更新的时候,需要配合@Modifying使用
  • CurdRepository:
    • 继承了Repository 主要提供了对数据的增删改查
  • PagingAndSortRepository:

    • 继承了CrudRepository 提供了对数据的分页和排序,缺点是只能对所有的数据进行分页或者排序,不能做条件判断

    JpaRepository: 继承了PagingAndSortRepository

    • 开发中经常使用的接口,主要继承了PagingAndSortRepository,对返回值类型做了适配
  • JpaSpecificationExecutor
    • 提供多条件查询

Spring Data - Spring Data JPA 提供的各种Repository接口的更多相关文章

  1. Spring Data JPA 提供的各种Repository接口作用

    各种Repository接口继承关系: Repository : public interface UserRepository extends Repository<User, Integer ...

  2. 一步步学习 Spring Data 系列之JPA(一)

    引入: Spring Data是SpringSource基金会下的一个用于简化数据库访问,并支持云服务的开源框架.其主要目标是使得数据库的访问变得方便快捷,并支持map-reduce框架和云计算数据服 ...

  3. 一步步学习 Spring Data 系列之JPA(二)

    继上一篇文章对Spring Data JPA更深( )一步剖析. 上一篇只是简单的介绍了Spring Data JPA的简单使用,而往往在项目中这一点功能并不能满足我们的需求.这是当然的,在业务中查询 ...

  4. JPA && Spring Data && Spring Data JPA

    1.JPA  Java Persistence API,用于对象持久化的一组API,JPA本身是一组规范,让开发者用同一种方式访问不同的ORM框架.其实也就是java实体对象和关系型数据库建立起映射关 ...

  5. 【Spring】Spring Data JPA

    原始JDBC操作数据库 传统JDBC方式实现数据库操作 package com.imooc.util; import java.io.InputStream; import java.sql.*; i ...

  6. Spring Data JPA 梳理 - JPA与“Spring、Spring Data JPA”的关系

    JPA其实也就是java实体对象和关系型数据库建立起映射关系,通过面向对象编程的思想操作关系型数据库的规范. Spring 框架对 JPA 提供的支持主要体现在如下几个方面: 首先,它使得 JPA 配 ...

  7. java(样品集成框架spring、spring mvc、spring data jpa、hibernate)

    这是你自己的参考springside集成框架的开源项目.主要的整合spring.spring mvc.spring data jpa.hibernate几个框架,对于这些框架中仍然感觉更舒适sprin ...

  8. Spring+SpringMVC+Spring Data JPA完美整合

    使用Maven实现SSS框架的整合. 方便记录,专门建了一个pom项目用来整合SSS框架所用的jar包 1.POM项目,作为父级项目,记录整个整合中的依赖jar包pom文件 <project x ...

  9. spring mvc Spring Data Redis RedisTemplate [转]

    http://maven.springframework.org/release/org/springframework/data/spring-data-redis/(spring-data包下载) ...

随机推荐

  1. github认证登陆

    使用github OAuth实现用户登录 做登录功能时,允许使用第三方网站的身份,这称为"第三方登录". 原理 github内的认证方法 在github上申请OAuth App,进 ...

  2. setStyleSheet 设置背景图片

    设置背景颜色很简单,大部分教程都对 设置背景图像有一个小坑. 设置背景图像主要有两种情况, 第一种:图片的绝对路径 ``` this->setObjectName("mainWindo ...

  3. springboot系列之02-需要了解的宏观知识点

    未经允许,不得转载 原作者:字母哥博客 本文完整系列出自:springboot深入浅出系列 一.Spring Boot . Spring MVC .Spring对比 首先你需要明白一件事情:Sprin ...

  4. mysql查询数据库中每一张表的内存大小

    SELECT TABLE_NAME,DATA_LENGTH+INDEX_LENGTH,TABLE_ROWS,concat(round((DATA_LENGTH+INDEX_LENGTH)//,), ' ...

  5. js实现敲回车键登录

    任何一个网站页面都有登陆界面,很多时候在输入好用户名和密码后,还要用鼠标去点一个类似于登陆什么的按钮或者链接.这样你才能进网站做你喜欢做的事情. 有时候我就在想是不是能在输入好我该输入的东西后,直接敲 ...

  6. Python 模拟淘宝登录的两种方法

    方法一.urllib的post登录 import urllib import urllib2 import cookielib def taobao(username,password): cj = ...

  7. 通俗易懂spring之singleton和prototype

    关于spring bean作用域,基于不同的容器,会有所不同,如BeanFactory和ApplicationContext容器就有所不同,在本篇文章,主要讲解基于ApplicationContext ...

  8. Python 爬虫从入门到进阶之路(十)

    之前的文章我们介绍了一下 Python 中正则表达式和 re 模块来做一个案例,爬取<糗事百科>的糗事并存储到本地.本章我们来看一下另一种爬取数据的方式 XPath. 我们在前面爬取< ...

  9. python编程基础之三十三

    构造方法: 目的:构造方法用于初始化对象,可以在构造方法中添加成员属性 触发时机:实例化对象的时候自动调用 参数:第一个参数必须是self,其它参数根据需要自己定义 返回值:不返回值,或者说返回Non ...

  10. Python Flask高级编程之从0到1开发《鱼书》精品项目 ☝☝☝

    Python Flask高级编程之从0到1开发<鱼书>精品项目 ☝☝☝ 一 .安装环境我们使用 flask web框架,并用 sqlalchemy来做数据库映射,并使用 migrate做数 ...