springboot学习第5期 - spring data jpa

spring data jpa 简化了数据库操作,在国外比较受欢迎,国内用的比较多的是 mybatis-plus。

引入依赖

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

<dependency>
  <groupId>com.mysql</groupId>
  <artifactId>mysql-connector-j</artifactId>
  <scope>runtime</scope>
</dependency>

配置

properties 复制代码
spring.datasource.url=jdbc:mysql://localhost:3306/helloword
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

上面 4 个属性就不多讲了,讲一下下面三个配置属性。

  • spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect

Hibernate 为不同的数据库类型提供了翻译器,如果你使用的是 mysql 8.x,则声明为 MySQL8Dialect,不写的话可能会导致兼容性问题。

  • spring.jpa.hibernate.ddl-auto=update

自动更新表结构,但不会删除表数据。

具体表现如下:

场景 Hibernate 会做什么
表不存在 自动创建表
表存在但字段不匹配 自动添加缺失的列
字段类型变化 尝试修改类型(可能失败,取决于数据库)
删除实体类里的字段 不会删除数据库中的列(安全)

还有其他取值:

取值 作用(启动时 Hibernate 对数据库表结构的处理) 常用场景
none 什么都不做,不检查也不修改表结构。 生产环境默认推荐
validate 只校验实体类字段和表是否匹配,不匹配就抛异常。 生产/测试,防止意外改表
update 自动更新表结构 开发/调试
create 先删所有表,再重新创建(数据全丢)。 单元测试或快速原型
create-drop 启动时 create,应用退出时再全部删表 一次性演示/集成测试
  • spring.jpa.show-sql=true

控制台会打印sql,生产环境建议关闭。

定义表结构

定义如下的对象,当程序启动后,会自动创建 tbl_user 表,不需要自己手动写sql语句。

java 复制代码
@Data
@Entity
@Table(name = "tbl_user")
public class UserDo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private Integer age;
}

主键策略 GenerationType.IDENTITY 的意思是: 把主键的生成完全交给数据库的自增机制(MySQL 的 AUTO_INCREMENT),JPA/Hibernate 执行 INSERT 时 ,而是等数据库成功插入后,再把数据库生成的主键值 取出来回填到实体对象的 id 字段。

唯一约束 和 非null 约束

可以给字段添加唯一约束 和 非null 约束。

java 复制代码
@Column(unique = true, nullable = false)
private String name;

注意,如果表和字段已经存在,再重新设置唯一约束和非null约束,是不会生效的,所以最好创建的时候就确定好,生产环境一般会使用 flyway 固化sql

字符长度设置

默认 String 类型的长度是 varchar(255),可以自定义它的长度。

java 复制代码
@Column(length = 512)
private String email;

实际生产中还是会结合 flyway 手写sql定义表结构,所以定义表结构的很多用法,了解即可。

定义Repository

java 复制代码
public interface UserRepository extends JpaRepository<UserDo, Long> {
}

JpaRepository 内部已经自带了常用的sql操作,比如根据id查询,查询所有数据;也可以自己添加一些操作,不用手写sql,jpa有一套规则,会自动生成sql。

java 复制代码
public interface UserRepository extends JpaRepository<UserDo, Long> {

    UserDo findByName(String name);

}

规则有如下:

关键字 示例方法名 生成的 SQL 片段
And findByNameAndAge where name = ? and age = ?
Or findByNameOrAge where name = ? or age = ?
Is / Equals findByNameIs where name = ?
IsNot findByNameIsNot where name <> ?
Like findByNameLike where name like ?
NotLike findByNameNotLike where name not like ?
StartingWith findByNameStartingWith where name like 'xxx%'
EndingWith findByNameEndingWith where name like '%xxx'
Containing findByNameContaining where name like '%xxx%'
LessThan findByAgeLessThan where age < ?
LessThanEqual findByAgeLessThanEqual where age <= ?
GreaterThan/GreaterThanEqual findByAgeGreaterThan where age > ?
Between findByAgeBetween where age between ? and ?

使用 Repository

java 复制代码
@RestController
@RequestMapping("/api/hello")
@Validated
@RequiredArgsConstructor
public class HelloController {

    private final UserRepository userRepository;

    @GetMapping
    public List<UserDo> hello() {
        return userRepository.findAll();
    }
}

审计功能

审计就是什么人再什么时间点删除/修改了记录。

spring data jpa 支持 创建时间,修改时间,创建人,修改人 这几个审计字段。

开启审计

再主类上添加注解 @EnableJpaAuditing 即可。

审计父类

实际使用的时候可以将审计字段抽离出来:

java 复制代码
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class AuditableEntity {

    @CreatedDate
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime updatedAt;

    @CreatedBy
    private String createdBy;

    @LastModifiedBy
    private String updatedBy;
}

实际使用可以继承这个类:

java 复制代码
@Entity
@Getter
@Setter
@Table(name = "tbl_user")
public class UserDo extends AuditableEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;

    private String passwordHash;

    private String email;
}

其中创建者和修改者,需要定义填充规则:

java 复制代码
@Component
public class AuditorAwareImpl implements AuditorAware<String> {
    @Override
    public Optional<String> getCurrentAuditor() {
        // 示例:从 SecurityContext 拿登录人
        return Optional.of("system");
    }
}

软删除

软删除就是数据库中有个字段专门标记是否被删除,而不是直接删除记录。

首先表中先定义一个字段表示是否删除,比如 is_deleted,然后可以在审计类中,添加下面这行即可:

java 复制代码
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@SoftDelete(columnName = "is_deleted")
public abstract class AuditableEntity {

    @CreatedDate
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime updatedAt;

    @CreatedBy
    private String createdBy;

    @LastModifiedBy
    private String updatedBy;
}

对于 is_deleted 为 true 的字段,正常查询是查不到的,除非自己自定义sql查询。

分页

自带分页功能,直接用就行:

java 复制代码
@GetMapping
public Page<UserDo> hello() {

    Pageable pageable = PageRequest.of(0, 1, Sort.by("id").descending());

    Page<UserDo> all1 = userRepository.findAll(pageable);

    return all1;
}

page = 0 是第1页,如果想和前端保持统一,数字1才是第1也,则传进后端的page参数减去1再调用api即可。

特殊场景,需要结合其他条件进行分页,只要参数带上 pageable 就好了。

java 复制代码
public interface UserRepository extends JpaRepository<User, Long> {

    // 1) 自带分页
    Page<User> findAll(Pageable pageable);

    // 2) 带条件的分页
    Page<User> findByUsernameContaining(String keyword, Pageable pageable);
}

主类上可以添加 @EnableSpringDataWebSupport(pageSerializationMode = EnableSpringDataWebSupport.PageSerializationMode.VIA_DTO),否则Controller直接返回Page的实现类会出现告警

多表查询

待补充

相关推荐
谢平康10 小时前
支持不限制大小,大文件分段批量上传功能(不受nginx /apache 上传大小限制)
java·vue.js·spring boot
DanB2412 小时前
Spring-boot实战demo
spring boot
灵犀学长13 小时前
Spring Boot Jackson 序列化常用配置详解
java·spring boot·后端
midsummer_woo15 小时前
基于springboot+vue+mysql智能推荐的卫生健康系统(源码+论文+开题报告)
vue.js·spring boot·mysql
天天进步201515 小时前
Spring Boot 3.0新特性全面解析与实战应用
spring boot
余很多之很多16 小时前
基于 Spring Boot、Spring Cloud、Nacos 的微服务架构,在性能测试下的层层优化
spring boot·spring cloud·架构
CodeWolf17 小时前
SpringBoot自动化配置原理
spring boot·spring
simplejian17 小时前
从零实现一个在线GIT平台并一文道尽git
spring boot·git
老友@17 小时前
Spring Boot 集成 RabbitMQ:普通队列、延迟队列与死信队列全解析
spring boot·消息队列·rabbitmq·java-rabbitmq·死信队列·延时队列