七、Spring Boot - 上手篇(3)

一、SpringBoot 使用JPA操作数据库

1.1 JPA介绍

JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

jpa具有什么优势?

  • (1)、标准化
    JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。
  • (2)、容器级特性的支持
    JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。
  • (3)、简单方便
    JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。JPA基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成。
  • (4)、查询能力
    JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。
  • (5)、高级特性
    JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。

1.2 SpringBoot 使用JPA 入门

创建项目springboot-jpa
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(1)、添加jpa起步依赖以及mysqljdbc驱动、连接池druid驱动

在这里插入图片描述

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>

注意jpa使用不要在依赖spring-boot-starter-jdbc 和jpa 同步依赖包有冲突!

(2)、修改springboot配置文件application.yml增加如下jpa配置:

在这里插入图片描述

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm?serverTimezone=GMT%2B8
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource

  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

jpa.hibernate.ddl-autohibernate的配置属性,其主要作用是:自动创建、更新、验证数据库表结构。该参数的几种配置如下:

  • ·create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
  • ·create-drop:每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
  • ·update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
  • ·validate:每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。

(3)、创建实体

在这里插入图片描述

package com.gansu.pojo;

import javax.persistence.*;
import java.io.Serializable;


@Entity
@Table(name = "t_person")
public class Person implements Serializable {

    @Id
    @GeneratedValue
    private Long id;
    @Column(length = 20,nullable = true,name = "name")
    private String name;
    @Column(length = 15,nullable = true,name = "age")
    private Integer age;

    public Person() {
    }

    public Person(Long id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

JPA注解:

注解作用
@Entity声明类为实体或表
@Table声明表名
@Basic指定非约束明确的各个字段
@Embedded指定类或它的值是一个可嵌入的类的实例的实体的属性
@Id指定的类的属性,用于识别(一个表中的主键)
@GeneratedValue指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值
@Transient指定的属性,它是不持久的,即:该值永远不会存储在数据库中
@Column指定持久属性栏属性
@SequenceGenerator指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列
@TableGenerator指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表
@AccessType这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量
@JoinColumn指定一个实体组织或实体的集合。这是用在多对一和一对多关联
@UniqueConstraint指定的字段和用于主要或辅助表的唯一约束
@ColumnResult参考使用select子句的SQL查询中的列名
@ManyToMany定义了连接表之间的多对多一对多的关系
@ManyToOne定义了连接表之间的多对一的关系
@OneToMany定义了连接表之间存在一个一对多的关系
@OneToOne定义了连接表之间有一个一对一的关系
@NamedQueries指定命名查询的列表
@NamedQuery指定使用静态名称的查询

(4)、数据访问接口

在这里插入图片描述

package com.gansu.service;

import com.gansu.pojo.Person;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PersonReposity extends JpaRepository<Person,Long> {


}

(5)、创建Controller

在这里插入图片描述

package com.gansu.controller;


import com.gansu.pojo.Person;
import com.gansu.service.PersonReposity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/person")
public class PersonController {

    @Autowired
    PersonReposity personReposity;

    @PostMapping("/addPerson")
    public String addPerson(@RequestBody  Person person){

        personReposity.save(person);

        return "addPerson-ok";
    }

    @GetMapping("/findPerson")
    public List<Person> findPerson(){

       return personReposity.findAll();

    }


    @GetMapping("/findPersonById/{id}")
    public Optional<Person> findPersonById(@PathVariable("id") Long id){

        return personReposity.findById(id);

    }


    @PutMapping("/updatePersonById/{id}")
    public String updatePersonById(@PathVariable("id") Long id,@RequestBody  Person person){

          person.setId(id);
         personReposity.saveAndFlush(person);

         return "updatePersonById-ok";

    }


    @DeleteMapping("/deletePersonById/{id}")
    public String deletePersonById(@PathVariable("id") Long id){


        personReposity.deleteById(id);

        return "deletePersonById-ok";

    }
}

注意:接收传递json格式的对象,需要增加注解:@RequestBody
@requestBody注解常用来处理content-type不是默认的application/x-www-form-urlcoded编码的内容,比如说:application/json或者是application/xml等。一般情况下来说常用其来处理application/json类型。

(6)、测试 添加数据

启动应用程序,看到自动创建了数据表

在这里插入图片描述

开启postman,设置发出post请求,请求地址:http://localhost:8080/person/addPerson
请求参数,选择body,选择 raw方式,发送JSON(application/json)请求

在这里插入图片描述

在程序控制台看到:

在这里插入图片描述
查看数据表即可

(7)、测试 获取数据

开启postman,设置发出get请求,请求地址:http://localhost:8080/person/findPerson

在这里插入图片描述

(8)、测试 修改数据

开启postman,设置发出put请求,请求地址:http://localhost:8080/person/updatePersonById/3
请求参数,选择body,选择 raw方式,发送JSON(application/json)请求

在这里插入图片描述

(9)、测试 删除数据

开启postman,设置发出delete请求,请求地址:http://localhost:8080/person/deletePersonById/3
Parsms参数设置,key名称id value 值 1

在这里插入图片描述

1.3 SpringBoot 使用JPA实现自动化查询

SpringBoot 使用JPA按照规定的接口命名方法来实现自动化查询

我们通过继承JpaRepository接口,除了可以获得上面的基础CRUD操作方法之外,还可以通过Spring规定的接口命名方法自动创建复杂的CRUD操作,以下是我在Spring Data JPA 文档中找到的命名规则表:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(1)、编辑PersonReposity,新增如下方法

在这里插入图片描述

package com.gansu.service;

import com.gansu.pojo.Person;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface PersonReposity extends JpaRepository<Person,Long> {

    //查询指定用户姓名的用户
    public Person findByNameIs(String name);

    //查询指定用户姓名和密年龄的用户
    public Person findByNameAndAge(String name,Integer age);

    //查询包含指定名字的用户
    public List<Person> findByNameContaining(String name);
}

(2)、新增Controller 类PersonController

在这里插入图片描述

package com.gansu.controller;


import com.gansu.pojo.Person;
import com.gansu.service.PersonReposity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/person")
public class PersonController {

    @Autowired
    PersonReposity personReposity;


    @GetMapping("/findByNameContaining/{name}")
    public List<Person> findByNameContaining(@PathVariable("name") String name){

        List<Person> personList =   personReposity.findByNameContaining(name);

        return personList;
    }


    @GetMapping("/findPersonByNameAndAge/{name}/{age}")
    public Person findPersonByNameAndAge(@PathVariable("name") String name,@PathVariable("age")Integer age){

        return  personReposity.findByNameAndAge(name,age);

    }

    @GetMapping("/findPersonByName/{name}")
    public Person findPersonByName(@PathVariable("name") String name){

         return  personReposity.findByNameIs(name);

    }
}

查询指定用户姓名的用户

http://localhost:8080/person/findPersonByName/888

在这里插入图片描述

查询指定用户姓名和密年龄的用户 http://localhost:8080/person/findPersonByNameAndAge/888/888

在这里插入图片描述

查询包含指定名字的用户http://localhost:8080/person/findByNameContaining/zhang

在这里插入图片描述

1.4 SpringBoot 使用JPA实现自定义查询

SpringBoot 使用JPA使用@Query实现自定义查询语句

Jpa提供了非常大的自由度给开发者,我们可以在接口方法中通过定义@Query 注解自定义接口方法的JPQL语句。

(1)、编辑PersonRepository,新增如下方法

在这里插入图片描述

//查询指定用户姓名的用户
@Query("SELECT p FROM Person p where name=:name")
public Person getPersonName(@Param("name") String name);


//查询指定用户姓名的用户  原生
@Query(value = "SELECT * FROM t_person p where name=:name",nativeQuery = true)
public Person getPersonNameYuan(@Param("name") String name);


//模糊查询
@Query("SELECT p FROM Person p where p.name like %:name%")
public List<Person> getPersonNameM(@Param("name") String name);

注意:@Query设置查询的jpsql语句,是面向对象的语法,类似HQL;也可以设置nativeQuery=true来使用原始sql语句。
注意:当jdk 版本大于1.8.0_101 @Parm 需要设置,传递给JPSQL语句的参数,对应在语句中用 :变量名 来获取变量.
原生sql传递多个参数在sql里面使用 ?序号 方式获取对应参数,比如 ?1 ?2
查询指定用户姓名的用户

(2)、新增Controller 类PersonController

在这里插入图片描述

@Autowired
PersonReposity personReposity;

@GetMapping("/getPersonName/{name}")
public Person getPersonName(@PathVariable("name") String name){

    // return  personReposity.getPersonName(name);
    return  personReposity.getPersonNameYuan(name);

}

@GetMapping("/findByNameContaining/{name}")
public List<Person> findByNameContaining(@PathVariable("name") String name){

   // List<Person> personList =   personReposity.findByNameContaining(name);
    List<Person> personList =   personReposity.getPersonNameM(name);

    return personList;
}

http://localhost:8080/person/getPersonName/zhang123

在这里插入图片描述

模糊查询http://localhost:8080/person/findByNameContaining/zhang

在这里插入图片描述

文章源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Daniel521-Spark

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值