Spring?Boot?整合持久層之Spring Data JPA
整合Spring Data JPA
JPA (Java Persistence API)和 Spring Data 是兩個(gè)范疇的概念。
Hibernate 是一個(gè) ORM 框架,JPA 則是一種ORM,JPA 和 Hibernate 的關(guān)系就像 JDBC 與 JDBC 驅(qū)動(dòng),即 JPA 制定了 ORM 規(guī)范,而 Hibernate 是這些規(guī)范的實(shí)現(xiàn)(事實(shí)上,是現(xiàn)有 Hibernate 后有 JPA ,JPA 規(guī)范的起草也是 Hibernate 的作者),因此從功能上來(lái)說(shuō),JPA 相當(dāng)于 Hibernate 的一個(gè)子集。
Spring Data 是 Spring 的一個(gè)子項(xiàng)目,致力于簡(jiǎn)化數(shù)據(jù)庫(kù)訪問,通過(guò)規(guī)范的方法名稱來(lái)分析開發(fā)者的意圖,進(jìn)而減少數(shù)據(jù)庫(kù)訪問層的代碼量。Spring Data 不僅支持關(guān)系型數(shù)據(jù)庫(kù),也支持非關(guān)系型數(shù)據(jù)庫(kù)。Spring Data JPA 可以有效簡(jiǎn)化關(guān)系型數(shù)據(jù)庫(kù)訪問代碼。
Spring Boot 整合 Spring Data JPA 步驟如下:
1. 創(chuàng)建數(shù)據(jù)庫(kù)
創(chuàng)建數(shù)據(jù)庫(kù)即可,不用創(chuàng)建表
創(chuàng)建數(shù)據(jù)庫(kù) jpa,如下
create database `jpa` default character set utf8;
2. 創(chuàng)建項(xiàng)目
創(chuàng)建 Spring Boot 項(xiàng)目,添加 MySQL 和 Spring Data JPA 的依賴
<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>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.9</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
3. 數(shù)據(jù)庫(kù)配置
在 application.properties 中配置數(shù)據(jù)庫(kù)基本信息以及 JPA 相關(guān)配置
# 數(shù)據(jù)庫(kù)基本配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=utf8&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
# JPA 配置
spring.jpa.show-sql=true
spring.jpa.database=mysql
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
4. 創(chuàng)建實(shí)體類
@Entity(name = "t_book") public class Book { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "book_name",nullable = false) private String name; private String author; private Float price; @Transient private String description; @Override public String toString() { return "Book{" + "id=" + id + ", name='" + name + '\'' + ", author='" + author + '\'' + ", price=" + price + ", description='" + description + '\'' + '}'; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } 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 getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; } }
代碼解釋:
- @Entity 注解表示該類是一個(gè)實(shí)體類,在項(xiàng)目啟動(dòng)時(shí)會(huì)根據(jù)該類生成一張表,表的名稱即 @Entity 注解中的 name 的值,如果不配置 name ,默認(rèn)表名為類名
- 所有的實(shí)體類都要有主鍵,@Id 注解表示改屬性是一個(gè)主鍵,@GeneratedValue 注解表示主鍵自動(dòng)生成,strategy 表示生成主鍵的策略
- 默認(rèn)情況下,生成的表中字段的名稱就是實(shí)體類中屬性的名稱,通過(guò) @Column 注解可以定制生成的字段的屬性,name 表示該屬性對(duì)應(yīng)的數(shù)據(jù)表中字段的名稱,nullable 表示該字段非空
- @Transient 注解表示在生成數(shù)據(jù)庫(kù)中的表時(shí),該屬性被忽略,即不生成對(duì)應(yīng)的字段
5. 創(chuàng)建 BookDao 接口
public interface BookDao extends JpaRepository<Book, Integer> { List<Book> getBooksByAuthorStartingWith(String author); List<Book> getBooksByPriceGreaterThan(Float price); @Query(value = "select * from t_book where id=(select max(id) from t_book)", nativeQuery = true) Book getMaxIdBook(); @Query("select b from t_book b where b.id>:id and b.author=:author") List<Book> getBookByIdAndAuthor(@Param("author") String author, @Param("id") Integer id); @Query("select b from t_book b where b.id<?2 and b.name like %?1%") List<Book> getBooksByIdAndName(String name, Integer id); }
代碼解釋:
- 自定義 BookDao 繼承 JpaRepository 。JpaRepository 中提供了一些基本的數(shù)據(jù)庫(kù)操作方法,有基本的增刪改查、分頁(yè)查詢、排序查詢等
- getBooksByAuthorStartingWith() 方法表示查詢以某個(gè)字符開始的所有的書
- getBooksByPriceGreaterThan() 方法表示查詢單價(jià)大于某個(gè)值的所有書
- 在Spring Data JPA 中,只要方法的定義符合既定規(guī)范,Spring Data JPA 就能分析出開發(fā)者的意圖,從而避免開發(fā)中定義 SQL 。 所謂的既定規(guī)范,就是一定的方法命名規(guī)則,支持的命名規(guī)則如下:
| 關(guān)鍵字 | 方法命名 | sql where字句 |
| — | — | — |
| And | findByNameAndPwd | where name= ? and pwd =? |
| Or | findByNameOrSex | where name= ? or sex=? |
| Is,Equals | findById,findByIdEquals | where id= ? |
| Between | findByIdBetween | where id between ? and ? |
| LessThan | findByIdLessThan | where id < ? |
| LessThanEqual | findByIdLessThanEqual | where id <= ? |
| GreaterThan | findByIdGreaterThan | where id > ? |
| GreaterThanEqual | findByIdGreaterThanEqual | where id > = ? |
| After | findByIdAfter | where id > ? |
| Before | findByIdBefore | where id < ? |
| IsNull | findByNameIsNull | where name is null |
| isNotNull,NotNull | findByNameNotNull | where name is not null |
| Like | findByNameLike | where name like ? |
| NotLike | findByNameNotLike | where name not like ? |
| StartingWith | findByNameStartingWith | where name like ‘?%’ |
| EndingWith | findByNameEndingWith | where name like ‘%?’ |
| Containing | findByNameContaining | where name like ‘%?%’ |
| OrderBy | findByIdOrderByXDesc | where id=? order by x desc |
| Not | findByNameNot | where name <> ? |
| In | findByIdIn(Collection<?> c) | where id in (?) | | NotIn | findByIdNotIn(Collection<?> c) | where id not in (?) |
| True | findByAaaTue | where aaa = true |
| False | findByAaaFalse | where aaa = false |
| IgnoreCase | findByNameIgnoreCase | where UPPER(name)=UPPER(?) |
- 既定的方法命名規(guī)則不一定滿足所有的開發(fā)需求,因此 Spring Data JPA 也支持自定義 JPQL 或者原生 SQL 。getMaxIdBook() 方法表示查詢id最大的書,nativeQuery = true 表示使用原生的 SQL 查詢
- getBookByIdAndAuthor() 表示根據(jù) id 和 author 進(jìn)行查詢,這里使用默認(rèn)的 JPQL 語(yǔ)句。JPQL 是一種面向?qū)ο蟊磉_(dá)式語(yǔ)言,可以將 SQL 語(yǔ)法和簡(jiǎn)單查詢語(yǔ)句綁定在一起,使用這種語(yǔ)言編寫的查詢是可以移植的,可以被編譯成所有主流數(shù)據(jù)庫(kù)服務(wù)器上的 SQL 。JPQL 與原生 SQL 語(yǔ)句類似,并且完全面向?qū)ο?,通過(guò)類名和屬性訪問,而不是表名和表的屬性。getBookByIdAndAuthor() 方法使用 :id、:name 這種方式來(lái)進(jìn)行參數(shù)綁定。注意:這里使用的列名是屬性名稱,而不是數(shù)據(jù)庫(kù)中的列的名稱。
- getBooksByIdAndName() 方法也是自定義 JPQL 查詢,不同的是傳參使用 ?1、?2 這種方式。注意:方法中的參數(shù)的順序要與參數(shù)聲明的順序一致
- 如果 BookDao 中的方法設(shè)計(jì)修改操作,就需要添加 @Modifying 注解并添加事務(wù)
6. 創(chuàng)建 BookService
@Service public class BookService { @Autowired BookDao bookDao; public void addBook(Book book) { bookDao.save(book); } public Page<Book> getBookByPage(Pageable pageable) { return bookDao.findAll(pageable); } public List<Book> getBooksByAuthorStartingWith(String author) { return bookDao.getBooksByAuthorStartingWith(author); } public List<Book> getBooksByPriceGreaterThan(Float price) { return bookDao.getBooksByPriceGreaterThan(price); } public Book getMaxIdBook() { return bookDao.getMaxIdBook(); } public List<Book> getBookByIdAndAuthor(String author, Integer id) { return bookDao.getBookByIdAndAuthor(author, id); } public List<Book> getBooksByIdAndName(String name, Integer id) { return bookDao.getBooksByIdAndName(name, id); } }
代碼解釋:
- bookDao.save(book) 標(biāo)識(shí)將對(duì)象數(shù)據(jù)保存到數(shù)據(jù)庫(kù),save 方法由 JpaRepository 接口提供
- bookDao.findAll(pageable) 是一個(gè)分頁(yè)查詢,使用 findAll 方法,返回值為 Page ,該對(duì)象中包含有分頁(yè)常用數(shù)據(jù),例如總記錄數(shù),總頁(yè)數(shù)、每頁(yè)記錄數(shù)、當(dāng)前頁(yè)記錄數(shù)等
7. 創(chuàng)建 BookController
@RestController public class BookController { @Autowired BookService bookService; @GetMapping("/findAll") public void findAll() { PageRequest pageable = PageRequest.of(2, 3); Page<Book> page = bookService.getBookByPage(pageable); System.out.println("總頁(yè)數(shù):"+page.getTotalPages()); System.out.println("總記錄數(shù):"+page.getTotalElements()); System.out.println("查詢結(jié)果:"+page.getContent()); System.out.println("當(dāng)前頁(yè)數(shù):"+(page.getNumber()+1)); System.out.println("當(dāng)前頁(yè)記錄數(shù):"+page.getNumberOfElements()); System.out.println("每頁(yè)記錄數(shù):"+page.getSize()); } @GetMapping("/search") public void search() { List<Book> bs1 = bookService.getBookByIdAndAuthor("魯迅", 7); List<Book> bs2 = bookService.getBooksByAuthorStartingWith("吳"); List<Book> bs3 = bookService.getBooksByIdAndName("西", 8); List<Book> bs4 = bookService.getBooksByPriceGreaterThan(30F); Book b = bookService.getMaxIdBook(); System.out.println("bs1:"+bs1); System.out.println("bs2:"+bs2); System.out.println("bs3:"+bs3); System.out.println("bs4:"+bs4); System.out.println("b:"+b); } @GetMapping("/save") public void save() { Book book = new Book(); book.setAuthor("魯迅"); book.setName("吶喊"); book.setPrice(23F); bookService.addBook(book); } }
代碼解釋:
- 在 findAll 接口中,首先通過(guò)調(diào)用 PageRequest 中的 of 方法構(gòu)造 PageRequest 對(duì)象。of 方法接收兩個(gè)參數(shù):第一個(gè)參數(shù)是頁(yè)數(shù),從 0 開始計(jì);第二個(gè)參數(shù)是每頁(yè)顯示的條數(shù)
- 在save 接口中構(gòu)造一個(gè) Book 對(duì)象,直接調(diào)用 save 方法保存即可
8. 測(cè)試
啟動(dòng)項(xiàng)目,查看數(shù)據(jù)庫(kù)發(fā)現(xiàn) t_book 表已自動(dòng)新建,添加測(cè)試數(shù)據(jù)
INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (1, '羅貫中', '三國(guó)演義', 30); INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (2, '曹雪芹', '紅樓夢(mèng)', 35); INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (3, '吳承恩', '西游記', 29); INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (4, '施耐庵', '水滸傳', 29); INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (5, '錢鐘書', '宋詩(shī)選注', 33); INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (6, '魯迅', '朝花夕拾', 18); INSERT INTO `jpa`.`t_book`(`id`, `author`, `book_name`, `price`) VALUES (7, '魯迅', '故事新編', 22);
然后調(diào)用 /findAll 接口,控制臺(tái)打印日志如下:
Hibernate: select book0_.id as id1_0_, book0_.author as author2_0_, book0_.book_name as book_nam3_0_, book0_.price as price4_0_ from t_book book0_ limit ?, ?
總頁(yè)數(shù):3
總記錄數(shù):7
查詢結(jié)果:[Book{id=7, name='故事新編', author='魯迅', price=22.0, description='null'}]
當(dāng)前頁(yè)數(shù):3
當(dāng)前頁(yè)記錄數(shù):1
每頁(yè)記錄數(shù):3
接著調(diào)用 /save 接口 ,查看數(shù)據(jù)庫(kù)表數(shù)據(jù),如下
最后調(diào)用 /search 接口,控制臺(tái)打印日志如下
Hibernate: select book0_.id as id1_0_, book0_.author as author2_0_, book0_.book_name as book_nam3_0_, book0_.price as price4_0_ from t_book book0_ where book0_.id>? and book0_.author=?
Hibernate: select book0_.id as id1_0_, book0_.author as author2_0_, book0_.book_name as book_nam3_0_, book0_.price as price4_0_ from t_book book0_ where book0_.author like ? escape ?
Hibernate: select book0_.id as id1_0_, book0_.author as author2_0_, book0_.book_name as book_nam3_0_, book0_.price as price4_0_ from t_book book0_ where book0_.id<? and (book0_.book_name like ?)
Hibernate: select book0_.id as id1_0_, book0_.author as author2_0_, book0_.book_name as book_nam3_0_, book0_.price as price4_0_ from t_book book0_ where book0_.price>?
Hibernate: select * from t_book where id=(select max(id) from t_book)
bs1:[Book{id=8, name='吶喊', author='魯迅', price=23.0, description='null'}]
bs2:[Book{id=3, name='西游記', author='吳承恩', price=29.0, description='null'}]
bs3:[Book{id=3, name='西游記', author='吳承恩', price=29.0, description='null'}]
bs4:[Book{id=2, name='紅樓夢(mèng)', author='曹雪芹', price=35.0, description='null'}, Book{id=5, name='宋詩(shī)選注', author='錢鐘書', price=33.0, description='null'}]
b:Book{id=8, name='吶喊', author='魯迅', price=23.0, description='null'}
到此這篇關(guān)于Spring Boot 整合持久層之Spring Data JPA的文章就介紹到這了,更多相關(guān)Spring Boot Spring Data JPA內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用SSM+Layui+Bootstrap實(shí)現(xiàn)汽車維保系統(tǒng)的示例代碼
本文主要實(shí)現(xiàn)對(duì)汽車維修廠的信息化管理功能,。實(shí)現(xiàn)的主要功能包含用戶管理、配置管理、汽車管理、故障管理、供應(yīng)商管理、配件管理、維修訂單管理、統(tǒng)計(jì)信息、公告管理、個(gè)人信息管理,感興趣的可以了解一下2021-12-12java 實(shí)現(xiàn)MD5加密算法的簡(jiǎn)單實(shí)例
這篇文章主要介紹了java 實(shí)現(xiàn)MD5加密算法的簡(jiǎn)單實(shí)例的相關(guān)資料,這里提供實(shí)例幫助大家應(yīng)用這樣的加密算法,需要的朋友可以參考下2017-09-09Java HttpURLConnection超時(shí)和IO異常處理
這篇文章主要介紹了Java HttpURLConnection超時(shí)和IO異常處理的相關(guān)資料,需要的朋友可以參考下2016-09-09Java基于socket實(shí)現(xiàn)簡(jiǎn)易聊天室實(shí)例
這篇文章主要介紹了Java基于socket實(shí)現(xiàn)簡(jiǎn)易聊天室的方法,實(shí)例分析了java基于socket實(shí)現(xiàn)聊天室服務(wù)端與客戶端的相關(guān)技巧,需要的朋友可以參考下2015-05-05