一、概述

  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. Modbus通用数据读取工具设计及使用

    一.公共功能码定义 二.能读取的数据类型 1.bit类型,比如01功能码,读到的就是位的状态,是ON 还是OFF,也就是对应着0或1. 2.byte类型,比如03功能码. 3.short类型,比如03 ...

  2. Linux系统NAT模式下设置网络网关

    1.配置Vm网络编辑器 2.配置固定IP地址 命令:vi /etc/sysconfig/network-scripts/ifcfg-ens33 #下面内容直接复制进去,如果有重复的可以去除 TYPE= ...

  3. 配置Nginx支持pathinfo模式

    Nginx服务器默认不支持pathinfo, 在需要pathinfo支持的程序中(如thinkphp),则无法支持”/index.php/Home/Index/index”这种网址.网上流传的解决办法 ...

  4. [温故]图解java多线程设计模式(一)

    去年看完的<图解java多线程设计模式>,可惜当时没做笔记,导致后来忘了许多东西,打算再温习下这本书,顺便在这里记录一下~  1.顺序执行.并行.并发 顺序执行:多个操作按照顺序依次执行. ...

  5. [Re:从零开始的分布式] 0.x——分布式锁概述

    为什么需要分布式锁 Martin Kleppmann是英国剑桥大学的分布式系统的研究员,Martin认为一般我们使用分布式锁有两个场景: 效率:使用分布式锁可以避免不同节点重复相同的工作,这些工作会浪 ...

  6. dede修改文章页命名规则

    一.DEDEcms  修改默认文章命名规则 1.单独添加分类默认修改,修改文件:include/common.inc.php. 大概在251行文档的命名规则 $cfg_df_namerule = '{ ...

  7. 剑指offer——面试题26:判断二叉树B是否为二叉树A的子结构

    #include"iostream" #include"stdio.h" #include"math.h" using namespace ...

  8. 033-JsonUtils 工具类模板

    模板一:使用的是jackson package cn.e3mall.common.utils; import java.util.List; import com.fasterxml.jackson. ...

  9. Struts dispatchAction

    在Struts中定义动态Action,不用定义多个Action,可以实现一个action,多个跳转. 在定义时,继承DispatchAction,并定义parameter的名字 在jsp页面选择act ...

  10. CNN-利用1*1进行降维和升维

    降维: 比如某次卷积之后的结果是W*H*6的特征,现在需要用1*1的卷积核将其降维成W*H*5,即6个通道变成5个通道: 通过一次卷积操作,W*H*6将变为W*H*1,这样的话,使用5个1*1的卷积核 ...