SpringBoot 學習筆記_整合持久層——Spring Boot JPA
聲明:
本次學習參考 《SpringBoot + Vue 開發實戰》 · 王松(著) 一書。
本文的目的是記錄我學習的過程和遇到的一些問題以及解決辦法,其內容主要來源於原書。
如有侵權,請聯繫我刪除
SpringBoot 整合持久層開發
整合 Spring Boot JPA
JPA
是一種ORM
規範。Spring Data
是Spring
的一個子項目,致力於簡化數據的訪問,通過規範的方法名稱來分析開發者的意圖,進而減少數據庫訪問層的代碼。
-
創建數據庫(表會根據實體類自動創建)
-
創建 SpringBoot 項目,添加依賴
<!-- 添加 Spring Boot 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>
-
數據庫配置(
application.properties
)### 數據庫基本配置 ### spring.datasource.type=com.alibaba.druid.pool.DruidDataSource #spring.datasource.url=jdbc:mysql:///chapter05?serverTimezone=GMT spring.datasource.url=jdbc:mysql://localhost:3306/chapter05?serverTimezone=GMT spring.datasource.username=root spring.datasource.password=root #### 數據庫配置 —— JPA 相關 #### # 表示是否在控制檯打印 JPA 打印過程生成的 SQL spring.jpa.show-sql=true # 表示 JPA 對應的數據庫是 MySQL spring.jpa.database=mysql # 表示在項目啓動時根據實體類更新數據庫中的表(可選:create、create-drop、validate、no) spring.jpa.hibernate.ddl-auto=update # 表示使用的數據庫方言是 MySQL57Dialect spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
-
創建實體類
// @Entity 表示該類是一個實體類。在項目啓動時會根據該類自動生成一個數據表,表名稱即 @Entity 的 name 值,如果不配置,默認爲類名。 @Entity(name = "t_book") public class BookJPA { // @Id 表示該實體類的主鍵。所有實體類都要有主鍵 @Id // @GeneratedValue 表示主鍵自動生成,strategy 表示生成策略 @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; // @Column 表示表中字段名稱和實體類中屬性名稱的映射。如果不配置,默認生成字段名就是屬性名。nullable 表示是否可爲空 @Column(name = "book_name", nullable = false) private String name; private String author; private Float price; // @Transient 表示生成數據表時,忽略該字段 @Transient private String description; }
-
創建數據庫訪問層
/** * 整合 JPA 的 BookDao * * 自定義 Dao 繼承 JpaRepository。JpaRepository 中提供了一些基本的數據操作方法,有增刪改查、分頁查詢、排序查詢等。 */ public interface BookJPADao extends JpaRepository<BookJPA, Integer> { //Spring Data JPA 支持既定規範命名查詢(方法名複合既定規範,自動生成對應 SQL) /** * keyWords 示例 對應 SQL * And findByNameAndAge where name=? and age=? * Or findByNameOrAge where name=? or age=? * Is/Equals findByAgeIs/findByAgeEquals where age=? * Between findByAgeBetween where age between ? and ? * LessThan/Before findByAgeLessThan/findByAgeBefore where age < ? * LessThanEquals findByAgeLessThanEquals where age <= ? * GreaterThan/After findByAgeGreaterThan/findByAgeAfter where age > ? * GreaterThanEquals findByAgeGreaterThanEquals where age >= ? * IsNull findByNameIsNull where name is null * IsNotNull/NotNull findByNameNotNull where name is not null * Not findByNameNot where name <> ? * In findByAgeIn where age in(?) * NotIn findByAgeNotIn where age not in(?) * NotLike findByNameNotLike where name not like ? * StartingWith findByNameStartingWith where name like '?%' * EndingWith findByNameEndingWith where name like '%?' * Containing/Contains findByNameContains where name like '%?%' * True findByEnabledTrue where enabled = true * False findByEnabledFalse where enabled = false * IgnoreCase findByNameIgnoreCase where UPPER(name)=UPPER(?) * * OrderBy findByAgeGreaterThanOrderByIdDesc where age > ? order by id desc */ // 查詢作者名以某字符開頭的所有書 List<BookJPA> getBooksByAuthorStartingWith(String author); // 查詢價格大於某值得所有書 List<BookJPA> getBooksByPriceGreaterThan(Float price); // Spring Data JPA 支持原生 SQL。 nativeQuery = true 表示使用原生 SQL 語句 @Query(value = "select * from t_book where id=(select max(id) from t_book)", nativeQuery = true) BookJPA getMaxIdBook(); // Spring Data JPA 支持默認的 JPQL。JPQL 是一種可移植的面向對象表達式語言。 // 通過類名和屬性(並非數據庫列名)來進行參數綁定。參數需要使用 @Param 綁定。 @Query("select b from t_book b where b.id > :id and b.author=:author") List<BookJPA> getBookByIdAndAuthor(@Param("author") String author, @Param("id") Integer id); // Spring Data JPA 支持默認的 JPQL。 // 通過佔位符進行參數傳遞。參數順序有嚴格要求。 @Query("select b from t_book b where b.id < ?2 and b.name like %?1%") List<BookJPA> getBooksByIdAndNameAnd(String name, Integer id); // 如果方法涉及修改操作,需要添加 @Modifying 註解並添加事務 }
-
創建 Service 和 Controller
/** * 整合 Spring Data JPA 的 Service 層 */ @Service public class BookJPAService { @Autowired BookJPADao bookDao; public void addBook(BookJPA book){ bookDao.save(book); } public Page<BookJPA> getBookByPage(Pageable pageable){ return bookDao.findAll(pageable); } public List<BookJPA> getBooksByAuthorStartingWith(String author){ return bookDao.getBooksByAuthorStartingWith(author); } public List<BookJPA> getBooksByPriceGreaterThan(Float price){ return bookDao.getBooksByPriceGreaterThan(price); } public BookJPA getMaxIdBook(){ return bookDao.getMaxIdBook(); } public List<BookJPA> getBookByIdAuthor(String author, Integer id){ return bookDao.getBookByIdAndAuthor(author, id); } public List<BookJPA> getBooksByIdAndName(String name, Integer id){ return bookDao.getBooksByIdAndName(name, id); } }
/** * 整個 Spring Data JPA 的 Controller 層 */ @RestController public class BookJPAController { @Autowired BookJPAService bookService; @GetMapping("/jpa/findAll") public void findAll(){ PageRequest pageable = PageRequest.of(2, 3); Page<BookJPA> page = bookService.getBookByPage(pageable); System.out.println(" 總頁數: " + page.getTotalPages()); System.out.println(" 總記錄: " + page.getTotalElements()); System.out.println(" 查詢結果: " + page.getContent()); System.out.println(" 當前頁數: " + page.getNumber() + 1); System.out.println(" 當前頁記錄數: " + page.getNumberOfElements()); System.out.println(" 每頁記錄數: " + page.getSize()); } @GetMapping("/jpa/search") public void search(){ List<BookJPA> bs1 = bookService.getBookByIdAndAuthor("吳承恩", 1); List<BookJPA> bs2 = bookService.getBooksByAuthorStartingWith("施"); List<BookJPA> bs3 = bookService.getBooksByPriceGreaterThan(0.1F); BookJPA book = bookService.getMaxIdBook(); System.out.println(bs1); System.out.println(bs2); System.out.println(bs3); System.out.println(book); } @GetMapping("/jpa/save") public void save(){ BookJPA book = new BookJPA(); book.setAuthor("臥龍"); book.setName("臥龍鍋巴"); book.setPrice(3.5F); bookService.addBook(book); } }