当前位置:   article > 正文

第十五节:SpringBoot使用JPA访问数据库_org.springframework.data.domain.page

org.springframework.data.domain.page

JPA是Java Persistence API的简写,是官方提出的一种ORM规范!

JPA规范,都在包路径:javax.persistence.*下,像一些常用的如:@Entity、@Id及@Transient都在此路径下。这些也是一些现在市面上常用的ORM一些约定俗成的注解了。

Spring Data JPA是Spring基于Hibernate开发的一个JPA框架。可以极大的简化JPA的写法,可以在几乎不用写具体代码的情况下,实现对资料的访问和操作。除了「CRUD」外,还包括如分页、排序等一些常用的功能。

pom.xml中添加依赖


  org.springframework.boot
  spring-boot-starter-data-jpa


  mysql
  mysql-connector-java

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

application.properties 配置

spring.datasource.url=jdbc:mysql://localhost:3306/rumenz_springboot
spring.datasource.username=root
spring.datasource.password=root1234
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.jpa.hibernate.ddl-auto=update
spring.sql.init.mode=always
spring.sql.init.schema-locations=classpath:/ddl/user-book.sql
spring.sql.init.data-locations=classpath:/ddl/user-book-data.sql
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

spring.jpa.hibernate.ddl-auto 是否根据实体类更新数据库,有四个属性值

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

spring.sql.init.mode 是否使用sql文件初始化数据库,有3个值

属性值作用
ALWAYS始终初始化数据库。
EMBEDDED仅初始化嵌入式数据库。
NEVER永远不要初始化数据库。
  • spring.sql.init.schema-locations 指定建表的sql文件
  • spring.sql.init.data-locations指定数据sql文件

创建实体类

User.java
@Getter
@Setter
@Builder
@AllArgsConstructor
@Entity //jpa必填
@DynamicInsert //填充默认值
@DynamicUpdate //填充默认值
@Table(name = "user") //jpa必填
@NoArgsConstructor
public class User {
    @Id //jpa必填
    @GeneratedValue(strategy = GenerationType.IDENTITY) //jpa必填
    private Integer id;
    private String name;
    private String domain;
    @Column(name = "age",columnDefinition = "tinyint default 0")
    private Integer age;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

@GeneratedValue(strategy = GenerationType.IDENTITY)有以下几种类型

  • TABLE:使用一个特定的数据库表格来保存主键。
  • SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。
  • IDENTITY:主键由数据库自动生成(主要是自动增长型)
  • AUTO:主键由程序控制。

创建repository

数据持久层,负责访问数据库,在这里声明的方法一般不用实现,只要按照Jpa的规范就可以自动生成SQL语句。

package com.rumenz.lession15.controller.repository;

import com.rumenz.lession15.controller.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

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

/**
 * @className: UserRepository
 * @description: TODO 类描述
 * @author: 入门小站 rumenz.com
 * @date: 2021/12/14
 **/

@Repository
public interface UserRepository extends PagingAndSortingRepository {


    Optional findById(Integer id);
    List findDistinctUserByName(String name);
    Integer countUserByName(String name);
    List readDistinctByName(String name);

    Page findAllByName(String name, Pageable pageable);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

Jpa可以通过接口名生成对应的sql语句,如 find… By,read… By,query… By,count… By,和get… By 。这些方法可以包含其他表达式,例如在要创建的查询上设置 Distinct 标志。第一个 By 用作分隔符,表示条件的开始,后面定义实体属性的各种条件,并将它们用 And 和 Or 连接起来。例如:

interface RumenzRepository extends JpaRepository {

  List findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);

  // 为查询启用 distinct 标志
  List findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
  List findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);

  // 为单个属性启用忽略大小写
  List findByLastnameIgnoreCase(String lastname);
  // 为所有属性启用忽略大小写
  List findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);

  // 为查询启用静态 Order by
  List findByLastnameOrderByFirstnameAsc(String lastname);
  List findByLastnameOrderByFirstnameDesc(String lastname);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

举一些例子

关键字方法示例JPQL snippet
AndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2
OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2
Is, EqualsfindByFirstname,findByFirstnameIs,findByFirstnameEquals… where x.firstname = ?1
BetweenfindByStartDateBetween… where x.startDate between ?1 and ?2
LessThanfindByAgeLessThan… where x.age < ?1
LessThanEqualfindByAgeLessThanEqual… where x.age <= ?1
GreaterThanfindByAgeGreaterThan… where x.age > ?1
GreaterThanEqualfindByAgeGreaterThanEqual… where x.age >= ?1
AfterfindByStartDateAfter… where x.startDate > ?1
BeforefindByStartDateBefore… where x.startDate < ?1
IsNull, NullfindByAge(Is)Null… where x.age is null
IsNotNull, NotNullfindByAge(Is)NotNull… where x.age not null
LikefindByFirstnameLike… where x.firstname like ?1
NotLikefindByFirstnameNotLike… where x.firstname not like ?1
StartingWithfindByFirstnameStartingWith… where x.firstname like ?1 (parameter bound with appended %)
EndingWithfindByFirstnameEndingWith… where x.firstname like ?1 (parameter bound with prepended %)
ContainingfindByFirstnameContaining… where x.firstname like ?1 (parameter bound wrapped in %)
OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname desc
NotfindByLastnameNot… where x.lastname <> ?1
InfindByAgeIn(Collection ages)… where x.age in ?1
NotInfindByAgeNotIn(Collection ages)… where x.age not in ?1
TruefindByActiveTrue()… where x.active = true
FalsefindByActiveFalse()… where x.active = false
IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstame) = UPPER(?1)

Repository有3种

JpaRepository继承PagingAndSortingRepository,PagingAndSortingRepository继承CrudRepository。

  • CrudRepository提供CRUD的功能
  • PagingAndSortingRepository提供分页和排序功能
  • JpaRepository提供JPA相关的方法,如刷新持久化数据、批量删除等。

image-20211222163426330

service

业务逻辑层,负责调用Repository处理数据完成业务。

package com.rumenz.lession15.controller.service;

import com.rumenz.lession15.controller.entity.User;
import org.springframework.data.domain.Page;

import java.util.List;

/**
 * @className: UserService
 * @description: TODO 类描述
 * @author: 入门小站 rumenz.com
 * @date: 2021/12/14
 **/
public interface UserService {
    Integer save(User user);

    User get(Integer id);

    List listByName(String name);

    Integer countByName(String name);

    List readDistinctByName(String name);

    Page listByNamePage(String name, Integer page, Integer pageSize);
}


//实现类


package com.rumenz.lession15.controller.service.lmpl;

import com.rumenz.lession15.controller.entity.User;

import com.rumenz.lession15.controller.repository.UserRepository;
import com.rumenz.lession15.controller.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

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

/**
 * @className: UserServiceImpl
 * @description: TODO 类描述
 * @author: 入门小站 rumenz.com
 * @date: 2021/12/14
 **/
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserRepository userRepository;


    @Override
    public Integer save(User user) {
        User save = userRepository.save(user);
        return save.getId();
    }

    @Override
    public User get(Integer id) {
        Optional opt = userRepository.findById(id);

        return opt.isPresent()?opt.get():null;
    }

    @Override
    public List listByName(String name) {
        List res = userRepository.findDistinctUserByName(name);
        return res;
    }

    @Override
    public Integer countByName(String name) {
        return userRepository.countUserByName(name);
    }

    @Override
    public List readDistinctByName(String name) {

        return userRepository.readDistinctByName(name);
    }

    @Override
    public Page listByNamePage(String name, Integer page, Integer pageSize) {

        Sort sort = Sort.by("id").descending();
        Pageable pageable= PageRequest.of(page-1, pageSize, sort);
        Page res = userRepository.findAllByName(name, pageable);
        return res;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101

Controller

前端控制器,负责接收前端请求,调用service,返回数据。

package com.rumenz.lession15.controller;

import com.rumenz.lession15.controller.entity.User;
import com.rumenz.lession15.controller.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @className: RumenzController
 * @description: TODO 类描述
 * @author: 入门小站 rumenz.com
 * @date: 2021/12/14
 **/
@RestController
@RequestMapping("/rumenz")
public class RumenzController {

    @Autowired
    UserService userService;

    //保存数据
    //id=1的数据不存在就添加
    //id=1的数据存在就更新
    @RequestMapping("/save")
    public String save(){
        User user=User.builder().id(1).name("入门小站123").domain("https://rumenz.com").build();
        Integer save = userService.save(user);
        return save.toString();
    }
    //通过id查询数据
    @GetMapping("/get")
    public User get(@RequestParam("id") Integer id){
        return userService.get(id);
    }


    //带条件查询
    @GetMapping("/listByName")
    public List get(@RequestParam("name") String name){
        return userService.listByName(name);
    }

    //按条件查询符合条件的数量
    @GetMapping("/countByName")
    public Integer countByName(@RequestParam("name") String name){
        return userService.countByName(name);
    }

    //带条件查询
    @GetMapping("/readDistinctByName")
    public List readDistinctByName(@RequestParam("name") String name){
        return userService.readDistinctByName(name);
    }

    //分页查询
    //带条件查询
    @GetMapping("/listByNamePage")
    public Page listByNamePage(@RequestParam("name") String name, @RequestParam("page") Integer page, @RequestParam("pageSize") Integer pageSize){
        return userService.listByNamePage(name,page,pageSize);
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

本小结源码地址:

  • GitHub:https://github.com/mifunc/springboot/tree/main/lession15
  • Gitee:https://gitee.com/rumenz/springboot/tree/master/lession15
  • https://rumenz.com/rumenbiji/springboot-jpa-base.html

介绍

  • 我的博客 https://rumenz.com/ ,
  • 我的工具箱 https://tooltt.com/
  • 微信公众号:【入门小站】

  • 关注【入门小站】回复【1001】获取 linux常用命令速查手册
  • 关注【入门小站】回复【1003】获取 LeetCode题解【java语言实现】
  • 关注【入门小站】回复【1004】获取 Java基础核心总结
  • 关注【入门小站】回复【1009】获取 阿里巴巴Java开发手册
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/784162
推荐阅读
相关标签
  

闽ICP备14008679号