Spring Data JPA

Spring Data JPA是Spring提供的基于ORM的JPA框架,它简化了数据库访问,通过接口即可实现CRUD操作。本文将介绍Spring Data JPA的概述、特性、与JPA和Hibernate的关系,以及快速入门教程,包括环境搭建、接口编写等。
摘要由CSDN通过智能技术生成

##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&amp;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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值