SpringBoot之SpringDataJpa-入门学习-1

1. 整体认识JPA

为什么要重新学习“Spring Data JPA”?俗话说的好:“未来已经来临,只是尚未流行”,纵观市场上的 ORM 框架,MyBatis 以灵活著称,但是要维护复杂的配置,并且不是 Spring 官方的天然全家桶,还得做额外的配置工作,如果资深的架构师还得做很多封装;Hibernate 以 HQL 和关系映射著称,但是就是使用起来不是特别灵活;那么 Spring Data JPA 来了,感觉要夺取 ORM 的 JPA 霸主地位了,底层以 Hibernate 为封装,对外提供了超级灵活的使用接口,又非常符合面向对象和 Rest 的风格,感觉是架构师和开发者的福音,并且 Spring Data JPA 与 Spring Boot 配合起来使用具有天然的优势,你会发现越来越多的公司的招聘要用会有传统的 SSH、Spring、MyBatis 要求,逐步的变为 Spring Boot、Spring Cloud、Spring Data 等 Spring 全家桶的要求,而很多新生代的架构师基于其生态的考虑,正在逐步推动者 Spring Data JPA 的更多的使用场景。

2. 市场上ORM框架对比

  • MyBatis:MyBatis 本是 Apache 的一个开源项目 iBatis,2010 年这个项目由 Apache Software Foundation 迁移到了 Google Code,并且改名为 MyBatis,其着力于 POJO 与 SQL 之间的映射关系,可以进行更为细致的 SQL,使用起来十分灵活、上手简单、容易掌握,所以深受开发者的喜欢,目前市场占有率最高,比较适合互联应用公司的 API 场景;缺点就是工作量比较大,需要各种配置文件的配置和 SQL 语句。
  • Hibernate:Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库,并且对象有自己的生命周期,着力点对象与对象之间关系,有自己的 HQL 查询语言,所以数据库移植性很好。Hibernate 是完备的 ORM 框架,是符合 JPA 规范的,有自己的缓存机制,上手来说比较难,比较适合企业级的应用系统开发。
  • Spring Data JPA:可以理解为 JPA 规范的再次封装抽象,底层还是使用了 Hibernate 的 JPA 技术实现,引用 JPQL(Java Persistence Query Language)查询语言,属于 Spring 的整个生态体系的一部分。由于 Spring Boot 和 Spring Cloud 在市场上的流行,Spring Data JPA 也逐渐进入大家的视野,他们有机的整体,使用起来比较方便,加快了开发的效率,使开发者不需要关系和配置更多的东西,完全可以沉浸在 Spring 的完整生态标准的实现下,上手简单、开发效率高,又对对象的支持比较好,又有很大的灵活性,市场的认可度越来越高。
  • OpenJPA :是 Apache 组织提供的开源项目,它实现了 EJB 3.0 中的 JPA 标准,为开发者提供功能强大、使用简单的持久化数据管理框架,但功能、性能、普及性等方面更加需要加大力度,所以用的人不人不是特别多。
  • QueryDSL:QueryDSL 可以在任何支持的 ORM 框架或者 SQL 平台上以一种通用的 API 方式来构建查询,目前 QueryDSL 支持的平台包括 JPA、JDO、SQL、Java Collections、RDF、Lucene、Hibernate Search,同时 Spring Data JPA 也对 QueryDSL 做了很好的支持。

3. SpringBoot Jpa

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

3.1 基础查询

基本查询也分为两种,一种是 Spring Data 默认已经实现,一种是根据查询的方法来自动解析成 SQL。
预先生成方法
Spring Boot Jpa 默认预先生成了一些基本的CURD的方法,例如:增、删、改等等

** 引入依赖**

 <!--1 确定spring boot的版本-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>

    <dependencies>
        <!--test测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>
        <!--web起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--通用mapper起步依赖-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.4</version>
        </dependency>
        <!--MySQL数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--jpa-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>

配置yml文件

#端口号
server:
  port: 9090
#服务名和数据源(连接池)
spring:
  application:
    name: activitiservice
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/activiti6_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&nullCatalogMeansCurrent=true
    username: root
    password: 1234
  jpa:
    show-sql: true

编写实体类

package com.yb.domain;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;

/**
 * @author [email protected]
 * @version 1.0
 * @date 2020/7/31
 */
@Data
@Entity
@Table(name = "act_hi_taskinst")
public class HiTaskinst {
    
    

    @Id
    @Column(name = "ID_")
    private String id;

    @Column(name = "PROC_DEF_ID_")
    private String procDefId;

    @Column(name = "TASK_DEF_KEY_")
    private String taskDefKey;

    @Column(name = "PROC_INST_ID_")
    private String procInstId;

    @Column(name = "EXECUTION_ID_")
    private String executionId;

    @Column(name = "NAME_")
    private String name;

    @Column(name = "PARENT_TASK_ID_")
    private String parentTaskId;

    @Column(name = "DESCRIPTION_")
    private String description;

    @Column(name = "OWNER_")
    private String owner;

    @Column(name = "ASSIGNEE_")
    private String assignee;

    @Column(name = "START_TIME_")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date startTime;

    @Column(name = "CLAIM_TIME_")
    private Date claimTime;

    @Column(name = "END_TIME_")
    private Date endTime;

    @Column(name = "DURATION_")
    private Long duration;

    @Column(name = "DELETE_REASON_")
    private String deleteReason;

    @Column(name = "PRIORITY_")
    private Integer priority;

    @Column(name = "DUE_DATE_")
    private Date dueDate;

    @Column(name = "FORM_KEY_")
    private String formKey;

    @Column(name = "CATEGORY_")
    private String category;

    @Column(name = "TENANT_ID_")
    private String tenantId;
}

编写HiTaskinstRepository接口,只需继承JpaRepository即可

public interface HiTaskinstRepository extends JpaRepository<HiTaskinst,String> {
    
    
}

编写JpaService接口

public interface JpaService {
    
    
    Optional<HiTaskinst> test01(String s);
}

JpaServiceImpl类

@Service
public class JpaServiceImpl implements JpaService {
    
    
    @Resource
    private HiTaskinstRepository hiTaskinstRepository;

    @Override
    public Optional<HiTaskinst> test01(String s) {
    
    

        return hiTaskinstRepository.findById(s);
    }
}

编写JpaController

@RestController
@RequestMapping("/jpa")
public class JpaController {
    
    
    @Resource
    private JpaService jpaService;

    @GetMapping
    private HiTaskinst test01(){
    
    
        Optional<HiTaskinst> byId = jpaService.test01("2505");
        if(byId.isPresent()){
    
    
            HiTaskinst hiTaskinst = byId.get();
            System.out.println(hiTaskinst);
            return hiTaskinst;
        }
        return null;
    }
}

测试
浏览器直接访问看运行结果
在这里插入图片描述

3.2 使用自己编写方法实现CRUD

3.2.1 自定义查询

JPA中一些常用的查询操作

    //And --- 等价于 SQL 中的 and 关键字,比如 findByHeightAndSex(int height,char sex);
    public List<HiTaskinst> findByHeightAndSex(int height,char sex);
 
   // Or --- 等价于 SQL 中的 or 关键字,比如 findByHeightOrSex(int height,char sex);
    public List<HiTaskinst> findByHeightOrSex(int height,char sex);
 
    //Between --- 等价于 SQL 中的 between 关键字,比如 findByHeightBetween(int min, int max);
    public List<HiTaskinst> findByHeightBetween(int min,int max);
 
    //LessThan --- 等价于 SQL 中的 "<",比如 findByHeightLessThan(int max);
    public List<HiTaskinst> findByHeightLessThan(int max);
 
    //GreaterThan --- 等价于 SQL 中的">",比如 findByHeightGreaterThan(int min);
    public List<HiTaskinst> findByHeightGreaterThan(int min);
 
    //IsNull --- 等价于 SQL 中的 "is null",比如 findByNameIsNull();
    public List<HiTaskinst> findByNameIsNull();
 
    //IsNotNull --- 等价于 SQL 中的 "is not null",比如 findByNameIsNotNull();
    public List<HiTaskinst> findByNameIsNotNull();
 
    //NotNull --- 与 IsNotNull 等价;
    public List<HiTaskinst> findByNameNotNull();
 
    //Like --- 等价于 SQL 中的 "like",比如 findByNameLike(String name);
    public List<HiTaskinst> findByNameLike(String name);
 
    //NotLike --- 等价于 SQL 中的 "not like",比如 findByNameNotLike(String name);
    public List<HiTaskinst> findByNameNotLike(String name);
 
    //OrderBy --- 等价于 SQL 中的 "order by",比如 findByNameNotNullOrderByHeightAsc();
    public List<HiTaskinst>findByNameNotNullOrderByHeightAsc();
 
    //Not --- 等价于 SQL 中的 "! =",比如 findByNameNot(String name);
    public List<HiTaskinst> findByNameNot(String name);
 
    //In --- 等价于 SQL 中的 "in",比如 findByNameIN(String name);
    public List<HiTaskinst> findByNameIn(String name);
 
    //NotIn --- 等价于 SQL 中的 "not in",比如 findByNameNotIN(String name);
    public List<HiTaskinst> findByNameNotIn(String name);

在HiTaskinstRepository中添加方法

 public interface HiTaskinstRepository extends JpaRepository<HiTaskinst,String> {
    
    
    /**
     * 通过名称查询
     * @param name
     * @return
     */
    List<HiTaskinst> findByNameLike(String name);
}

在controller中添加代码测试

/**
     * 通过名称查询-自定义方法
     * @param name
     * @return
     */
    @GetMapping("/test02/{name}")
    private List<HiTaskinst> test02(@PathVariable("name") String name) {
    
    
        System.out.println(name);
        List<HiTaskinst>  list = jpaService.test02(name);
        System.out.println(list.size());
        for (HiTaskinst hiTaskinst : list) {
    
    
            System.out.println(hiTaskinst);
        }
       return list;
    }

JpaServiceImpl中方法

  /**
     * 通过名称查询-自定义方法
     * @param name
     * @return
     */
    @Override
    public List<HiTaskinst>  test02(String name) {
    
    
    	//自定义方法
        List<HiTaskinst> byNameLike = hiTaskinstRepository.findByNameLike(name);
        return byNameLike;
    }

测试
浏览器直接访问看运行结果
在这里插入图片描述
这是因为 jpa 通过关键字以及驼峰命名解析,findByName 会帮你解析成select from user where name like ?从而实现查询。

3.2.2 复杂的关联查询

一些比较复杂的关联查询要怎么实现呢,JPA的处理方法是:利用原生的SQl命令来实现那些复杂的关联查询
JpaController

package com.yb.controller;

import com.yb.domain.HiTaskinst;
import com.yb.service.JpaService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;

/**
 * @author [email protected]
 * @version 1.0
 * @date 2020/7/31
 */
@RestController
@RequestMapping("/jpa")
public class JpaController {
    
    
    @Resource
    private JpaService jpaService;

    /**
     * 测试基础查询-通过id查询
     * @return
     */
    @GetMapping
    private HiTaskinst test01(){
    
    
        Optional<HiTaskinst> byId = jpaService.test01("2505");
        if(byId.isPresent()){
    
    
            HiTaskinst hiTaskinst = byId.get();
            System.out.println(hiTaskinst);
            return hiTaskinst;
        }
        return null;
    }

    /**
     * 通过名称查询-自定义方法
     * @param name
     * @return
     */
    @GetMapping("/test02/{name}")
    private List<HiTaskinst> test02(@PathVariable("name") String name) {
    
    
        System.out.println(name);
        List<HiTaskinst>  list = jpaService.test02(name);
        System.out.println(list.size());
        for (HiTaskinst hiTaskinst : list) {
    
    
            System.out.println(hiTaskinst);
        }
       return list;
    }
    /**
     * 通过名称查询-原生SQL进行查询操作
     * @param name
     * @return
     */
    @GetMapping("/test03/{name}")
    private List<HiTaskinst> test03(@PathVariable("name") String name) {
    
    
        System.out.println(name);
        List<HiTaskinst>  list = jpaService.test03(name);
        System.out.println(list.size());
        for (HiTaskinst hiTaskinst : list) {
    
    
            System.out.println(hiTaskinst);
        }
        return list;
    }

}

HiTaskinstRepository

package com.yb.dao;

import com.yb.domain.HiTaskinst;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

/**
 * @author [email protected]
 * @version 1.0
 * @date 2020/7/31
 */
public interface HiTaskinstRepository extends JpaRepository<HiTaskinst,String> {
    
    
    /**
     * 通过名称查询
     * @param name
     * @return
     */
    List<HiTaskinst> findByNameLike(String name);

    /**
     * 原生SQL
     * @param name
     * @return
     */
    @Query(value = "select ht.* from `act_hi_taskinst` ht WHERE ht.`NAME_` = ?1",
           nativeQuery = true)
    @Modifying
    List<HiTaskinst> findHiTaskinstByName(String name);

}

测试
在这里插入图片描述

3.2.3 JPA分页查询

3.2.3.1 普通分页查询

JpaController

/**
     * 分页查询
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping("/test04")
    private List<HiTaskinst> test04(Integer pageNum,Integer pageSize) {
    
    
        System.out.println(pageNum+"==="+pageSize);
        PageRequest pageRequest = new PageRequest(pageNum-1, pageSize);
        Page<HiTaskinst> pages = jpaService.test04(pageRequest);
        List<HiTaskinst> content = pages.getContent();
        System.out.println(content.size());
        return content;
    }

JpaServiceImpl

/**
     * 分页查询
     * @param pageRequest
     * @return
     /
    @verride
    public Page<HiTaskinst> test04(PageRequest pageRequest) {
        Page<HiTaskinst> byNameNot = hiTaskinstRepository.findAll(pageRequest);
        return byNameNot;
    }

HiTaskinstRepository

/**
     * 分页查询
     * @param pageable
     * @return
     */
    Page<HiTaskinst> findAll(Pageable pageable);

测试
浏览器直接访问看运行结果,查询第一页,每页两条数据。
在这里插入图片描述

3.2.3.2 排序分页查询

JpaController

/**
     * 分页查询+排序
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping("/test05")
    private List<HiTaskinst> test05(Integer pageNum,Integer pageSize) {
    
    
        System.out.println("排序分页:"+pageNum+"==="+pageSize);

        Page<HiTaskinst> pages = jpaService.test05(pageNum,pageSize);
        List<HiTaskinst> content = pages.getContent();
        System.out.println(content.size());
        return content;
    }

JpaServiceImpl

/**
     * 排序分页查询
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public Page<HiTaskinst> test05(Integer pageNum, Integer pageSize) {
    
    
        //设置以表中具体字段来进行排序,desc倒序,asc正序
        Sort sort = new Sort(Sort.Direction.DESC,"endTime");
        PageRequest pageRequest = new PageRequest(pageNum - 1, pageSize, sort);
        Page<HiTaskinst> all = hiTaskinstRepository.findAll(pageRequest);
        return all;
    }

HiTaskinstRepository

 /**
     * 分页查询
     * @param pageable
     * @return
     */
    Page<HiTaskinst> findAll(Pageable pageable);

测试
浏览器直接访问看运行结果,查询第一页,每页两条数据。此查询以endTime结束时间来排序,倒序
在这里插入图片描述

3.2.3.3 条件分页查询

JpaController

 /**
     * 分页查询+条件
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping("/test06/{name}")
    private List<HiTaskinst> test06(@PathVariable("name") String name,Integer pageNum,Integer pageSize) {
    
    
        System.out.println("条件分页:"+pageNum+"==="+pageSize);

        Page<HiTaskinst> pages = jpaService.test06(name,pageNum,pageSize);
        List<HiTaskinst> content = pages.getContent();
        System.out.println(content.size());
        return content;
    }

JpaServiceImpl

 /**
     * 分页查询+条件
     * @param name
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public Page<HiTaskinst> test06(String name, Integer pageNum, Integer pageSize) {
    
    
        PageRequest pageRequest = new PageRequest(pageNum - 1, pageSize);

        return hiTaskinstRepository.findByNameLike(name,pageRequest);
    }

HiTaskinstRepository

/**
     * 分页查询+条件(根据名称查询)
     * @param name
     * @param pageable
     * @return
     */
    Page<HiTaskinst> findByNameLike(String name,Pageable pageable);

测试
浏览器直接访问看运行结果,查询第一页,每页两条数据,这里传输的条件是name=班长审批,数据库就这一条,所以效果只有一条信息
在这里插入图片描述

3.2.4 JPA添加

JpaController

/**
     * JPA添加
     * @return
     */
    @PostMapping("/add")
    public HiTaskinst addHiTaskinst(@RequestBody HiTaskinst hiTaskinst){
    
    
        System.out.println(hiTaskinst);
        HiTaskinst h = jpaService.addHiTaskinst(hiTaskinst);
        return h;
    }

JpaServiceImpl

/**
     * 添加-save
     * @param hiTaskinst
     * @return
     */
    @Override
    public HiTaskinst addHiTaskinst(HiTaskinst hiTaskinst) {
    
    
        HiTaskinst save = hiTaskinstRepository.save(hiTaskinst);
        return save;
    }

测试
在这里插入图片描述

3.2.4 JPA删除

JpaController

/**
     * JPA删除
     * @return
     */
    @DeleteMapping("/delete/{id}")
    public String deleteHiTaskinst(@PathVariable("id") String id){
    
    
        System.out.println(id);
        String h = jpaService.deleteHiTaskinst(id);
        return h;
    }

JpaServiceImpl

 /**
     * JPA删除
     * @param id
     * @return
     */
    @Override
    public String deleteHiTaskinst(String id) {
    
    
        try {
    
    
            hiTaskinstRepository.deleteById(id);
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return "服务器繁忙";
        }
        return "删除成功";
    }

3.2.5 JPA修改

JpaController

/**
     * JPA修改
     * @return
     */
    @PutMapping("/put")
    public HiTaskinst putHiTaskinst(@RequestBody HiTaskinst hiTaskinst){
    
    
        System.out.println(hiTaskinst);
        HiTaskinst h = jpaService.putHiTaskinst(hiTaskinst);
        return h;
    }

JpaServiceImpl

/**
     * 修改
     * @param hiTaskinst
     * @return
     */
    @Override
    public HiTaskinst putHiTaskinst(HiTaskinst hiTaskinst) {
    
    
        HiTaskinst save = hiTaskinstRepository.save(hiTaskinst);
        return save;
    }

测试
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Lv_vI/article/details/107711390