本篇要點
-
簡單介紹JPA。
-
介紹快速SpringBoot快速整合JPA
JPA是啥?
The Java Persistence API is a standard technology that lets you “map” objects to relational databases. The spring-boot-starter-data-jpa POM provides a quick way to get started.
- JPA是
The Java Persistence API
標准,Java持久層API,是一種能讓對象能夠快速映射到關系型數據庫的技術規范。 - JPA只是一種規范,它需要第三方自行實現其功能,在眾多框架中
Hibernate
是最為強大的一個。
Spring Data JPA
Spring Data JPA
是采用基於JPA規范的Hibernate
框架基礎下提供了Repository
層的實現。Spring Data Repository
極大地簡化了實現各種持久層的數據庫訪問而寫的樣板代碼量,同時CrudRepository
提供了豐富的CRUD功能去管理實體類。SpringBoot框架為Spring Data JPA提供了整合,spring-boot-starter-data-jpa
能夠讓你快速使用這門技術,它提供了以下依賴。
- Hibernate:最流行的JPA實現之一。
- Spring Data JPA:幫助你去實現JPA-based repositories。
- Spring ORM:Spring Framework提供的核心ORM支持。
快速SpringBoot快速整合JPA
引入依賴
<!--SpringBoot對jpa的封裝-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--mysql驅動,8.x版本-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
配置yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/jpa?serverTimezone=GMT%2B8
username: root
password: 123456
hikari:
maximum-pool-size: 20
minimum-idle: 5
jpa:
#在建表的時候,將默認的存儲引擎切換為 InnoDB
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
# 配置在日志中打印出執行的 SQL 語句信息。
show-sql: true
# 配置指明在程序啟動的時候要刪除並且創建實體類對應的表。
hibernate:
ddl-auto: create #update
值得注意的是:spring.jpa.hibernate.ddl-auto
第一建表的時候可以create,指明在程序啟動的時候要刪除並且創建實體類對應的表。后續使用就需要改為update。
ddl-auto的幾種屬性值
- create:每次加載hibernate時都會刪除上一次的生成的表,再重新根據model生成表,因此可能會導致數據丟失。
- create-drop :每次加載hibernate時根據model類生成表,但是sessionFactory一關閉,表就自動刪除。
- update:最常用的屬性,第一次加載hibernate時根據model類會自動建立起表的結構(前提是先建立好數據庫),以后加載hibernate時根據 model類自動更新表結構,原有數據不會清空,只會更新。
- validate :每次加載hibernate時,會校驗數據與數據庫的字段類型是否相同,字段不同會報錯。
實體類
JPA規范定義在javax.persistence
包下,注意導包的時候不要導錯。
@Entity(name = "t_user")
@Data
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
@Transient
private String email;
}
-
@Entity標注保證實體能夠被SpringBoot掃描到,對應表名為
t_user
。 -
@Id表明id。
-
@GeneratedValue中標注主鍵生成策略。
-
@Transient表示不需要映射的字段。
常見的主鍵生成策略
- TABLE: 使用一個特定的數據庫表格來保存主鍵
- SEQUENCE: 根據底層數據庫的序列來生成主鍵,條件是數據庫支持序列。這個值要與generator一起使用,generator 指定生成主鍵使用的生成器(可能是orcale中自己編寫的序列)。
- IDENTITY: 主鍵由數據庫自動生成(主要是支持自動增長的數據庫,如mysql)
- AUTO: 主鍵由程序控制,也是GenerationType的默認值。
啟動項目,生成表
首先在數據庫中創建jpa庫,庫名無所謂,和配置對應上就可以。
啟動項目,你會發現控制台輸出日志如下:
Hibernate: drop table if exists t_user
Hibernate: create table t_user
(id bigint not null auto_increment, password varchar(255), username varchar(255), primary key (id)) engine=InnoDB
此時我們配置的create效果已經顯現,我們之后將它改為update,不然每次啟動程序,數據表又得重建咯。
數據訪問層
Spring Data JPA repositories是你可以定義訪問數據的接口,JPA查詢是根據你的方法名稱自動創建的。
這里我們編寫一個接口,繼承JpaRepository即可。User是對象名,不是表名,Long為主鍵的類型。
public interface UserDao extends JpaRepository<User, Long> {
/**
* 根據用戶名和密碼查詢用戶
*/
User findByUsernameAndPassword(String username, String password);
}
JPA默認支持常見的增刪改查,也支持findByUsernameAndPassword
這種以字段命名的方法,對於更復雜的查詢,您可以使用Spring Data的Query注解對方法進行注解。
命名規范與對應SQL
Keyword | Sample | JPQL snippet |
---|---|---|
Distinct |
findDistinctByLastnameAndFirstname |
select distinct … where x.lastname = ?1 and x.firstname = ?2 |
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.firstname) = UPPER(?1) |
測試JPA
@SpringBootTest
class SpringBootJpaApplicationTests {
@Resource
UserDao userDao;
@Test
void testJPA() {
User user = userDao.save(new User(null, "summerday", "123456", "hangzhou"));
System.out.println("添加用戶: " + user);
User u = userDao.findByUsernameAndPassword("summerday", "123456");
System.out.println("根據用戶名和密碼查詢用戶: " + u);
long count = userDao.count();
System.out.println("當前用戶數量: " + count);
PageRequest page = PageRequest.of(0, 5, Sort.by(Sort.Order.desc("id")));
Page<User> all = userDao.findAll(page);
System.out.println("分頁 + 根據id逆序 查詢結果: " + all.getContent());
if(userDao.existsById(u.getId())) {
userDao.deleteById(u.getId());
System.out.println("刪除id為" + u.getId()+ "的用戶成功");
}
long c = userDao.count();
System.out.println("剩余用戶數為: " + c);
}
}
控制台輸出如下:
源碼下載
本文內容均為對優秀博客及官方文檔總結而得,原文地址均已在文中參考閱讀處標注。最后,文中的代碼樣例已經全部上傳至Gitee:https://gitee.com/tqbx/springboot-samples-learn,另有其他SpringBoot的整合哦。