javascript
Spring-Data-JPA尝鲜:快速搭建CRUD+分页后台实例
戳藍(lán)字“CSDN云計(jì)算”關(guān)注我們哦!
簡(jiǎn)書(shū)ID:@我沒(méi)有三顆心臟 ?
github:wmyskxz ?
歡迎關(guān)注公眾微信號(hào):wmyskxz
前言:由于之前沒(méi)有接觸過(guò)Hibernate框架,但是最近看一些博客深深被它的“效率”所吸引,所以這就來(lái)跟大家一起就著一個(gè)簡(jiǎn)單的例子來(lái)嘗嘗Spring全家桶里自帶的JPA的鮮
Spring-DATA-JPA 簡(jiǎn)介
JPA(Java Persistence API)是Sun官方提出的Java持久化規(guī)范。它為Java開(kāi)發(fā)人員提供了一種對(duì)象/關(guān)聯(lián)映射工具來(lái)管理Java應(yīng)用中的關(guān)系數(shù)據(jù)。他的出現(xiàn)主要是為了簡(jiǎn)化現(xiàn)有的持久化開(kāi)發(fā)工作和整合ORM技術(shù),結(jié)束現(xiàn)在Hibernate,TopLink,JDO等ORM框架各自為營(yíng)的局面。值得注意的是,JPA是在充分吸收了現(xiàn)有Hibernate,TopLink,JDO等ORM框架的基礎(chǔ)上發(fā)展而來(lái)的,具有易于使用,伸縮性強(qiáng)等優(yōu)點(diǎn)。從目前的開(kāi)發(fā)社區(qū)的反應(yīng)上看,JPA受到了極大的支持和贊揚(yáng),其中就包括了Spring與EJB3.0的開(kāi)發(fā)團(tuán)隊(duì)。
注意:JPA是一套規(guī)范,不是一套產(chǎn)品,那么像Hibernate,TopLink,JDO他們是一套產(chǎn)品,如果說(shuō)這些產(chǎn)品實(shí)現(xiàn)了這個(gè)JPA規(guī)范,那么我們就可以叫他們?yōu)镴PA的實(shí)現(xiàn)產(chǎn)品。
Spring Data JPA 是 Spring 基于 ORM 框架、JPA 規(guī)范的基礎(chǔ)上封裝的一套JPA應(yīng)用框架,可使開(kāi)發(fā)者用極簡(jiǎn)的代碼即可實(shí)現(xiàn)對(duì)數(shù)據(jù)的訪問(wèn)和操作。它提供了包括增刪改查等在內(nèi)的常用功能,且易于擴(kuò)展!學(xué)習(xí)并使用 Spring Data JPA 可以極大提高開(kāi)發(fā)效率!(spring data jpa讓我們解脫了DAO層的操作,基本上所有CRUD都可以依賴(lài)于它來(lái)實(shí)現(xiàn))
摘自:springboot(五):spring data jpa的使用——純潔的微笑
Hibernate 和 MyBatis 簡(jiǎn)單對(duì)比
由于JPA底層干活的仍然是Hibernate框架,而我們之前學(xué)習(xí)的只有MyBatis相關(guān)的東西,所以在嘗鮮之前還是有必要簡(jiǎn)單了解一下兩者的區(qū)別:
Hibernate的優(yōu)勢(shì):
Hibernate的DAO層開(kāi)發(fā)比MyBatis簡(jiǎn)單,Mybatis需要維護(hù)SQL和結(jié)果映射。
Hibernate對(duì)對(duì)象的維護(hù)和緩存要比MyBatis好,對(duì)增刪改查的對(duì)象的維護(hù)要方便。
Hibernate數(shù)據(jù)庫(kù)移植性很好,MyBatis的數(shù)據(jù)庫(kù)移植性不好,不同的數(shù)據(jù)庫(kù)需要寫(xiě)不同SQL。
Hibernate有更好的二級(jí)緩存機(jī)制,可以使用第三方緩存。MyBatis本身提供的緩存機(jī)制不佳。
MyBatis的優(yōu)勢(shì):
MyBatis可以進(jìn)行更為細(xì)致的SQL優(yōu)化,可以減少查詢(xún)字段。
MyBatis容易掌握,而Hibernate門(mén)檻較高。
簡(jiǎn)單總結(jié):
MyBatis:小巧、方便、高效、簡(jiǎn)單、直接、半自動(dòng)化
Hibernate:強(qiáng)大、方便、高效、復(fù)雜、間接、全自動(dòng)化
引用自:【持久化框架】Mybatis與Hibernate的詳細(xì)對(duì)比——高亮
CRUD + 分頁(yè)后臺(tái)實(shí)例
下面我們來(lái)快速搭建一個(gè)使用Spring-DATA-JPA的CRUD+分頁(yè)后臺(tái)實(shí)例,并且我們會(huì)直接使用到RESTful API(不熟悉的同學(xué)[戳這里]())
第一步:新建SpringBoot項(xiàng)目
打開(kāi)IDEA新建一個(gè)SpringBoot項(xiàng)目,不熟悉SpringBoot的同學(xué)請(qǐng)右轉(zhuǎn):【傳送門(mén)】,然后在pom.xml中添加以下依賴(lài):
<!--?mysql--><dependency>
????<groupId>mysql</groupId>
????<artifactId>mysql-connector-java</artifactId>
????<version>5.1.21</version>
</dependency>
<!--?jpa-->
<dependency>
????<groupId>org.springframework.boot</groupId>
????<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
然后把a(bǔ)pplication.properties弄成這個(gè)樣子:
#數(shù)據(jù)庫(kù)spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
#顯示SQL語(yǔ)句
spring.jpa.show-sql=true
#不加下面這句則默認(rèn)創(chuàng)建MyISAM引擎的數(shù)據(jù)庫(kù)
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
#自己重寫(xiě)的配置類(lèi),默認(rèn)使用utf8編碼
spring.jpa.properties.hibernate.dialect=com.wmyskxz.demo.config.MySQLConfig
spring.jpa.properties.hibernate.hbm2ddl.auto是hibernate的配置屬性,其主要作用是:自動(dòng)創(chuàng)建、更新、驗(yàn)證數(shù)據(jù)庫(kù)表結(jié)構(gòu)。該參數(shù)的幾種配置如下:
create:每次加載hibernate時(shí)都會(huì)刪除上一次的生成的表,然后根據(jù)你的model類(lèi)再重新來(lái)生成新表,哪怕兩次沒(méi)有任何改變也要這樣執(zhí)行,這就是導(dǎo)致數(shù)據(jù)庫(kù)表數(shù)據(jù)丟失的一個(gè)重要原因。
create-drop:每次加載hibernate時(shí)根據(jù)model類(lèi)生成表,但是sessionFactory一關(guān)閉,表就自動(dòng)刪除。
update:最常用的屬性,第一次加載hibernate時(shí)根據(jù)model類(lèi)會(huì)自動(dòng)建立起表的結(jié)構(gòu)(前提是先建立好數(shù)據(jù)庫(kù)),以后加載hibernate時(shí)根據(jù)model類(lèi)自動(dòng)更新表結(jié)構(gòu),即使表結(jié)構(gòu)改變了但表中的行仍然存在不會(huì)刪除以前的行。要注意的是當(dāng)部署到服務(wù)器后,表結(jié)構(gòu)是不會(huì)被馬上建立起來(lái)的,是要等應(yīng)用第一次運(yùn)行起來(lái)后才會(huì)。
validate:每次加載hibernate時(shí),驗(yàn)證創(chuàng)建數(shù)據(jù)庫(kù)表結(jié)構(gòu),只會(huì)和數(shù)據(jù)庫(kù)中的表進(jìn)行比較,不會(huì)創(chuàng)建新表,但是會(huì)插入新值。
然后新建一個(gè)【config】包,創(chuàng)建一個(gè)【MySQLConfig】類(lèi)(上面的spring.jpa.properties.hibernate.dialect屬性就要配置這里的類(lèi)全路徑):
package?com.wmyskxz.demo.config;import?org.hibernate.dialect.MySQL5InnoDBDialect;
public?class?MySQLConfig?extends?MySQL5InnoDBDialect?{
????@Override
????public?String?getTableTypeString()?{
????????return?"ENGINE=InnoDB?DEFAULT?CHARSET=utf8";
????}
}
第二步:創(chuàng)建好需要的數(shù)據(jù)庫(kù)
打開(kāi)SQL服務(wù),建表語(yǔ)句也很簡(jiǎn)單啦:
create?database?testdb;第三步:創(chuàng)建實(shí)體類(lèi)
實(shí)體類(lèi)映射的實(shí)際上是數(shù)據(jù)庫(kù)表的結(jié)構(gòu),在適當(dāng)?shù)陌夸浵?#xff08;例如【entity】)下創(chuàng)建好實(shí)體類(lèi):
package?com.wmyskxz.demo.entity;import?javax.persistence.Column;
import?javax.persistence.Entity;
import?javax.persistence.GeneratedValue;
import?javax.persistence.Id;
@Entity?//?表明這是個(gè)實(shí)體類(lèi)
public?class?User?{
????@Id?//?表明這個(gè)屬性是主鍵
????@GeneratedValue?//?自增長(zhǎng)
????private?long?id;
????@Column(nullable?=?false,?unique?=?true)????//?不允許為空,屬性唯一
????private?String?username;
????@Column(nullable?=?false)???//?不允許為空
????private?String?password;
????//?getter?and?setter
}
第四步:DAO層
新建一個(gè)【repository】包,然后新建一個(gè)【UserRepository】接口,并繼承JpaRepository類(lèi):
package?com.wmyskxz.demo.repository;import?com.wmyskxz.demo.entity.User;
import?org.springframework.data.jpa.repository.JpaRepository;
public?interface?UserRepository?extends?JpaRepository<User,?Long>?{
}
繼承JpaRepository需要傳入兩個(gè)參數(shù),一個(gè)是實(shí)體類(lèi)User一個(gè)是主鍵的類(lèi)型Long,而凡是繼承了JpaRepository類(lèi)的就會(huì)自動(dòng)實(shí)現(xiàn)很多內(nèi)置的方法,包括增刪改查,以及使用默認(rèn)支持的Pageable對(duì)象來(lái)進(jìn)行分頁(yè),默認(rèn)的方法大致如下:
public?interface?JpaRepository<T,?ID>?extends?PagingAndSortingRepository<T,?ID>,?QueryByExampleExecutor<T>?{????List<T>?findAll();
????List<T>?findAll(Sort?var1);
????List<T>?findAllById(Iterable<ID>?var1);
????<S?extends?T>?List<S>?saveAll(Iterable<S>?var1);
????void?flush();
????<S?extends?T>?S?saveAndFlush(S?var1);
????void?deleteInBatch(Iterable<T>?var1);
????void?deleteAllInBatch();
????T?getOne(ID?var1);
????<S?extends?T>?List<S>?findAll(Example<S>?var1);
????<S?extends?T>?List<S>?findAll(Example<S>?var1,?Sort?var2);
}
第五步:Controller層
新建【controller】包,新建一個(gè)【UserController】類(lèi),編寫(xiě)簡(jiǎn)單的增刪改查代碼:
package?com.wmyskxz.demo.controoler;import?com.wmyskxz.demo.entity.User;
import?com.wmyskxz.demo.repository.UserRepository;
import?org.springframework.beans.factory.annotation.Autowired;
import?org.springframework.data.domain.PageRequest;
import?org.springframework.data.domain.Sort;
import?org.springframework.web.bind.annotation.*;
import?java.util.Optional;
@RestController?//?表明這是一個(gè)Controller并返回JSON格式
public?class?UserController?{
????@Autowired
????private?UserRepository?userRepository;
????@GetMapping("/getOne")
????public?Optional<User>?getOneUserById(@RequestParam?long?id)?{
????????return?userRepository.findById(id);
????}
????@GetMapping("/all")
????public?Iterable<User>?getAllUsers(@RequestParam(value?=?"page",?defaultValue?=?"0")?int?page,
??????????????????????????????????????@RequestParam(value?=?"size",?defaultValue?=?"5")?int?size)?{
????????page?=?page?<?0???0?:?page;//?如果page為負(fù)數(shù)則修改為0,防止在首頁(yè)點(diǎn)擊上一頁(yè)發(fā)生錯(cuò)誤
????????Sort?sort?=?new?Sort(Sort.Direction.DESC,?"id");//?按id倒敘排列
????????return?userRepository.findAll(new?PageRequest(page,?size,?sort));
????}
????@PostMapping("/add")
????public?String?addUser(@RequestParam?String?username,
??????????????????????????@RequestParam?String?password)?{
????????User?user?=?new?User();
????????user.setUsername(username);
????????user.setPassword(password);
????????userRepository.save(user);//?注意這里是save
????????return?"Saved";
????}
????@DeleteMapping("/delete")
????public?String?deleteUserById(@RequestParam?long?id)?{
????????userRepository.deleteById(id);
????????return?"Deleted";
????}
????@PutMapping("/update")
????public?String?updateUser(User?user)?{
//????????User?user?=?new?User();
//????????user.setId(id);
//????????user.setUsername(username);
//????????user.setPassword(password);
????????userRepository.save(user);
????????return?"Updated";
????}
}
上面就直接使用@Autowired自動(dòng)引入了繼承了JpaRepository的UserRepository接口,我們使用它默認(rèn)的方法已經(jīng)足夠完成我們的基礎(chǔ)功能了,值得一提的是我們的getAllUsers(...)方法,它往findAll()方法里傳入了一個(gè)Pageable對(duì)象,這是Spring Data庫(kù)中定義的一個(gè)接口,是所有分頁(yè)相關(guān)信息的一個(gè)抽象,通過(guò)該接口,我們可以得到和分頁(yè)相關(guān)的所有信息(例如pageNumber、pageSize等),這樣Jpa就能夠通過(guò)Pageable參數(shù)來(lái)得到一個(gè)帶分頁(yè)信息的Sql語(yǔ)句。
當(dāng)然上面我們是通過(guò)自己創(chuàng)建了一個(gè)Pageable對(duì)象,Spring也支持直接獲取Pageable對(duì)象,可以把上面的getAllUsers(...)方法改寫(xiě)成下面這樣:
@GetMapping("/all")public?Iterable<User>?getAllUsers(@PageableDefault(value?=?5,?sort?=?{"id"},?direction?=?Sort.Direction.DESC)?
??????????????????????????????????????????????Pageable?pageable)?{
????return?userRepository.findAll(pageable);
}
默認(rèn)從第0頁(yè)開(kāi)始,也可以自己傳入一個(gè)page參數(shù),跟上面的是一樣的。
第六步:運(yùn)行項(xiàng)目
上面我們就快速搭建起來(lái)了一個(gè)基于Spring Boot和JPA的REST風(fēng)格的后臺(tái)增刪改查實(shí)例,我們把項(xiàng)目跑起來(lái),可以看到數(shù)據(jù)庫(kù)自動(dòng)創(chuàng)建了一些表:
JPA幫我們創(chuàng)建的user表的創(chuàng)建SQL如下:
CREATE?TABLE?`user`?(??`id`?bigint(20)?NOT?NULL,
??`password`?varchar(255)?NOT?NULL,
??`username`?varchar(255)?NOT?NULL,
??PRIMARY?KEY?(`id`),
??UNIQUE?KEY?`UK_sb8bbouer5wak8vyiiy4pf2bx`?(`username`)
)?ENGINE=InnoDB?DEFAULT?CHARSET=utf8;
使用REST測(cè)試工具測(cè)試
完全符合我們的要求,然后我們使用一些REST的測(cè)試工具,來(lái)測(cè)試上面的功能是否都能正確運(yùn)行,比如我這里使用的【Restlet Client】,在Chrome商店就可以下載到。
`/all`地址測(cè)試:
首先先來(lái)測(cè)試一下http://localhost:8080/all地址,由于現(xiàn)在數(shù)據(jù)庫(kù)還是空的,所以可以看到返回如下:
{????"content":?[
????],
????"pageable":?{
????????"sort":?{
????????????"sorted":?true,
????????????"unsorted":?false,
????????????"empty":?false
????????},
????????"offset":?0,
????????"pageNumber":?0,
????????"pageSize":?5,
????????"unpaged":?false,
????????"paged":?true
????},
????"totalElements":?0,
????"last":?true,
????"totalPages":?0,
????"number":?0,
????"size":?5,
????"sort":?{
????????"sorted":?true,
????????"unsorted":?false,
????????"empty":?false
????},
????"numberOfElements":?0,
????"first":?true,
????"empty":?true
}
添加用戶(hù)測(cè)試:
然后我們使用http://localhost:8080/add?username=wmyskxz&password=123地址,添加幾個(gè)類(lèi)似的用戶(hù)信息:
可以看到返回正確的Saved信息:
`/getOne`地址測(cè)試:
我們就直接使用http://localhost:8080/getOne?id=1來(lái)獲取剛才添加的用戶(hù),可以看到返回正確的數(shù)據(jù):
{????"id":?1,
????"username":?"wmyskxz",
????"password":?"123"
}
修改用戶(hù)測(cè)試:
然后我們使用http://localhost:8080/update?id=1&username=wmyskxz&password=123456來(lái)模擬進(jìn)行用戶(hù)密碼的修改:
可以看到正確的更新信息Updated,再次查詢(xún)用戶(hù),也能看到正確的數(shù)據(jù):
{????"id":?1,
????"username":?"wmyskxz",
????"password":?"123456"
}
分頁(yè)測(cè)試:
我們使用添加功能為數(shù)據(jù)庫(kù)添加5條以上的數(shù)據(jù),然后進(jìn)行一次查詢(xún)/all,可以看到能夠按照id倒敘排列后返回5條數(shù)據(jù):
數(shù)據(jù)庫(kù)的情況返回的JSON數(shù)據(jù)如下:
{????"content":?[
????????{
????????????"id":?10,
????????????"username":?"wmyskxz8",
????????????"password":?"123"
????????},
????????{
????????????"id":?9,
????????????"username":?"wmyskxz7",
????????????"password":?"123"
????????},
????????{
????????????"id":?8,
????????????"username":?"wmyskxz6",
????????????"password":?"123"
????????},
????????{
????????????"id":?7,
????????????"username":?"wmyskxz5",
????????????"password":?"123"
????????},
????????{
????????????"id":?6,
????????????"username":?"wmyskxz4",
????????????"password":?"123"
????????}
????],
????"pageable":?{
????????"sort":?{
????????????"sorted":?true,
????????????"unsorted":?false,
????????????"empty":?false
????????},
????????"offset":?0,
????????"pageNumber":?0,
????????"pageSize":?5,
????????"unpaged":?false,
????????"paged":?true
????},
????"totalElements":?9,
????"last":?false,
????"totalPages":?2,
????"number":?0,
????"size":?5,
????"sort":?{
????????"sorted":?true,
????????"unsorted":?false,
????????"empty":?false
????},
????"numberOfElements":?5,
????"first":?true,
????"empty":?false
}
刪除用戶(hù)測(cè)試:
使用地址http://localhost:8080/delete?id=1來(lái)刪除ID為1的用戶(hù):
能正確看到Deleted信息,并查看數(shù)據(jù)能夠看到數(shù)據(jù)已經(jīng)被刪除了。
以上,我們就快速搭建好了一個(gè)CRUD+分頁(yè)的后臺(tái)實(shí)例,還用了比較流行的RESTful風(fēng)格,粗略的感受了一下JPA的方便,還是挺爽的..沒(méi)有復(fù)雜的Mapper文件,不用自動(dòng)生成實(shí)體,甚至不用管SQL,只需要專(zhuān)注在邏輯上就行了,其實(shí)簡(jiǎn)單使用的話以上的東西也能應(yīng)付一些常見(jiàn)的場(chǎng)景了,后期再深入了解了解吧!
參考資料:
springboot(五):spring data jpa的使用——純潔的微笑
springboot(十五):springboot+jpa+thymeleaf增刪改查示例——純潔的微笑
Spring Boot中使用Spring-data-jpa讓數(shù)據(jù)訪問(wèn)更簡(jiǎn)單、更優(yōu)雅——程序猿DD
推薦閱讀
5G大規(guī)模商用來(lái)臨之前,你必須知道的幾個(gè)知識(shí)點(diǎn)
“離開(kāi)360時(shí),它只給了我一塊錢(qián)”
AI找Bug,一鍵快速預(yù)測(cè)
原子互換:一統(tǒng)公鏈江湖的神來(lái)之筆
春晚鬼畜 B 站日排行最高,趙本山:我的時(shí)代還沒(méi)有結(jié)束!
PDF翻譯神器,再也不擔(dān)心讀不懂英文Paper了
新聞聯(lián)播也可以拿來(lái)做數(shù)據(jù)分析?
高曉松侃5G!2019開(kāi)年大講揭示運(yùn)營(yíng)商的秘密
1.微信群:
添加小編微信:color_ld,備注“進(jìn)群+姓名+公司職位”即可,加入【云計(jì)算學(xué)習(xí)交流群】,和志同道合的朋友們共同打卡學(xué)習(xí)!
2.征稿:
投稿郵箱:liudan@csdn.net;微信號(hào):color_ld。請(qǐng)備注投稿+姓名+公司職位。
喜歡就點(diǎn)擊“好看”吧! 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的Spring-Data-JPA尝鲜:快速搭建CRUD+分页后台实例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 养老保险个人怎么交 有以下3点要搞清楚
- 下一篇: 从 0 到 300,Instagram