前言
在前面的第九章:Mybatis-plus的集成和使用章節中,介紹了使用
ORM
框架mybatis-plus
進行數據庫的訪問。今天,我們來簡單學習下如何使用spring-data-jpa
進行數據庫的訪問。由於本人未使用過jpa
,也是趁着寫博文的機會查閱了相關資料下,有錯誤的地方還望指出!
一點知識
何為JPA
JPA
是Java Persistence API
的簡寫,是Sun
官方提出的一種ORM
規范!
對於Sun
官網而言,
一是想簡化現有Java EE
和Java SE
應用開發工作。
二是想整合ORM技術,實現天下歸一。
對於JPA
規范,都在包路徑:javax.persistence.*
下,像一些常用的如:@Entity
、@Id
及@Transient
都在此路徑下。這些也是一些現在市面上常用的ORM
一些約定俗成的注解了。
簡單來說,JPA
是一套規范。所以使用Jpa的一個好處是,可以更換實現而不必改動太多代碼。
何為Sping-data-jpa
Spring Data JPA
是Spring
基於Hibernate
開發的一個JPA
框架。可以極大的簡化JPA
的寫法,可以在幾乎不用寫具體代碼的情況下,實現對數據的訪問和操作。除了CRUD
外,還包括如分頁
、排序
等一些常用的功能。
Spring Data JPA提供的接口,也是Spring Data JPA的核心概念:
Repository
:最頂層的接口,是一個空的接口,目的是為了統一所有Repository的類型,且能讓組件掃描的時候自動識別。CrudRepository
:是Repository的子接口,提供CRUD的功能PagingAndSortingRepository
:是CrudRepository的子接口,添加分頁和排序的功能JpaRepository
:是PagingAndSortingRepository的子接口,增加了一些實用的功能,比如:批量操3作等。JpaSpecificationExecutor
:用來做負責查詢的接口Specification
:是Spring Data JPA
提供的一個查詢規范,要做復雜的查詢,只需圍繞這個規范來設置查詢條件即可。
題外話:剛開始,其實我看mybatis
提供的都差不多,最讓我覺得神奇的是:可以通過方法命名規則
進行相關數據庫操作,這個確實可以減少很多代碼的編寫。原本使用Mybatis-plus
新增一個自定義方法,需要使用通用查詢模版EntityWrapper
進行相應的操作的
其中,相關命名規范如下:
關鍵字 | 方法命名 | 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 < ? |
LessThanEquals | findByIdLessThanEquals | where id <= ? |
GreaterThan | findByIdGreaterThan | where id > ? |
GreaterThanEquals | findByIdGreaterThanEquals | 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(?) |
這個確實,夠強大!但查詢添加一多,是不是這個方法名就也很長了,(┬_┬)
SpringBoot集成Spring-data-jpa
本示例,使用druid(連接池)
+mysql
進行演示。同時以User
表舉例:
CREATE TABLE `user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '唯一標示',
`code` varchar(20) DEFAULT NULL COMMENT '編碼',
`name` varchar(64) DEFAULT NULL COMMENT '名稱',
`status` char(1) DEFAULT '1' COMMENT '狀態 1啟用 0 停用',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
題外話:雖然也提供了自動根據實體創建表的功能,但一般上開發應該不會這么創建吧。因為表結構一般都需要經過評審的,評審后就創建好了。。
0.引入pom依賴
<!-- 引入jpa依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- mysql驅動 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
1.編寫User
的實體類。
/**
* 用戶實體
* @author oKong
*
*/
@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EntityListeners(AuditingEntityListener.class)
//@Table(name="CUSTOM_USER")//自定義表名
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = -3752294262021766827L;
/**
* 唯一標示
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 編碼
*/
private String code;
/**
* 名稱
*/
private String name;
/**
* 創建時間
*/
@CreatedDate //自動創建
private Date gmtCreate;
/**
* 修改時間
*/
@LastModifiedDate //有修改時 會自動時間
private Date gmtModified;
}
這里需要注意,在使用mybatis-plus
時,在《Mybatis-Plus使用全解》時,介紹過可如何設置公共字段自動填充功能,比如創建時間和修改時間,創建人和修改人等等,都是可以統一進行賦值的。而在spring-data-jap
中,是使用@CreatedDate
和@LastModifiedDate
標記的,同時,需要在實體類上,加入@EntityListeners(AuditingEntityListener.class)
,然后在啟動類上加入注解@EnableJpaAuditing
,這樣就實現了類似公共字段自動填充功能了。
2.創建資源類,這里習慣了命名為dao
了,所以還是以Dao
進行結尾。
/**
* 資源類
* @author oKong
*
*/
public interface UserDao extends PagingAndSortingRepository<User,Long>{
List<User> findById(Long id);
//使用自動命名規則進行查詢服務
List<User> findByCodeAndName(String code,String name);
//使用@Query進行 自定義sql編寫
//nativeQuery=true,正常的sql語法
//負責是hsql語法
@Query(value="select * from user where code = ?1",nativeQuery=true)
List<User> queryByCode(String code);
//分頁
Page<User> findByCode(String code,Pageable pageable);
}
注意:這里直接繼承了PagingAndSortingRepository
,其本身實現了分頁功能,還可以按需要繼承CrudRepository
或者JpaRepository
等。而且,占位符為:?
+具體的參數索引值
3.創建控制層,引入資源類。示例了一些常用的操作,包括分頁,查詢、刪除、新增等等。
/**
* 測試類
* @author oKong
*
*/
@RestController
@Slf4j
public class DemoController {
@Autowired
UserDao userDao;
@PostMapping("/add")
public String addUser(User user) {
log.info("新增用戶:{}", user);
user = userDao.save(user);
return "新增成功,返回用戶id為:" + user.getId();
}
@GetMapping("/find/{id}")
public User findUser(@PathVariable Long id) {
log.info("查找用戶ID:{}", id);
return userDao.findOne(id);
}
@PostMapping("/del/{id}")
public String delUser(Long id) {
log.info("刪除用戶ID:{}", id);
userDao.delete(id);
return "用戶id為:" + id + ",已被刪除!";
}
@GetMapping("/find/{code}/{name}")
public List<User> findUserByCodeAndName(@PathVariable("code") String code, @PathVariable("name")String name) {
log.info("命名規則方式,查找用戶:編碼:{},名稱:{}", code, name);
return userDao.findByCodeAndName(code, name);
}
@GetMapping("/find/paging/{code}")
public Page<User> findUserByCodePagin(@PathVariable("code") String code){
log.info("分頁模式,查找用戶:編碼:{}", code);
//這里注意 page是從0開始的
return userDao.findByCode(code, new PageRequest(0,10));
}
@GetMapping("/find/sql/{code}")
public List<User> findUserByQuerySql(@PathVariable("code") String code){
log.info("自定義sql方式,查找用戶:編碼:{}", code);
return userDao.queryByCode(code);
}
}
4.配置文件添加相關數據源及jpa相關信息。這里使用druid
作為數據連接池。
#數據源設置
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/learning?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456
#以上為必須的
#選填
spring.datasource.druid.initial-size=5
# maxPoolSize
spring.datasource.druid.max-active=20
# minPoolSize
spring.datasource.druid.min-idle=5
#配置獲取連接等待超時的時間
spring.datasource.druid.max-wait=60000
# 校驗
spring.datasource.druid.validation-query=SELECT 'x'
spring.datasource.druid.test-on-borrow=false
spring.datasource.druid.test-on-return=false
spring.datasource.druid.test-while-idle=true
#配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒
spring.datasource.druid.time-between-eviction-runs-millis=60000
#配置一個連接在池中最小生存的時間,單位是毫秒
spring.datasource.druid.min-evictable-idle-time-millis=300000
#jpa相關配置
# 顯示sql 但不會顯示具體的操作值 可以替換成log4jdbc
spring.jpa.show-sql=true
5.編寫啟動類。
/**
* jpa集成
*
* @author oKong
*
*/
@SpringBootApplication
@EnableJpaAuditing
@Slf4j
public class JpaApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(JpaApplication.class, args);
log.info("spring-boot-jpa-chapter30啟動!");
}
}
6.啟動服務。然后使用postman
進行訪問(關於postman
相關用法,可以查看:第十五章:基於Postman的RESTful接口測試)。
會返回相關信息,如總記錄數,總頁碼數等等。
控制台輸出:
Hibernate: select user0_.id as id1_0_, user0_.code as code2_0_, user0_.gmt_create as gmt_crea3_0_, user0_.gmt_modified as gmt_modi4_0_, user0_.name as name5_0_ from user user0_ where user0_.code=? limit ?
Hibernate: select count(user0_.id) as col_0_0_ from user user0_ where user0_.code=?
- 自定義sql查找:http://127.0.0.1:8080/find/sql/okong
控制台輸出:
Hibernate: select * from user where code = ?
參考資料
總結
本章節主要介紹了
Spring-data-jpa
的集成和簡單的使用。並未深入了解,想了解更多細節,比如排序、@Param使用等等,可去官網查閱下。待有機會深入學習后,再寫一篇關於JPA
的提高篇吧使用起來其實也蠻簡單的,就是可能更開始接觸,不是很習慣到時真的,有機會一些小的項目或者demo項目,到時可以使用下,切身體驗下
最后
目前互聯網上很多大佬都有
SpringBoot
系列教程,如有雷同,請多多包涵了。原創不易,碼字不易,還希望大家多多支持。若文中有所錯誤之處,還望提出,謝謝。
老生常談
- 個人QQ:
499452441
- 微信公眾號:
lqdevOps
個人博客:http://blog.lqdev.cn
完整示例:https://github.com/xie19900123/spring-boot-learning/tree/master/chapter-30