乐趣区

关于springboot:第十五节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_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

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;
}

@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<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);
}

举一些例子

关键字 办法示例 JPQL snippet
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is, Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull, Null findByAge(Is)Null … where x.age is null
IsNotNull, NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (parameter bound with appended %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (parameter bound with prepended %)
Containing findByFirstnameContaining … where x.firstname like ?1 (parameter bound wrapped in %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection ages) … where x.age not in ?1
True findByActiveTrue() … where x.active = true
False findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

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
 **/
@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<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/spr…
  • Gitee:https://gitee.com/rumenz/spri…
  • https://rumenz.com/rumenbiji/…

介绍

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

  • 关注【入门小站】回复【1001】获取 linux 常用命令速查手册
  • 关注【入门小站】回复【1003】获取 LeetCode 题解【java 语言实现】
  • 关注【入门小站】回复【1004】获取 Java 根底外围总结
  • 关注【入门小站】回复【1009】获取 阿里巴巴 Java 开发手册
退出移动版