Spring Boot JPA

提到JPA操作数据库,有的人惊叹于它的简洁与强大,有些人则会觉得不够灵活,影响实战效率,那么究竟JPA为何让人又爱又恨呢?

一 原理 战前磨刀

01.认识 JPA

JPA-Java Persistence API,即Java持久化API

总得来说,JPA 为对象关系映射提供了⼀种基于 POJO 的持久化模型

简化数据持久化代码的开发⼯作

为 Java 社区屏蔽不同持久化 API 的差异

而我们常说的Hibernate又是什么呢?它其实是JPA的一种实现

02. 认识 Spring Data

以前,Spring只是在内部实现了支持JDBC、JPA等的方式。后来,Spring将所有对于数据操作的工具都整理在了Spring Data中,Spring Data 在保留底层存储属性的同时,提供相对一致的、基于Spring的编程模型。

主要模块:

Spring Data JPA

Spring Data JDBC

Spring Data Redis

Spring Data MongoDB

03. 认识 Spring Data JPA

Spring Data JPA,即Spring对JPA的封装。

官网上讲:Spring Data JPA旨在通过将工作量减少到实际需要的数量,来显著改善数据访问层的操作

作为开发人员,你只需要写你的repository接口,包括自定义的方法,Spring会自动提供实现

04. 常用的jpa实体类注解

通过JPA提供的一些实体类注解,我们可以配置一个对应的表,从而在程序运行时,JPA可以自动实现为我们建表的工作

常见的JPA实体类注解如下:

实体

  • @Entity
  • @MappedSuperclass
  • @Table(name)

@Entity与@MappedSuperclass都是声明实体类的注解。

@Entity表示所声明的实体类里面定义的所有属性,均与对应的表关联

@MappedSuperclass表示所注解的类为一个父类,子类可以通过继承该父类来扩展自己的属性

@Table(name),表明该实体类与数据库中的某个表关联

主键

  • @Id
  • @GeneratedValue(strategy, generator)
  • @SequenceGenerator(name, sequenceName)

@Id和**@GeneratedValue**常常组合起来,用于主键声明,并指定主键生成策略和生成器(若不指定,JPA会根据所引入驱动依赖的数据库进行默认策略的设置)

@SequenceGenerator注解,表示主键会采用系列号的方式生成

映射

  • @Column(name,nullable,length,insertable,updatable)
  • @JoinTable(name) @JoinColumn(name)

均用在属性上。@Column指定一个属性所映射的字段信息

若存在外键,可以使用**@JoinTable(name)** **@JoinColumn(name)**组合进行定义

关系

  • @OneToOne @OneToMany
  • @ManyToOne @ManyToMany
  • @OrderBy

前四个注解用在属性上,分别表示表与该属性的对应关系。

@OrderBy同样使用在属性上,表示**@oneToMany以及@ManyToMany**,即一对多或者多对多时,字段的排序方式

05. Repository介绍

加上**@EnableJpaRepositories**,即可开启JPA的repository的支持,Spring 就会发现以下repository的扩展

  • CrudRepository<T, ID> 提供基本增删改查方法
  • PagingAndSortingRepository<T, ID> 用于分页、排序方法
  • JpaRepository<T, ID> 用于持久化等方法

06. 查询方式

1 ) 根据方法名定义查询

查询方法,默认只提供了查询所有或者按照ID查询的方法。

若想要查询更丰富的内容,比如按照某个条件查询、统计记录数、排序展示、多条件查询、查询第一条或最后一条等,这么多复杂的场景,依旧不需要写sql,我们只需要在repository中定义如下格式的方法就可以轻而易举的实现啦~

• find…By… / read…By… / query…By… / get…By…

• count…By…

• …OrderBy…[Asc / Desc]

• And / Or / IgnoreCase

• Top / First / Distinct

2) 分页查询

• PagingAndSortingRepository<T, ID>

• Pageable / Sort

• Slice / Page

要想实现分页查询,可以使用PagingAndSortingRepository接口,与Pagable/Sort类相配合,即可实现分页查询

二 实战 实战环节

对原理有个大概的了解,接下来,就进入今天的实战环节啦~

本次实战依旧演示操作mysql数据库。

01. 引入依赖

只需要引入spring-data-jpa和mysql驱动两个主要依赖。

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<scope>runtime</scope>

</dependency>

02. 属性配置

分别进行数据库连接信息以及jpa的相关信息配置

以下分别为大家演示了jpa的建表机制、是否打印sql语句以及是否格式化sql语句显示这3个常用的配置项

#1、数据库连接信息配置

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8

spring.datasource.username=root

spring.datasource.password=123456

#可以不用配置数据库驱动,SpringBoot 会根据引入的依赖进行自动配置

#spring.datasource.driver-class-name=com.mysql.jdbc.Driver

#2、jpa配置信息

#建表机制

#create-drop - 运行程序新建,程序结束:删表

#create -运行程序会新建表,程序结束:表的数据会清空

#update - 没有表格时会新建表格,表内有数据不会清空,只会更新,

#valid - 运行程序会校验数据与数据库的字段类型是否相同,不同会报错

spring.jpa.hibernate.ddl-auto=update

#打印sql开关

spring.jpa.properties.hibernate.show_sql=true

#是否格式化sql

spring.jpa.properties.hibernate.format_sql=true

其中,JPA的建表机制分为四种,注释中已标出,大家可以按照实际需求,选择不同机制,一般情况建议选择update机制,比较完善,也不用怕每次清空了表或者数据

03. 创建实体类

根据我们在战前准备中所介绍的实体类的注解,我们建立好的实体类User如下:

@Entity

@Table(name = "USER")

@Builder

@Data

@NoArgsConstructor

@AllArgsConstructor

public class User implements Serializable {

@Id

@GeneratedValue

private Long id;

private String name;

@Column(updatable = false)

@CreationTimestamp

private Date createTime;

@UpdateTimestamp

private Date updateTime;

}

首先使用**@Entity与@Table(name="USER")**组合,表明该实体类与数据库中的user表关联;

@Id与@GeneratedValue组合,表明字段id被映射为主键,JPA会根据引入的数据库依赖,来配置对应的主键生成策略。

而属性createTime,分别使用注解**@Column(updatable=false)和@CreationTimestamp**表示它不可被修改,且对应表中字段的值默认为插入对应记录的时间;

注解**@UpdateTimestamp**则表示,属性updateTime会自动变为对应行记录的更新时间

04. 创建repository

创建自己的UserRepository接口,并实现CrudRepository

public interface UserRepository extends CrudRepository<User,Long> {

List<User> findByNameOrderByCreateTimeDesc(String name);

}

05. 调用repository方法

1)开启jpa的repossitory注解

在启动类上添加注解:

@EnableJpaRepositories

2)注入自定义的Repository

3) 调用具体数据库操作方法

@SpringBootApplication

@Slf4j

@EnableJpaRepositories

public class SpringBootJpaApplication implements ApplicationRunner {

@Autowired

private UserRepository userRepository;

@Override

public void run(ApplicationArguments args) throws Exception {

User user = User.builder()

.name("小米")

.createTime(new Date())

.updateTime(new Date())

.build();

userRepository.save(user);

log.info("one user added :{}",user);

Iterable<User> users = userRepository.findAll();

users.forEach(System.out::println);

}

  1. 运行项目

通过运行项目,我们可以通过打印出的sql语句看到,JPA在服务启动时,分别为我们创建了对应于实体类User的user表,并生成了序列化主键id

接着执行了数据库的插入操作,成功插入一条数据

最后,执行数据库的查询语句,查询出我们所添加的一条user记录

回顾一下,我们的主要的操作其实就只是实现了@CrudRepository接口,然后直接调用其方法,就可以操作数据库了

那么,简单的数据库操作就实现啦~

庆祝一会儿,然后开始接下来的进阶操作

我们试着自定义一个查询方法根据姓名查询,并以CreateTime降序排序的方法:

findByNameOrderByCreateTimeDesc(String name)

调用,并运行服务之后,结果如下:

打印出的sql语句表示:根据姓名查询,并以CreateTime降序排序

相应地,如果要定义其他查询方法,只需要直接在自定义的Repository中直接按照第一节中的方法定义规则进行定义即可,具体规则可以查看包org.springframework.data.repository.query.parser中的各类,比如PartTree类:

Tips:

JPA也有专门的**@Query注解以及JPA Named Queries**,可以分别在方法上或者xml文件中自定义sql,实现更多操作场景,感兴趣的话,大家可以参考官网查看哦~

三 总结 总而言之

相对于Mybatis来说,我们可以看到,JPA不知方便多少倍了。它可以说是真正意义上的ORM框架,有以下两大优势:

I.直接可以通过实体类与表、实体属性与表的字段之间的关联,自动为我们建表

II.使用时不需要再考虑使用的是何种数据库,也基本不需要写sql语句

大大解放了 coding的劳动人民!有木有

但是呢,正如我们所看到的那样,正因为JPA将ORM封装的太完善了,使得我们操作数据库的灵活性大大降低了。比如我们如果想要实现多表关联的查询、多条件查询等等,都会变得更加复杂

所以,项目中要想使用JPA,一定得预先根据项目实际需求,来权衡这些特点

恭喜你,又get到了几个技能点:

1、JPA、Spring DATA的定位与功能

2、Spring DATA JPA操作数据库的方式

3、JPA让人又爱又恨的原因

嗯,就这样。每天学习一点,时间会见证你的成长

以上是 Spring Boot JPA 的全部内容, 来源链接: utcz.com/a/19599.html

回到顶部