Spring Boot与数据访问一–Spring Data介绍
Spring Boot与数据访问二–使用原生JDBC及源码解析
Spring Boot与数据访问三–整合Druid
Spring Boot与数据访问四–整合MyBatis(注解版)
Spring Boot与数据访问五–整合MyBatis(配置版)
Spring Boot与数据访问六–整合JPA
Spring Boot与数据访问七–多数据源
一、引入JPA
可以在一开始创建项目的时候就勾选JPA模块
也可以直接在pom.xml文件中添加配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
用图表的方式来看下这个starter引入了哪些依赖(在pom.xml文件中右击鼠标):
二、整合SpringData JPA
JPA基于ORM(Object Relational Mapping 即对象关系映射)思想
1、编写一个实体类(bean)和数据表进行映射并配置好映射关系
package com.huiq.springboot.entity;
import javax.persistence.*;
// 使用JPA注解配置映射关系
@Entity // 告诉JPA这是一个实体类(和数据表映射的类)
@Table(name = "tbl_user") // @Table来指定和哪个数据表对应;如果省略默认表名是user;
public class User {
@Id // 这是一个主键
@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增主键
private Integer id;
@Column(name = "na_me", length = 50) // 这是和数据表对应的一个列
private String name;
@Column // 省略默认列名就是属性名
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2、编写一个Dao接口来操作实体类对应的数据表(Repository)
package com.huiq.springboot.repository;
import com.huiq.springboot.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
// 继承JpaRepository来完成对数据库的操作
public interface UserRepository extends JpaRepository<User,Integer> {
}
3、编写一个Controller
package com.huiq.springboot.controller;
import com.huiq.springboot.entity.User;
import com.huiq.springboot.repository.UserRepository;
import org.hibernate.criterion.Example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
@RestController
public class UserController {
@Autowired
UserRepository userRepository;
@GetMapping("/user/{id}")
public User getUser(@PathVariable("id") Integer id) {
Optional<User> user = userRepository.findById(id);
return user.get();
}
@GetMapping("/user")
public User insertUser(User user) {
User save = userRepository.save(user);
return save;
}
}
注:findOne()方法的替代方法findById()
2.0版本之前
T findOne(ID primaryKey);
2.0版本
Optional<T> findById(ID id);
Optional findById(ID id)中Optional的一些用法:
1)如果没找到指定实体,则返回一个默认值。
User user = repository.findById(id)
.orElse(new User());
或者
User user = repository.findById(id)
.orElse(null);
2)如果找到实体返回它,否则抛出异常
return repository.findById(id)
.orElseThrow(() -> new EntityNotFoundException(id));
3)假设希望根据是否找到实体来应用不同的处理(无需抛出异常)
Optional<User> userOptional = repository.findById(id);
if (userOptional.isPresent()){
User user = userOptional.get();
// 处理 user ...
}
else{
// 另一种情况....
}
4、application.yml
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/database1
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
filters: stat,wall
jpa:
hibernate:
# 更新或者创建数据表结构
ddl-auto: update
# 控制台显示SQL
show-sql: true
注:ddl-auto的几个常用属性值:
- none:默认值,什么都不做,每次启动项目,不会对数据库进行任何验证和操作
- create:每次加载hibernate,重新创建数据库表结构,这就是导致数据库表数据丢失的原因
- create-drop:加载hibernate时创建,退出时(如果表不存在报错)执行一下drop
- update:这个操作启动的时候会去检查schema是否一致,如果不一致会做scheme更新,每次运行程序,没有表会新建表,但是表内有数据不会被清空,只会更新表结构。
- validate:启动时验证现有schema与你配置的hibernate是否一致,如果不一致就抛出异常,并不做更新
实际项目中update用的多一点,即使表结构改变了,表中的行仍然存在,不会删除以前的行,只更新对象关系的变化,不会清空数据。
需要注意的是,如果你不打算在设计表的时候强制加表级别的外键关系约束,就自己手动建表,然后不设置 jpa.hibernate.ddl-auto 或者设置它的值为 none。
因为使用 update 更新表,每次启动 @OneToOne、@OneToMany 等注解会检查表的外键关系,然后强制建立表外键约束,这个很烦人。
5、启动程序测试
该表目前状态
启动程序并访问
注意:网上有的说JPA写一些复杂查询(如多表关联查询)非常不友好。