如果餓了就吃,困了就睡,渴了就喝,人生就太無趣了
源碼地址:https://github.com/keer123456789/springbootstudy/tree/master/jpa_demo
本人剛剛接觸jpa,如有錯誤,歡迎大家指正!!
1.JPA介紹
JPA(Java Persistence API)Java持久化API,是 Java 持久化的標準規範,Hibernate是持久化規範的技術實現,而Spring Data JPA是在 Hibernate 基礎上封裝的一款框架。JPA作爲標準,實際上並沒有說侷限於某個固定的數據源,事實上mysql,mongo, solr都是ok的。接下來我們將介紹下springboot結合jpa 來實現mysql的curd以及更加複雜一點的sql支持
2.環境配置
2.1 數據庫配置
數據庫選擇mysql
數據庫。並新建一個數據庫jpademo1
。如圖
2.2 SpringBoot pom 配置
mysql
依賴中的版本根據自己的mysql
版本配置。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
2.3 MySQL數據源配置
mysql的基本配置,不再過多解釋。
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/jpademo?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
2.4 jpa配置
每個屬性的解釋都在註釋中,
spring.jpa.show-sql
建議開啓,這個會在日誌中打印sql語句,對之後的調試很有幫助。- ddl-auto:update 每次運行程序,沒有表格會新建表格,表內有數據不會清空,只會更新
# JPA配置
spring.jpa.database=mysql
# 在控制檯打印SQL
spring.jpa.show-sql=true
# 數據庫平臺
spring.jpa.database-platform=mysql
# 每次啓動項目時,數據庫初始化策略
spring.jpa.hibernate.ddl-auto=update
# 指定默認的存儲引擎爲InnoDB
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
3.Entity介紹
JPA提供了實體與庫表的映射關係。只需要使用@Entity
註解即可。
@Entity
- 聲明這個POJO是一個與數據庫中叫做
user
的表關聯的對象. - 參數name,用於指定表名,如果不主動指定時,默認用類名,即上面如果不指定那麼,那麼默認與表 user 綁定
- 聲明這個POJO是一個與數據庫中叫做
@Column
- 這個註解就是用來解決我們pojo成員名和數據庫列名不一致的問題的
- name參數填寫表名
- nullable參數是表示該列是否可以爲空
- 主鍵註解
@Id
註解 表示這個列是主鍵,關係型數據中很重的。@GeneratedValue
設置初始值,談到主鍵,我們一般會和”自增“這個一起說,所以你經常會看到的取值爲strategy = GenerationType.IDENTITY
(由數據庫自動生成)
這個註解提供了四種形式,關於這幾種使用姿勢,這裏不詳細展開了,有興趣的可以可以看一下這博文: @GeneratedValue
取值 | 說明 |
---|---|
GenerationType.TABLE |
使用一個特定的數據庫表格來保存主鍵 |
GenerationType.SEQUENCE |
根據底層數據庫的序列來生成主鍵,條件是數據庫支持序列 |
GenerationType.IDENTITY |
主鍵由數據庫自動生成(主要是自動增長型) |
GenerationType.AUTO |
主鍵由程序控制 |
@Entity(name = "user")
public class User {
@Column(name = "name", nullable = false)
private String name;
@Column(name = "password", nullable = false)
private String password;
@Column(name = "address", nullable = false)
private String address;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
public User() {
}
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;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
", address='" + address + '\'' +
", id=" + id +
'}';
}
}
4.增刪改查
jpa只需要繼承一個接口即可完成DB的操作。這次繼承的CrudRepository類。這樣就可以實現很多操作。
@Component
public interface UserDao extends CrudRepository<User, Integer> {
}
4.1 Select
由於繼承了CrudRepository
接口,這個接口提供了三個查詢方法,如圖
- 查詢表中所有
User
信息 - 根據主鍵查詢相應的
User
- 根據一組主鍵查詢相應的信息。
這單單是此接口實現的根據主鍵查詢的方法,jpa具有強大的查詢功能,實現了GroupBy,having
等等高級的sql查詢功能,這些功能會在之後的博客中介紹……
這次簡單的介紹findAll()
的功能。在Service層進行查詢。查尋完成之後返回給controller
,即可,webResult
返回請求的自定義的值。具體的就不在介紹,可以自行去項目中查看。
public WebResult selectAllUsers(){
List<User> users= (List<User>) userDao.findAll();
WebResult webResult=new WebResult();
webResult.setStatus(WebResult.SUCCESS);
webResult.setMessage("查詢成功");
webResult.setData(users);
logger.info("查詢成功,數據:"+users.toString());
return webResult;
}
如圖,可以看到查詢語句
數據庫中的數據和日誌打印出來的數據:
4.2 Insert
1.插入單個數據
public WebResult addUser(User user) {
User res = userDao.save(user);
WebResult result = new WebResult();
if (res != null) {
result.setData(user);
result.setMessage("增加成功");
result.setStatus(WebResult.SUCCESS);
return result;
}
return null;
}
- 調用接口的
save()
方法。入參是需要增加的User信息
進行測試:
測試數據:
#增加用戶信息
POST http://127.0.0.1:8080/jpa/addUser
Content-Type: application/json
{
"id": 4,
"name": "keer",
"password": "133333",
"address": "北京市平谷區"
}
測試結果:
- 先根據id進行查詢(防止主鍵重複,這是一種可能,原因在update的時候在深入解釋)。
- 然後在進行插入操作
2.批量插入
同樣是調用接口已經有的方法,saveAll()
方法,入參是User的list數組
public WebResult addUsers(List list) {
WebResult webResult = new WebResult();
userDao.saveAll(list);
List<User> failUsers = new ArrayList<>();
for (Object o : list) {
User user = (User) o;
if (!userDao.existsById(user.getId())) {
failUsers.add(user);
}
}
if (failUsers.size() == 0) {
webResult.setStatus(WebResult.SUCCESS);
webResult.setMessage("插入成功");
} else {
webResult.setMessage("部分插入失敗");
webResult.setData(failUsers);
webResult.setStatus(WebResult.ERROR);
}
return webResult;
}
進行測試:
測試數據:
#批量增加用戶
POST http://127.0.0.1:8080/jpa/addUsers
Content-Type: application/json
[
{
"name": "可耳",
"password": "love",
"address": "北京市"
},
{
"name": "java",
"password": "hello world",
"address": "main()"
}
]
測試結果:
- 這次沒有指明主鍵id,因爲是自增主鍵,所以就自動生成了
- 日誌中的select語句,是因爲調用了
existsById()
方法進行查詢是否存在。
4.3 Delete
刪除操作直接調用接口中的delete()
方法,入參是user實例
public WebResult removeUser(User user) {
userDao.delete(user);
WebResult webResult = new WebResult();
if (!userDao.existsById(user.getId())) {
webResult.setStatus(WebResult.SUCCESS);
webResult.setMessage("刪除用戶信息成功!");
} else {
webResult.setStatus(WebResult.ERROR);
webResult.setMessage("刪除用戶信息失敗!");
}
return webResult;
}
進行測試:
測試數據:
#刪除用戶
POST http://127.0.0.1:8080/jpa/deleteUser
Content-Type: application/json
{
"name": "java",
"password": "hello world",
"address": "main()",
"id": 6
}
測試結果:
- 日誌中首先使用主鍵進行了查詢
- 之後再進行刪除
- 日誌中的select語句,是因爲調用了
existsById()
方法進行查詢是否存在。
4.4 Updata
1.使用save()
方法,數據必須帶有主鍵,而且需要user中帶有全部數據,這樣才能進行update。
public WebResult updateUser(User user) {
WebResult webResult = new WebResult();
User newUser = userDao.save(user);
logger.info("更新信息:" + newUser.toString());
webResult.setMessage("更新操作成功");
webResult.setData(newUser);
webResult.setStatus(WebResult.SUCCESS);
return webResult;
}
進行測試:
測試數據:
POST http://127.0.0.1:8080/jpa/updateUser
Content-Type: application/json
{
"id": 1,
"name": "keer",
"password": "133333",
"address": "北京市平谷區"
}
測試結果:
- 日誌中首先使用主鍵進行了查詢(回答上面的問題,查詢這個id對應的記錄是否存在,存在就是update,不存在就是insert)