前言:因爲以前沒有接觸過Hibernate框架,可是最近看一些博客深深被它的「效率」所吸引,因此這就來跟你們一塊兒就着一個簡單的例子來嚐嚐Spring全家桶裏自帶的JPA的鮮java
JPA(Java Persistence API)是Sun官方提出的Java持久化規範。它爲Java開發人員提供了一種對象/關聯映射工具來管理Java應用中的關係數據。他的出現主要是爲了簡化現有的持久化開發工做和整合ORM技術,結束如今Hibernate,TopLink,JDO等ORM框架各自爲營的局面。值得注意的是,JPA是在充分吸取了現有Hibernate,TopLink,JDO等ORM框架的基礎上發展而來的,具備易於使用,伸縮性強等優勢。從目前的開發社區的反應上看,JPA受到了極大的支持和讚賞,其中就包括了Spring與EJB3.0的開發團隊。mysql
注意:JPA是一套規範,不是一套產品,那麼像Hibernate,TopLink,JDO他們是一套產品,若是說這些產品實現了這個JPA規範,那麼咱們就能夠叫他們爲JPA的實現產品。git
Spring Data JPA 是 Spring 基於 ORM 框架、JPA 規範的基礎上封裝的一套JPA應用框架,可以使開發者用極簡的代碼便可實現對數據的訪問和操做。它提供了包括增刪改查等在內的經常使用功能,且易於擴展!學習並使用 Spring Data JPA 能夠極大提升開發效率!(spring data jpa讓咱們解脫了DAO層的操做,基本上全部CRUD均可以依賴於它來實現)github
摘自:springboot(五):spring data jpa的使用——純潔的微笑web
因爲JPA底層幹活的仍然是Hibernate框架,而咱們以前學習的只有MyBatis相關的東西,因此在嚐鮮以前仍是有必要簡單瞭解一下二者的區別:spring
Hibernate的優點:sql
Hibernate的DAO層開發比MyBatis簡單,Mybatis須要維護SQL和結果映射。數據庫
Hibernate對對象的維護和緩存要比MyBatis好,對增刪改查的對象的維護要方便。緩存
Hibernate數據庫移植性很好,MyBatis的數據庫移植性很差,不一樣的數據庫須要寫不一樣SQL。springboot
Hibernate有更好的二級緩存機制,可使用第三方緩存。MyBatis自己提供的緩存機制不佳。
MyBatis的優點:
MyBatis能夠進行更爲細緻的SQL優化,能夠減小查詢字段。
MyBatis容易掌握,而Hibernate門檻較高。
簡單總結:
MyBatis:小巧、方便、高效、簡單、直接、半自動化
Hibernate:強大、方便、高效、複雜、間接、全自動化
引用自:【持久化框架】Mybatis與Hibernate的詳細對比——高亮
下面咱們來快速搭建一個使用Spring-DATA-JPA的CRUD+分頁後臺實例,而且咱們會直接使用到RESTful API(不熟悉的同窗[戳這裏]())
打開IDEA新建一個SpringBoot項目,不熟悉SpringBoot的同窗請右轉:【傳送門】,而後在pom.xml中添加如下依賴:
<!-- 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>
而後把application.properties弄成這個樣子:
#數據庫
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語句
spring.jpa.show-sql=true
#不加下面這句則默認建立MyISAM引擎的數據庫
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
#本身重寫的配置類,默認使用utf8編碼
spring.jpa.properties.hibernate.dialect=com.wmyskxz.demo.config.MySQLConfig
spring.jpa.properties.hibernate.hbm2ddl.auto
是hibernate的配置屬性,其主要做用是:自動建立、更新、驗證數據庫表結構。該參數的幾種配置以下:
create:每次加載hibernate時都會刪除上一次的生成的表,而後根據你的model類再從新來生成新表,哪怕兩次沒有任何改變也要這樣執行,這就是致使數據庫表數據丟失的一個重要緣由。
create-drop:每次加載hibernate時根據model類生成表,可是sessionFactory一關閉,表就自動刪除。
update:最經常使用的屬性,第一次加載hibernate時根據model類會自動創建起表的結構(前提是先創建好數據庫),之後加載hibernate時根據model類自動更新表結構,即便表結構改變了但表中的行仍然存在不會刪除之前的行。要注意的是當部署到服務器後,表結構是不會被立刻創建起來的,是要等應用第一次運行起來後纔會。
validate:每次加載hibernate時,驗證建立數據庫表結構,只會和數據庫中的表進行比較,不會建立新表,可是會插入新值。
而後新建一個【config】包,建立一個【MySQLConfig】類(上面的spring.jpa.properties.hibernate.dialect
屬性就要配置這裏的類全路徑):
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";
}
}
打開SQL服務,建表語句也很簡單啦:
create database testdb;
實體類映射的其實是數據庫表的結構,在適當的包目錄下(例如【entity】)下建立好實體類:
package com.wmyskxz.demo.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity // 代表這是個實體類
public class User {
@Id // 代表這個屬性是主鍵
@GeneratedValue // 自增加
private long id;
@Column(nullable = false, unique = true) // 不容許爲空,屬性惟一
private String username;
@Column(nullable = false) // 不容許爲空
private String password;
// getter and setter
}
新建一個【repository】包,而後新建一個【UserRepository】接口,並繼承JpaRepository類:
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須要傳入兩個參數,一個是實體類User一個是主鍵的類型Long,而凡是繼承了JpaRepository類的就會自動實現不少內置的方法,包括增刪改查,以及使用默認支持的Pageable對象來進行分頁,默認的方法大體以下:
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】包,新建一個【UserController】類,編寫簡單的增刪改查代碼:
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 // 代表這是一個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爲負數則修改成0,防止在首頁點擊上一頁發生錯誤
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
自動引入了繼承了JpaRepository的UserRepository接口,咱們使用它默認的方法已經足夠完成咱們的基礎功能了,值得一提的是咱們的getAllUsers(...)
方法,它往findAll()
方法裏傳入了一個Pageable對象,這是Spring Data庫中定義的一個接口,是全部分頁相關信息的一個抽象,經過該接口,咱們能夠獲得和分頁相關的全部信息(例如pageNumber
、pageSize
等),這樣Jpa就可以經過Pageable參數來獲得一個帶分頁信息的Sql語句。
固然上面咱們是經過本身建立了一個Pageable對象,Spring也支持直接獲取Pageable對象,能夠把上面的getAllUsers(...)
方法改寫成下面這樣:
@GetMapping("/all")
public Iterable<User> getAllUsers(@PageableDefault(value = 5, sort = {"id"}, direction = Sort.Direction.DESC)
Pageable pageable) {
return userRepository.findAll(pageable);
}
默認從第0頁開始,也能夠本身傳入一個page參數,跟上面的是同樣的。
上面咱們就快速搭建起來了一個基於Spring Boot和JPA的REST風格的後臺增刪改查實例,咱們把項目跑起來,能夠看到數據庫自動建立了一些表:
JPA幫咱們建立的user表的建立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的測試工具,來測試上面的功能是否都能正確運行,好比我這裏使用的【Restlet Client】,在Chrome商店就能夠下載到。
首先先來測試一下http://localhost:8080/all
地址,因爲如今數據庫仍是空的,因此能夠看到返回以下:
{
"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
}
而後咱們使用
能夠看到返回正確的Saved
信息:
咱們就直接使用http://localhost:8080/getOne?id=1
來獲取剛纔添加的用戶,能夠看到返回正確的數據:
{
"id": 1,
"username": "wmyskxz",
"password": "123"
}
而後咱們使用http://localhost:8080/update?id=1&username=wmyskxz&password=123456來模擬進行用戶密碼的修改:
能夠看到正確的更新信息Updated
,再次查詢用戶,也能看到正確的數據:
{
"id": 1,
"username": "wmyskxz",
"password": "123456"
}
咱們使用添加功能爲數據庫添加5條以上的數據,而後進行一次查詢/all
,能夠看到可以按照id
倒敘排列後返回5條數據:
返回的JSON數據以下:
{
"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
}
使用地址http://localhost:8080/delete?id=1來刪除ID爲1的用戶:
能正確看到Deleted
信息,並查看數據可以看到數據已經被刪除了。
以上,咱們就快速搭建好了一個CRUD+分頁的後臺實例,還用了比較流行的RESTful風格,粗略的感覺了一下JPA的方便,仍是挺爽的..沒有複雜的Mapper文件,不用自動生成實體,甚至不用管SQL,只須要專一在邏輯上就好了,其實簡單使用的話以上的東西也能應付一些常見的場景了,後期再深刻了解了解吧!
參考資料:
springboot(五):spring data jpa的使用——純潔的微笑
springboot(十五):springboot+jpa+thymeleaf增刪改查示例——純潔的微笑
Spring Boot中使用Spring-data-jpa讓數據訪問更簡單、更優雅——程序猿DD
歡迎轉載,轉載請註明出處!
簡書ID:@我沒有三顆心臟
github:wmyskxz
歡迎關注公衆微信號:wmyskxz
分享本身的學習 & 學習資料 & 生活
想要交流的朋友也能夠加qq羣:3382693
我沒有三顆心臟