##1、Spring Data JPA的概述
1.1 Spring Data JPA概述

Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!
Spring Data JPA 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现,在实际的工作工程中,推荐使用Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦
1.2 Spring Data JPA的特性

SpringData Jpa 极大简化了数据库访问层代码。 如何简化的呢? 使用了SpringDataJpa,我们的dao层中只需要写接口,就自动具有了增删改查、分页查询等方法。
1.3 Spring Data JPA 与 JPA和hibernate之间的关系
JPA是一套规范,内部是有接口和抽象类组成的。hibernate是一套成熟的ORM框架,而且Hibernate实现了JPA规范,所以也可以称hibernate为JPA的一种实现方式,我们使用JPA的API编程,意味着站在更高的角度上看待问题(面向接口编程)
Spring Data JPA是Spring提供的一套对JPA操作更加高级的封装,是在JPA规范下的专门用来进行数据持久化的解决方案。
2、Spring Data JPA的快速入门
2.1需求说明
- Spring Data JPA完成客户的基本CRUD操作
2.2搭建Spring Data JPA的开发环境
2.2.1 引入Spring Data JPA的坐标
使用Spring Data JPA,需要整合Spring与Spring Data JPA,并且需要提供JPA的服务提供者hibernate,所以需要导入spring相关坐标,hibernate坐标,数据库驱动坐标等
<properties>
<spring.version>5.0.2.RELEASE</spring.version>
<hibernate.version>5.0.7.Final</hibernate.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<c3p0.version>0.9.1.2</c3p0.version>
<mysql.version>5.1.18</mysql.version>
</properties>
<dependencies>
<!-- junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- spring beg -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring整合ORM框架用的 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring end -->
<!-- hibernate beg -->
<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>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.1.Final</version>
</dependency>
<!-- hibernate end -->
<!-- c3p0 beg -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- c3p0 end -->
<!-- log end -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- Spring Data Jpa的坐标 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- el beg 使用spring data jpa 必须引入 -->
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
<!-- el end -->
</dependencies>
2.2.2 整合Spring Data JPA与Spring
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.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">
<!-- 配置spring data jpa 和 Spring -->
<!-- 1、创建数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///jpa?useUnicode=true&characterEncoding=UTF-8"/>
<property name="user" value="root"/>
<property name="password" value="passw0rd"/>
</bean>
<!-- 2、把实体类管理器工厂交给Spring管理 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!-- 数据源-->
<property name="dataSource" ref="dataSource"/>
<!-- 扫描实体类的包 -->
<property name="packagesToScan" value="com.domain"/>
<!-- 指定jpa的提供商 -->
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
</property>
<!--JPA的供应商适配器-->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--
true: HBM2DDL_AUTO为"update" ,有表就维护表,没有表就创建表
false: 默认为false
-->
<property name="generateDdl" value="false" />
<property name="database" value="MYSQL" />
<!-- 数据库方言:根据这个方言生成不同数据库的sql -->
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
<property name="showSql" value="true" />
</bean>
</property>
<!-- 可选:Jpa的方言 -->
<property name="jpaDialect" >
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
</property>
</bean>
<!-- 3、配置事务-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!-- 事务通知和aop切面这里就不配置: 今天是dao层的代码-->
<!-- 4、 配置SpringDataJpa的相关配置
base-package:指定基包
entity-manager-factory-ref: 引用实体类管理器工厂
transaction-manager-ref: 引用平台事务管理器
-->
<jpa:repositories base-package="com.dao"
entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager"/>
<!-- 5、开启组件的扫描-->
<context:component-scan base-package="com"/>
</beans>
2.2.3 使用 JPA 注解配置映射关系
import javax.persistence.*;
/**
* 客户实体类
*/
@Entity
@Table(name="cst_customer")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="cust_id")
private Long custId;
@Column(name="cust_name")
private String custName;
@Column(name="cust_source")
private String custSource;
@Column(name="cust_level")
private String custLevel;
@Column(name="cust_industry")
private String custIndustry;
@Column(name="cust_address")
private String custAddress;
@Column(name="cust_phone")
private String custPhone;
// 省略 setter and getter 及 toString 方法
}
2.3 使用 Spring Data JPA 完成需求
2.3.1 编写符合 Spring Data JPA 规范的 Dao 层接口
import com.domain.Customer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
/**
* 创建符合SpringDataJpa规范的接口: 约定优于配置
* 1、继承JpaRepository,并写上相应的泛型 : 增删改查
* *第一个泛型:我们要操作的实体类
* *第二个泛型:主键属性的数据类型
* 2、继承JpaSpecificationExecutor,并写上相应的泛型 : 复杂查询,动态查询
* *只有一个泛型: 就是我们操作的实体类
*
*
* SpringDataJpa中的查询:
*
* 1、dao接口中定义的方法
save和delete
findAll();查询所有
findOne(id);查询一个对象:立即查询
getOne(id); 查询一个对象:延迟加载
@Transactional
* 为了测试延迟加载,这个测试方法上需要加上一个事务注解:只是为了去掉no session异常
* 调用的是EntityManager.getReference();
count();查询总记录数
exists(id的值);查询对象是否存在,true存在,false不存在
* 判断一个实体是否存在: exists方法
* 1、发送根据id查询语句,如果查出来不为空,就代表存在,反之不存在
* select * from cst_customer where cust_id = ?
* 2、发送统计查询语句,统计有几条,如果大于0,就代表存在这条数据,反之不存在
* select count(*) from cst_customer where cust_id = ?
*
* SpringDataJpa用那种?看控制它发送的sql语句就可以了,我们测试发送,Spring用的是第二种
* 1、调用的是exists方法,传入的id主键值
* 2、返回的是布尔类型:
* true: 存在
* false:不存在
2、JPQL查询
JPA Query Language : jpa查询语言
需要写JPQL:
1、把sql中的表名换成实体类的名称
2、把sql中的字段名换成实体类中属性的名称
SpringDataJpa中使用jpql查询注意点:
1、需要在我们的接口中编写方法
2、在这个方法上使用注解:@Query,此注解中的value属性出入的就是jpql语句
3、如果是【更新】操作:除了加入Query之外还需要一个@Modifying注解
4、测试更新的时候需要加入事务和回滚的注解,只是为了测试
@Transactional
@Rollback(false)
*
* 1、在测试更新的时候,需要用到一个注解:@Transactional : 加入这个注解只是为了让程序不报错
* 2、加入了@Transactional注解后,程序不报错,但是数据没有更新
* 3、默认的情况下,我们在service层使用到是声明式事务,可以正常去更新数据,但是现在我们没有service层,所以需要加入另外一个注解
* @Rollback : 默认情况下我们没有service的时候,执行完之后,会回滚
* value: true 回滚
* value: false 不回滚
3、SQL查询【了解】
@Query注解:
* value属性:写的sql语句
* nativeQuery:
* true: sql查询
* false: jpql查询【默认值】
4、方法名规则查询
1)编写dao中的方法,编写有规则的
2)方法名以 findBy开头
3)findBy后面跟上的是 对象的属性名称,首字母大写
5、动态查询
*/
public interface CustomerDao extends JpaRepository<Customer,Long>,JpaSpecificationExecutor<Customer>{
//================== 2、JPQL查询 ==================================
/**
* 查询所有客户
* @return
*/
@Query("from Customer")
public List<Customer> findJPQL();
/**
* JPQL的条件查询:精确匹配
*/
@Query("from Customer where custName = ?")
public Customer findJPQL2(String n);
/**
* JPQL的条件查询:模糊查询
*/
@Query("from Customer where custName like ?")
public List<Customer> findJPQL3(String n);
/**
* JPQL的多条件查询
* 默认情况下: 方法中的参数有索引:从1开始, 占位符可以指定索引
* ?1 获取的是方法参数列表中的第一个参数
* ?2 获取的是方法参数列表中的第二个参数
*
*/
@Query("from Customer where custName like ?2 and custId = ?1")
public List<Customer> findJPQL4(Long id ,String n);
/**
* 需求:只修改客户的名称
*
* 使用JPQL来执行
* 需要用到两个注解:
* @Query里面写入的是update的语句
* @Modifying 告诉框架我们进行的是一个修改操作
*/
@Query("update Customer set custName = ?2 where custId = ?1")
@Modifying
public void updateCustomerName(Long id,String name);
//================== 3、SQL查询【了解】 ==================================
/**
* sql查询:
* @Query注解:
* value属性:写的sql语句
* nativeQuery:
* true: sql查询
* false: jpql查询【默认值】
*
*/
@Query(value="select * from cst_customer where cust_name like ?2 and cust_id = ?1",nativeQuery = true)
public List<Customer> findsql(Long id,String name);
//================== 4、方法名规则查询【推荐】==================================
/**
* 根据方法名查询:
* findByCustName : 根据客户名称精确查询
*/
public List<Customer> findByCustName(String name);
/**
* 根据方法名查询:
* findByCustName + Like : 根据客户名称模糊查询
*/
public List<Customer> findByCustNameLike(String name);
/**
* 根据方法名查询:多条件
* findByCustName + Like + And | Or + 对象的属性名称,首字母大写 + [Like ]
*/
public List<Customer> findByCustNameLikeAndCustId(String name,Long id);
}
SpringDataJpa原理分析
1、注入的dao的实现类:代理对象,JDKDynamicAopProxy
2、代理对象实现InvocationHandler接口,此接口中有invoke方法
3、此方法中调用具体dao的实现类:target = SimpleJpaRepository
4、底层完成的增删改查都是SimpleJpaRepository来完成
5、此类实现implements JpaRepository<T, ID>, JpaSpecificationExecutor<T>接口
6、我们调用customerDao.findOne(1L);方法底层其实就是调用SimpleJpaRepository的findOne
7、findOne的方法中调用:em.find(domainType, id);
8、em到底是谁?
它就是jpa规范中的实体类管理器
SpringDataJpa其实就是JPA规范封装
补充资料:
实例详解Spring Data JPA的使用
https://blog.csdn.net/l1357852347/article/details/73718700#t6
Spring Data JPA是Spring提供的基于ORM的JPA框架,它简化了数据库访问,通过接口即可实现CRUD操作。本文将介绍Spring Data JPA的概述、特性、与JPA和Hibernate的关系,以及快速入门教程,包括环境搭建、接口编写等。
8257

被折叠的 条评论
为什么被折叠?



