写点什么

第十五节:SpringBoot 使用 JPA 访问数据库

作者:入门小站
  • 2022 年 2 月 23 日
  • 本文字数:4715 字

    阅读完需:约 15 分钟

第十五节:SpringBoot使用JPA访问数据库

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


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


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

pom.xml 中添加依赖

<dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency>  <groupId>mysql</groupId>  <artifactId>mysql-connector-java</artifactId></dependency>
复制代码

application.properties 配置

spring.datasource.url=jdbc:mysql://localhost:3306/rumenz_springbootspring.datasource.username=rootspring.datasource.password=root1234spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=updatespring.sql.init.mode=alwaysspring.sql.init.schema-locations=classpath:/ddl/user-book.sqlspring.sql.init.data-locations=classpath:/ddl/user-book-data.sql
复制代码


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



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



  • 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必填@NoArgsConstructorpublic 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;}
复制代码


@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 **/
@Repositorypublic interface UserRepository extends PagingAndSortingRepository<User,Integer> {

Optional<User> findById(Integer id); List<User> findDistinctUserByName(String name); Integer countUserByName(String name); List<User> readDistinctByName(String name);
Page<User> findAllByName(String name, Pageable pageable);}
复制代码


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


interface RumenzRepository extends JpaRepository<Rumenz, Long> {
List<Rumenz> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
// 为查询启用 distinct 标志 List<Rumenz> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname); List<Rumenz> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);
// 为单个属性启用忽略大小写 List<Rumenz> findByLastnameIgnoreCase(String lastname); // 为所有属性启用忽略大小写 List<Rumenz> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);
// 为查询启用静态 Order by List<Rumenz> findByLastnameOrderByFirstnameAsc(String lastname); List<Rumenz> findByLastnameOrderByFirstnameDesc(String lastname);}
复制代码


举一些例子



Repository 有 3 种


JpaRepository 继承 PagingAndSortingRepository,PagingAndSortingRepository 继承 CrudRepository。


  • CrudRepository 提供 CRUD 的功能

  • PagingAndSortingRepository 提供分页和排序功能

  • JpaRepository 提供 JPA 相关的方法,如刷新持久化数据、批量删除等。


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<User> listByName(String name);
Integer countByName(String name);
List<User> readDistinctByName(String name);
Page<User> 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 **/@Servicepublic 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<User> opt = userRepository.findById(id);
return opt.isPresent()?opt.get():null; }
@Override public List<User> listByName(String name) { List<User> res = userRepository.findDistinctUserByName(name); return res; }
@Override public Integer countByName(String name) { return userRepository.countUserByName(name); }
@Override public List<User> readDistinctByName(String name) {
return userRepository.readDistinctByName(name); }
@Override public Page<User> listByNamePage(String name, Integer page, Integer pageSize) {
Sort sort = Sort.by("id").descending(); Pageable pageable= PageRequest.of(page-1, pageSize, sort); Page<User> res = userRepository.findAllByName(name, pageable); return res; }}
复制代码

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<User> 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<User> readDistinctByName(@RequestParam("name") String name){ return userService.readDistinctByName(name); }
//分页查询 //带条件查询 @GetMapping("/listByNamePage") public Page<User> listByNamePage(@RequestParam("name") String name, @RequestParam("page") Integer page, @RequestParam("pageSize") Integer pageSize){ return userService.listByNamePage(name,page,pageSize); }
}
复制代码


本小结源码地址:


  • 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 开发手册

发布于: 刚刚阅读数: 2
用户头像

入门小站

关注

还未添加个人签名 2020.01.18 加入

还未添加个人简介

评论

发布
暂无评论
第十五节:SpringBoot使用JPA访问数据库