Spring?Data?JPA實(shí)現(xiàn)數(shù)據(jù)持久化過(guò)程詳解
Spring Data JPA是一個(gè)流行的Java持久化框架,它在Java應(yīng)用程序中提供了一種簡(jiǎn)單、一致和易于使用的方式來(lái)訪問(wèn)各種數(shù)據(jù)庫(kù)。由于它的簡(jiǎn)單性和強(qiáng)大的功能,它已經(jīng)成為許多開(kāi)發(fā)人員的首選框架。通過(guò)使用Spring Data JPA,開(kāi)發(fā)人員可以更快地開(kāi)發(fā)應(yīng)用程序,減少代碼量,提高代碼的可讀性和可維護(hù)性。本文將介紹Spring Data JPA的基本概念和用法,并提供一個(gè)完整的實(shí)例,幫助您更好地理解它的使用方法和優(yōu)勢(shì)。
什么是Spring Data JPA
Spring Data JPA是Spring Framework的一個(gè)子項(xiàng)目,它提供了一種易于使用的方式來(lái)訪問(wèn)各種關(guān)系型數(shù)據(jù)庫(kù)的數(shù)據(jù)。它通過(guò)將JPA(Java Persistence API)和Spring Framework的強(qiáng)大功能相結(jié)合,簡(jiǎn)化了數(shù)據(jù)庫(kù)訪問(wèn)的復(fù)雜性,并提供了許多特性和工具,如基于注解的Repository模型、自動(dòng)化查詢、分頁(yè)和排序支持、復(fù)雜查詢DSL等。
Spring Data JPA的歷史可以追溯到2011年,當(dāng)時(shí)SpringSource(Spring Framework的開(kāi)發(fā)公司)發(fā)布了一個(gè)名為“Spring Data JPA”的項(xiàng)目,旨在幫助開(kāi)發(fā)人員更好地利用JPA規(guī)范進(jìn)行數(shù)據(jù)持久化。此后,該項(xiàng)目得到了廣泛的應(yīng)用和認(rèn)可,并在不斷地發(fā)展和完善。目前,Spring Data JPA已成為Java開(kāi)發(fā)人員中最流行的持久化框架之一,廣泛應(yīng)用于各種企業(yè)級(jí)應(yīng)用程序和互聯(lián)網(wǎng)應(yīng)用程序中。
入門案例
準(zhǔn)備數(shù)據(jù)
CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `email` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; INSERT INTO `user` (`name`, `email`) VALUES ('劉德華', 'liudehua@qq.com'), ('張學(xué)友', 'zhangxueyou@qq.com'), ('黎明', 'liming@qq.com'), ('郭富城', 'guofucheng@qq.com'), ('梁朝偉', 'liangchaowei@qq.com');
添加依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
創(chuàng)建實(shí)體類
import lombok.Data; import javax.persistence.*; @Entity @Table(name = "user") @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private String name; @Column(nullable = false) private String email; }
使用JPA注解@Entity
和@Table
來(lái)標(biāo)記該類為實(shí)體類,并指定映射的表名。@Id
注解標(biāo)記了實(shí)體類中的唯一標(biāo)識(shí)符,@GeneratedValue
注解指定了主鍵生成策略。同時(shí),我們使用@Column
注解指定了實(shí)體類中的字段名以及是否允許為空。
@Column
注解
該注解可以應(yīng)用在實(shí)體類的屬性和Getter方法上。如果同時(shí)出現(xiàn)在屬性和Getter方法上,以Getter方法上的注解為準(zhǔn)。該注解的各個(gè)屬性含義如下:
- name:可選,用于指定數(shù)據(jù)庫(kù)表字段名,默認(rèn)值為屬性名。
- unique:可選,用于指定該字段是否唯一,默認(rèn)值為false。
- nullable:可選,用于指定該字段是否可空,默認(rèn)值為true。
- insertable:可選,用于指定在執(zhí)行INSERT操作時(shí)是否插入該字段的值,默認(rèn)值為true。
- updatable:可選,用于指定在執(zhí)行UPDATE操作時(shí)是否更新該字段的值,默認(rèn)值為true。
- columnDefinition:可選,用于指定該字段在數(shù)據(jù)庫(kù)中的實(shí)際類型,如VARCHAR(255)、INTEGER等。默認(rèn)情況下,根據(jù)屬性類型自動(dòng)生成。
- table:可選,用于指定該字段所在的表名,默認(rèn)值為主表。
- length:可選,用于指定該字段的長(zhǎng)度,僅在字段類型為字符串類型時(shí)生效,默認(rèn)值為255。
- precision:可選,用于指定該字段的精度,僅在字段類型為DECIMAL時(shí)生效,默認(rèn)值為0。
- scale:可選,用于指定該字段的小數(shù)位數(shù),僅在字段類型為DECIMAL時(shí)生效,默認(rèn)值為0。
@GeneratedValue
注解指定了主鍵生成策略。常見(jiàn)的主鍵生成策略有以下幾種:
GenerationType.IDENTITY:主鍵由數(shù)據(jù)庫(kù)自動(dòng)生成(適用于 MySQL、PostgreSQL 等關(guān)系型數(shù)據(jù)庫(kù))。
GenerationType.AUTO:JPA 自動(dòng)選擇合適的策略,根據(jù)底層數(shù)據(jù)庫(kù)自動(dòng)選擇主鍵生成策略。
GenerationType.SEQUENCE:通過(guò)序列生成主鍵(適用于 Oracle 數(shù)據(jù)庫(kù))。
GenerationType.TABLE:使用表模擬序列生成主鍵。
其中 GenerationType.IDENTITY 是最常用的主鍵生成策略,因?yàn)樗?jiǎn)單易用且性能不錯(cuò)。如果你使用的是 MySQL、PostgreSQL 等數(shù)據(jù)庫(kù),則建議使用 GenerationType.IDENTITY 生成主鍵。如果你使用的是 Oracle 數(shù)據(jù)庫(kù),則可以考慮使用 GenerationType.SEQUENCE 生成主鍵。如果你使用的是其他數(shù)據(jù)庫(kù),則可以根據(jù)具體情況選擇合適的主鍵生成策略。
創(chuàng)建Repository
public interface UserRepository extends JpaRepository<User,Long> { }
我們使用了JpaRepository
接口,該接口提供了許多常用的持久化操作,如增加、刪除、修改、查詢等。我們只需要繼承該接口,并指定實(shí)體類的類型和主鍵類型即可。
兩個(gè)泛型 ,一個(gè)寫實(shí)體類,一個(gè)寫主鍵類型
find{By|FirstBy|AllBy}[屬性名稱][查詢關(guān)鍵字][連接符][屬性名稱][查詢關(guān)鍵字]...
By
:表示該方法是一個(gè)查詢方法,緊隨其后的是查詢條件的屬性名稱。FirstBy
:表示查詢結(jié)果的第一條記錄。AllBy
:表示查詢所有符合條件的記錄。[屬性名稱]
:表示查詢條件的屬性名稱,屬性名稱要與實(shí)體類中的屬性名稱保持一致。[查詢關(guān)鍵字]
:表示查詢條件的關(guān)鍵字,如Equals
、GreaterThan
、LessThan
、IsNotNull
等。[連接符]
:表示連接條件的連接符,如And
、Or
等。
public interface UserRepository extends JpaRepository<User, Long> { // 查詢所有性別為男性的用戶 List<User> findByGender(String gender); // 查詢用戶名為指定值的用戶 User findByUsername(String username); // 查詢用戶名和密碼都匹配的用戶 User findByUsernameAndPassword(String username, String password); // 查詢用戶年齡大于等于指定值且性別為指定值的用戶 List<User> findByAgeGreaterThanEqualAndGender(int age, String gender); }
除此之外,還可以使用 @Query 注解自定義 JPQL 或 SQL 查詢語(yǔ)句,例如:
@Query("SELECT u FROM User u WHERE u.username = :username") User findByUsername(@Param("username") String username);
這個(gè)例子定義了一個(gè)自定義查詢方法 findByUsername,使用 JPQL 查詢語(yǔ)句查詢用戶對(duì)象。在方法上使用了 @Query 注解,并傳入 JPQL 查詢語(yǔ)句作為 value 值,其中 :username 是一個(gè)占位符,使用 @Param 注解標(biāo)注其對(duì)應(yīng)的方法參數(shù)。
還可以在 @Query 注解中使用原生 SQL 查詢,例如:
@Query(value = "SELECT * FROM users WHERE username = :username", nativeQuery = true) User findByUsername(@Param("username") String username);
這個(gè)例子定義了一個(gè)使用原生 SQL 查詢的自定義查詢方法 findByUsername。在 @Query 注解中將 nativeQuery 屬性設(shè)置為 true,表示使用原生 SQL 查詢,其中 :username 是一個(gè)占位符,使用 @Param 注解標(biāo)注其對(duì)應(yīng)的方法參數(shù)。
編寫業(yè)務(wù)邏輯
@Service public class UserService { @Autowired private UserRepository userRepository; public List<User> findAll() { return userRepository.findAll(); } public Optional<User> findById(Long id) { return userRepository.findById(id); } public User save(User user) { return userRepository.save(user); } public void deleteById(Long id) { userRepository.deleteById(id); } }
編寫控制器
@RestController @RequestMapping("/users") public class UserController { @Autowired private UserService userService; @GetMapping("all") public List<User> getAllUsers() { return userService.findAll(); } @GetMapping("/{id}") public ResponseEntity<User> getUserById(@PathVariable Long id) { Optional<User> user = userService.findById(id); if (user.isPresent()) { return new ResponseEntity<>(user.get(), HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } } @PostMapping public User addUser(@RequestBody User user) { return userService.save(user); } @DeleteMapping("/{id}") public ResponseEntity<Void> deleteUser(@PathVariable Long id) { userService.deleteById(id); return ResponseEntity.noContent().build(); } }
結(jié)果
配置文件詳解
spring: datasource: url: jdbc:mysql://localhost:3306/mydb username: user password: pass driver-class-name: com.mysql.jdbc.Driver jpa: database-platform: org.hibernate.dialect.MySQL8Dialect show-sql: true # 是否打印生成的 SQL 語(yǔ)句 hibernate: ddl-auto: update # 應(yīng)用啟動(dòng)時(shí),自動(dòng)更新數(shù)據(jù)庫(kù)的表結(jié)構(gòu) properties: hibernate: format_sql: true # 是否格式化打印 SQL 語(yǔ)句
hibernate.ddl-auto
hibernate.ddl-auto
是一個(gè)Hibernate的配置屬性,用于控制在應(yīng)用啟動(dòng)時(shí)如何自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)模式(schema)。
其可選值包括:
- validate:驗(yàn)證Hibernate的所有實(shí)體類是否與數(shù)據(jù)庫(kù)中的表結(jié)構(gòu)匹配,如果不匹配則拋出異常,不做任何修改。
- update:根據(jù)Hibernate的實(shí)體類自動(dòng)更新數(shù)據(jù)庫(kù)模式(schema),不會(huì)刪除數(shù)據(jù),只會(huì)修改表結(jié)構(gòu)和數(shù)據(jù)類型。
- create:根據(jù)Hibernate的實(shí)體類自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)模式(schema),會(huì)刪除舊表并重新創(chuàng)建新表,但不會(huì)刪除表中的數(shù)據(jù)。
- create-drop:根據(jù)Hibernate的實(shí)體類自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)模式(schema),在應(yīng)用程序關(guān)閉時(shí)刪除所有表和數(shù)據(jù)。
- none:不進(jìn)行自動(dòng)數(shù)據(jù)庫(kù)模式(schema)管理,需要手動(dòng)管理數(shù)據(jù)庫(kù)模式(schema)。
需要注意的是,hibernate.ddl-auto
屬性在生產(chǎn)環(huán)境下不應(yīng)該使用,因?yàn)樗赡軙?huì)導(dǎo)致數(shù)據(jù)丟失和不可逆的表結(jié)構(gòu)修改。在開(kāi)發(fā)和測(cè)試環(huán)境下,它可以加快開(kāi)發(fā)迭代速度和方便數(shù)據(jù)庫(kù)模式(schema)的重建。
使用hibernate.ddl-auto屬性中的create或者create-drop值可以讓Hibernate根據(jù)實(shí)體類自動(dòng)創(chuàng)建表。
jpa.database-platform
jpa.database-platform
是Spring Data JPA中一個(gè)可選的配置項(xiàng),用于指定要使用的數(shù)據(jù)庫(kù)平臺(tái),以便在應(yīng)用程序啟動(dòng)時(shí)創(chuàng)建或更新數(shù)據(jù)庫(kù)時(shí)生成正確的SQL語(yǔ)句。該配置項(xiàng)需要指定一個(gè)數(shù)據(jù)庫(kù)方言(database dialect)的類名或者Hibernate方言名稱。
在默認(rèn)情況下,Spring Data JPA會(huì)根據(jù)數(shù)據(jù)源的元數(shù)據(jù)信息自動(dòng)檢測(cè)使用的數(shù)據(jù)庫(kù)類型和版本,并根據(jù)此信息自動(dòng)選擇合適的方言。但是,有些情況下自動(dòng)檢測(cè)可能無(wú)法正確識(shí)別數(shù)據(jù)庫(kù)類型或版本,或者應(yīng)用程序需要使用某些數(shù)據(jù)庫(kù)特定的特性,這時(shí)候就需要手動(dòng)指定方言。
jpa.database-platform
的取值通常為一下三種類型:
- Hibernate方言名稱(如
org.hibernate.dialect.MySQL5Dialect
) - 數(shù)據(jù)庫(kù)方言類名(如
com.mysql.cj.jdbc.Driver
) - Hibernate的方言實(shí)現(xiàn)類(如
org.hibernate.dialect.MySQL8Dialect
)
如果不指定此配置項(xiàng),Spring Data JPA會(huì)嘗試根據(jù)數(shù)據(jù)源的元數(shù)據(jù)自動(dòng)檢測(cè)數(shù)據(jù)庫(kù)類型和版本,并選擇合適的方言。如果自動(dòng)檢測(cè)失敗,可能會(huì)導(dǎo)致應(yīng)用程序啟動(dòng)失敗或生成的SQL語(yǔ)句無(wú)法正常執(zhí)行。
需要注意的是,如果應(yīng)用程序使用的是多個(gè)數(shù)據(jù)源,那么需要為每個(gè)數(shù)據(jù)源單獨(dú)指定方言??梢酝ㄟ^(guò)在application.yaml
中為每個(gè)數(shù)據(jù)源添加不同的jpa.database-platform
配置項(xiàng)來(lái)實(shí)現(xiàn)。
spring data jpa與其他orm框架的對(duì)比
Spring Data JPA是一個(gè)基于Spring Framework的數(shù)據(jù)訪問(wèn)框架,封裝了JPA規(guī)范,簡(jiǎn)化了JPA的使用,提供了一些常用的數(shù)據(jù)訪問(wèn)操作。
下面是Spring Data JPA與其他ORM框架的對(duì)比:
- Hibernate
Hibernate是一個(gè)流行的ORM框架,與JPA相比,它提供了更多的特性和靈活性,可以更好地處理復(fù)雜的映射關(guān)系和查詢。但是,Hibernate使用起來(lái)相對(duì)復(fù)雜,需要處理更多的配置和細(xì)節(jié)。相比之下,Spring Data JPA更加簡(jiǎn)潔易用,適合快速開(kāi)發(fā)和小型項(xiàng)目。
- MyBatis
MyBatis是一個(gè)輕量級(jí)的ORM框架,相比之下,它更加靈活,可以根據(jù)具體需求自定義SQL語(yǔ)句和映射關(guān)系。但是,使用MyBatis需要自己編寫SQL語(yǔ)句,相對(duì)繁瑣,而且需要自己處理一些細(xì)節(jié)。Spring Data JPA則提供了更加簡(jiǎn)便的操作,可以根據(jù)方法名自動(dòng)生成SQL,使用起來(lái)更加方便。
- JOOQ
JOOQ是一個(gè)基于Java的SQL構(gòu)建器和ORM框架,它提供了類型安全的SQL構(gòu)建和查詢,可以生成可維護(hù)的Java代碼。相比之下,Spring Data JPA更加簡(jiǎn)單易用,可以省去編寫SQL的麻煩,但是相對(duì)缺少類型安全性和可維護(hù)性。
總之,Spring Data JPA適合快速開(kāi)發(fā)和小型項(xiàng)目,能夠極大地簡(jiǎn)化數(shù)據(jù)訪問(wèn)操作,減少代碼量,但是相對(duì)缺少靈活性和復(fù)雜映射關(guān)系的處理能力。而Hibernate和MyBatis則更加靈活,可以處理更復(fù)雜的場(chǎng)景,但需要更多的配置和細(xì)節(jié)處理。
以上就是Spring Data JPA實(shí)現(xiàn)數(shù)據(jù)持久化過(guò)程詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring Data JPA數(shù)據(jù)持久化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java數(shù)據(jù)結(jié)構(gòu)之紅黑樹(shù)的真正理解
這篇文章主要為大家詳細(xì)介紹了Java數(shù)據(jù)結(jié)構(gòu)之紅黑樹(shù)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11Jmeter正則表達(dá)式提取器實(shí)現(xiàn)過(guò)程圖解
這篇文章主要介紹了Jmeter正則表達(dá)式提取器實(shí)現(xiàn)過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08詳解SpringBoot如何實(shí)現(xiàn)統(tǒng)一后端返回格式
在前后端分離的項(xiàng)目中后端返回的格式一定要友好,不然會(huì)對(duì)前端的開(kāi)發(fā)人員帶來(lái)很多的工作量。那么SpringBoot如何做到統(tǒng)一的后端返回格式呢?本文將為大家詳細(xì)講講2022-04-04java實(shí)現(xiàn)pgsql自動(dòng)更新創(chuàng)建時(shí)間與更新時(shí)間的兩種方式小結(jié)
本文主要介紹了java實(shí)現(xiàn)pgsql自動(dòng)更新創(chuàng)建時(shí)間與更新時(shí)間的兩種方式小結(jié),主要包括通過(guò)數(shù)據(jù)庫(kù)自身實(shí)現(xiàn)以及通過(guò)mybatisplus的TableField注解添加,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01Eclipse設(shè)置svn忽略文件或文件夾(svn:ignore)的操作
這篇文章主要介紹了Eclipse設(shè)置svn忽略文件或文件夾(svn:ignore)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01Mac使用Idea配置傳統(tǒng)SSM項(xiàng)目(非maven項(xiàng)目)
本文主要介紹了Mac使用Idea配置傳統(tǒng)SSM項(xiàng)目(非maven項(xiàng)目),將展示如何設(shè)置項(xiàng)目結(jié)構(gòu)、添加依賴關(guān)系等,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01springboot aspect通過(guò)@annotation進(jìn)行攔截的實(shí)例代碼詳解
這篇文章主要介紹了springboot aspect通過(guò)@annotation進(jìn)行攔截的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08基于JSON和java對(duì)象的互轉(zhuǎn)方法
下面小編就為大家?guī)?lái)一篇基于JSON和java對(duì)象的互轉(zhuǎn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09