Spring Data JPA

JPA(二)Spring Data JPA

2019-06-26  本文已影响0人  guideEmotion

一 概述

Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!

推荐组合

Spring Data JPA 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现,在实际的工作工程中,推荐使用Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦

特性

SpringData Jpa 极大简化了数据库访问层代码。 如何简化的呢? 使用了SpringDataJpa,我们的dao层中只需要写接口,就自动具有了增删改查、分页查询等方法。

和其他框架的关系

Spring Data JPA 与 JPA和hibernate之间的关系
JPA是一套规范,内部是有接口和抽象类组成的。hibernate是一套成熟的ORM框架,而且Hibernate实现了JPA规范,所以也可以称hibernate为JPA的一种实现方式,我们使用JPA的API编程,意味着站在更高的角度上看待问题(面向接口编程)

Spring Data JPA是Spring提供的一套对JPA操作更加高级的封装,是在JPA规范下的专门用来进行数据持久化的解决方案。


注意
真正干活的还是hibernate

二 搭建环境

依赖

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zyc</groupId>
    <artifactId>springDateJpa</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springDateJpa</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <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>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

dao

使用Spring Data JPA,只需要按照框架的规范提供dao接口,不需要实现类就可以完成数据库的增删改查、分页查询等方法的定义,极大的简化了我们的开发过程。
规范

  1. 创建一个Dao层接口,并实现JpaRepositoryJpaSpecificationExecutor
  2. 提供相应的泛型
package com.zyc.springDateJpa.dao;

import com.zyc.springDateJpa.entity.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的dao层接口规范
 *      JpaRepository<操作的实体类类型,实体类中主键属性的类型>
 *          * 封装了基本CRUD操作
 *      JpaSpecificationExecutor<操作的实体类类型>
 *          * 封装了复杂查询(分页)
 */
public interface CustomerDao extends JpaRepository<Customer,Long> ,JpaSpecificationExecutor<Customer> {


    public Customer findByCustName(String custName);

}

测试

package com.zyc.springDateJpa;

import com.zyc.springDateJpa.dao.CustomerDao;
import com.zyc.springDateJpa.entity.Customer;
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.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringDateJpaApplicationTests {

    @Autowired
    private CustomerDao customerDao;


    @Test
    public void contextLoads() {
        Customer c = new Customer();
        c.setCustName("zhuyc");
        customerDao.save(c);


    }

}

三 CRUD

查询

        Optional<Customer> c = customerDao.findById(1l);
        System.out.println(c.get());

保存/更新

svae:保存或者更新

                Customer c = new Customer();
        c.setCustName("zhuyc");
        customerDao.save(c);

删除

根据id删除

springDataJpa会先查询,再删除;没查到,会报错

customerDao.deleteById(2l);

查询所有

List<Customer> list = customerDao.findAll();
        for(Customer customer : list) {
            System.out.println(customer);
        }

四 执行过程

在SpringDataJpa中我们只需要声明接口,框架会自动帮我们通过jdk动态代理生成接口实现类,然后注入导spring中。
动态代理对象中一般都是默认调用SimpleJpaRepository中的方法来工作的

image.png

五 复杂查询

查询总数

long count = customerDao.count();

查询id是否存在

boolean exists = customerDao.existsById(4l);

getOne

Customer customer = customerDao.getOne(4l);

JPQL

@Query注解的使用非常简单,只需在方法上面标注该注解,同时提供一个JPQL查询语句即可

    @Query(value="from Customer where custName = ?1")
    public Customer findJpql(String custName);

占位符

通过索引

    /**
     * 案例:根据客户名称和客户id查询客户
     *      jpql: from Customer where custName = ? and custId = ?
     *
     *  对于多个占位符参数
     *      赋值的时候,默认的情况下,占位符的位置需要和方法参数中的位置保持一致
     *
     *  可以指定占位符参数的位置
     *      ? 索引的方式,指定此占位的取值来源
     */
    @Query(value = "from Customer where custName = ?2 and custId = ?1")
    public Customer findCustNameAndId(Long id, String name);

实现更新

@Query : 代表的是进行查询
@Modifying:当前执行的是一个更新操作.有点组合的感觉,补充@Query

    /**
     *
     *  sql  :update cst_customer set cust_name = ? where cust_id = ?
     *  jpql : update Customer set custName = ? where custId = ?
     */
    @Query(value = " update Customer set custName = ?2 where custId = ?1 ")
    @Modifying
    public void updateCustomer(long custId, String custName);

@Rollback
设置是否自动回滚,本地测试:默认不回滚。

    @Test
    @Transactional //添加事务的支持
    @Rollback(value = true)
    public void testUpdateCustomer() {
        customerDao.updateCustomer(4l,"黑马程序员");
    }

sql查询

@Query有一个nativeQuery属.

    /**
     *  sql : select * from cst_customer;
     *  Query : 配置sql查询
     *      value : sql语句
     *      nativeQuery : 查询方式
     *          true : sql查询
     *          false:jpql查询(默认)
     *
     */
    //@Query(value = " select * from cst_customer" ,nativeQuery = true)
    @Query(value="select * from cst_customer where cust_name like ?1",nativeQuery = true)
    public List<Object [] > findSql(String name);

查询Map

有时会用到

    @Test
    public void testNativeQuery(){
        Query query = em.createNativeQuery("select * from cst_customer ");
        List<Map<String,Object>> list = query.unwrap(NativeQuery.class).addScalar("cust_id", StandardBasicTypes.LONG).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
        for(Map<String,Object> map:list){
            System.out.println(map.values());
        }

    }

方法命名规则查询

按照Spring Data JPA 定义的规则,查询方法以 findBy开头,涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法名多余的前缀截取掉,然后对剩下部分进行解析。

    /**
     * 方法名的约定:
     *      findBy : 查询
     *            对象中的属性名(首字母大写) : 查询的条件
     *            CustName
     *            * 默认情况 : 使用 等于的方式查询
     *                  特殊的查询方式
     *
     *  findByCustName   --   根据客户名称查询
     *
     *  再springdataJpa的运行阶段
     *          会根据方法名称进行解析  findBy    from  xxx(实体类)
     *                                      属性名称      where  custName =
     *
     *      1.findBy  + 属性名称 (根据属性名称进行完成匹配的查询=)
     *      2.findBy  + 属性名称 + “查询方式(Like | isnull)”
     *          findByCustNameLike
     *      3.多条件查询
     *          findBy + 属性名 + “查询方式”   + “多条件的连接符(and|or)”  + 属性名 + “查询方式”
     */
    public Customer findByCustName(String custName);

    public Customer findByCustNameLikeAndCustIndustry(String custName, String custIndustry);

具体的关键字,使用方法和生产成SQL如下表所示

image.png
image.png

参考

  1. 黑马Spring Data Jpa教学资料
上一篇下一篇

猜你喜欢

热点阅读