SpringBoot是為了簡(jiǎn)化Spring應用的創(chuàng )建、運行、調試、部署等一系列問(wèn)題而誕生的產(chǎn)物,自動(dòng)裝配的特性讓我們可以更好的關(guān)注業(yè)務(wù)本身而不是外部的XML配置,我們只需遵循規范,引入相關(guān)的依賴(lài)就可以輕易的搭建出一個(gè) WEB 工程
上一篇介紹了Spring JdbcTemplate的使用,對比原始的JDBC而言,它更加的簡(jiǎn)潔。但隨著(zhù)表的增加,重復的CRUD工作讓我們苦不堪言,這時(shí)候Spring Data Jpa的作用就體現出來(lái)了…..
JPA是Java Persistence API的簡(jiǎn)稱(chēng),中文名Java持久層API,是官方(Sun)在JDK5.0后提出的Java持久化規范。其目的是為了簡(jiǎn)化現有JAVA EE和JAVA SE應用開(kāi)發(fā)工作,以及整合現有的ORM技術(shù)實(shí)現規范統一
JPA的總體思想和現有
Hibernate、TopLink、JDO等ORM框架大體一致??偟膩?lái)說(shuō),JPA包括以下3方面的技術(shù):
ORM映射元數據: 支持XML和注解兩種元數據的形式,元數據描述對象和表之間的映射關(guān)系,框架據此將實(shí)體對象持久化到數據庫表中;
API: 操作實(shí)體對象來(lái)執行CRUD操作,框架在后臺替代我們完成所有的事情,開(kāi)發(fā)者從繁瑣的JDBC和SQL代碼中解脫出來(lái)。
查詢(xún)語(yǔ)言: 通過(guò)面向對象而非面向數據庫的查詢(xún)語(yǔ)言查詢(xún)數據,避免程序的SQL語(yǔ)句緊密耦合。
JPA只是一種規范,它需要第三方自行實(shí)現其功能,在眾多框架中Hibernate是最為強大的一個(gè)。從功能上來(lái)說(shuō),JPA就是Hibernate功能的一個(gè)子集。Hibernate 從3.2開(kāi)始,就開(kāi)始兼容JPA。同時(shí)Hibernate3.2獲得了Sun TCK的JPA(Java Persistence API) 兼容認證。
常見(jiàn)的ORM框架中Hibernate的JPA最為完整,因此Spring Data JPA 是采用基于JPA規范的Hibernate框架基礎下提供了Repository層的實(shí)現。Spring Data Repository極大地簡(jiǎn)化了實(shí)現各種持久層的數據庫訪(fǎng)問(wèn)而寫(xiě)的樣板代碼量,同時(shí)CrudRepository提供了豐富的CRUD功能去管理實(shí)體類(lèi)。
優(yōu)點(diǎn)
豐富的API,簡(jiǎn)單操作無(wú)需編寫(xiě)額外的代碼
豐富的SQL日志輸出
缺點(diǎn)
學(xué)習成本較大,需要學(xué)習HQL
配置復雜,雖然SpringBoot簡(jiǎn)化的大量的配置,關(guān)系映射多表查詢(xún)配置依舊不容易
性能較差,對比JdbcTemplate、Mybatis等ORM框架,它的性能無(wú)異于是最差的
在 pom.xml 中添加 spring-boot-starter-data-jpa 的依賴(lài)
<!-- Spring JDBC 的依賴(lài)包,使用 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa 將會(huì )自動(dòng)獲得HikariCP依賴(lài) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MYSQL包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 默認就內嵌了Tomcat 容器,如需要更換容器也極其簡(jiǎn)單-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 測試包,當我們使用 mvn package 的時(shí)候該包并不會(huì )被打入,因為它的生命周期只在 test 之內-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
在application.properties中添加如下配置。值得注意的是,SpringBoot默認會(huì )自動(dòng)配置DataSource,它將優(yōu)先采用HikariCP連接池,如果沒(méi)有該依賴(lài)的情況則選取tomcat-jdbc,如果前兩者都不可用最后選取Commons DBCP2。通過(guò)spring.datasource.type屬性可以指定其它種類(lèi)的連接池
spring.datasource.url=jdbc:mysql://localhost:3306/chapter5?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
spring.datasource.password=root
spring.datasource.username=root
#spring.datasource.type
# JPA配置
spring.jpa.hibernate.ddl-auto=update
# 輸出日志
spring.jpa.show-sql=true
# 數據庫類(lèi)型
spring.jpa.database=mysql
ddl-auto 幾種屬性
create: 每次運行程序時(shí),都會(huì )重新創(chuàng )建表,故而數據會(huì )丟失
create-drop: 每次運行程序時(shí)會(huì )先創(chuàng )建表結構,然后待程序結束時(shí)清空表
upadte: 每次運行程序,沒(méi)有表時(shí)會(huì )創(chuàng )建表,如果對象發(fā)生改變會(huì )更新表結構,原有數據不會(huì )清空,只會(huì )更新(推薦使用)
validate: 運行程序會(huì )校驗數據與數據庫的字段類(lèi)型是否相同,字段不同會(huì )報錯
由于上面我們采用的是spring.jpa.hibernate.ddl-auto=update方式,因此這里可以跳過(guò)手動(dòng)建表的操作
JPA規范注解坐落在javax.persistence包下,@Id注解一定不要引用錯了,否則會(huì )報錯。@GeneratedValue(strategy = GenerationType.IDENTITY)自增策略,不需要映射的字段可以通過(guò)@Transient注解排除掉
常見(jiàn)的幾種自增策略
TABLE: 使用一個(gè)特定的數據庫表格來(lái)保存主鍵
SEQUENCE: 根據底層數據庫的序列來(lái)生成主鍵,條件是數據庫支持序列。這個(gè)值要與generator一起使用,generator 指定生成主鍵使用的生成器(可能是orcale中自己編寫(xiě)的序列)。
IDENTITY: 主鍵由數據庫自動(dòng)生成(主要是支持自動(dòng)增長(cháng)的數據庫,如mysql)
AUTO: 主鍵由程序控制,也是GenerationType的默認值。
package com.battcn.entity;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import java.io.Serializable;
/**
* @author Levin
* @since 2018/5/7 0007
*/
@Entity(name = 't_user')
public class User implements Serializable {
private static final long serialVersionUID = 8655851615465363473L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
/**
* TODO 忽略該字段的映射
*/
@Transient
private String email;
// TODO 省略get set
}
創(chuàng )建UserRepository數據訪(fǎng)問(wèn)層接口,需要繼承JpaRepository<T,K>,第一個(gè)泛型參數是實(shí)體對象的名稱(chēng),第二個(gè)是主鍵類(lèi)型。只需要這樣簡(jiǎn)單的配置,該UserRepository就擁常用的CRUD功能,JpaRepository本身就包含了常用功能,剩下的查詢(xún)我們按照規范寫(xiě)接口即可,JPA支持@Query注解寫(xiě)HQL,也支持findAllByUsername這種根據字段名命名的方式(強烈推薦IntelliJ IDEA對JPA支持非常NICE)
package com.battcn.repository;
import com.battcn.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* t_user 操作
*
* @author Levin
* @since 2018/5/7 0007
*/
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
/**
* 根據用戶(hù)名查詢(xún)用戶(hù)信息
*
* @param username 用戶(hù)名
* @return 查詢(xún)結果
*/
List<User> findAllByUsername(String username);
}
完成數據訪(fǎng)問(wèn)層接口后,最后編寫(xiě)一個(gè)junit測試類(lèi)來(lái)檢驗代碼的正確性。
下面的幾個(gè)操作中,只有findAllByUsername是我們自己編寫(xiě)的代碼,其它的都是繼承自JpaRepository接口中的方法,更關(guān)鍵的是分頁(yè)及排序是如此的簡(jiǎn)單實(shí)例化一個(gè)Pageable即可…
package com.battcn;
import com.battcn.entity.User;
import com.battcn.repository.UserRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
/**
* @author Levin
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Chapter5ApplicationTests {
private static final Logger log = LoggerFactory.getLogger(Chapter5ApplicationTests.class);
@Autowired
private UserRepository userRepository;
@Test
public void test1() throws Exception {
final User user = userRepository.save(new User('u1', 'p1'));
log.info('[添加成功] - [{}]', user);
final List<User> u1 = userRepository.findAllByUsername('u1');
log.info('[條件查詢(xún)] - [{}]', u1);
Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Order.desc('username')));
final Page<User> users = userRepository.findAll(pageable);
log.info('[分頁(yè) 排序 查詢(xún)所有] - [{}]', users.getContent());
userRepository.findById(users.getContent().get(0).getId()).ifPresent(user1 -> log.info('[主鍵查詢(xún)] - [{}]', user1));
final User edit = userRepository.save(new User(user.getId(), '修改后的ui', '修改后的p1'));
log.info('[修改成功] - [{}]', edit);
userRepository.deleteById(user.getId());
log.info('[刪除主鍵為 {} 成功] - [{}]', user.getId());
}
}
更多內容請參考官方文檔
目前很多大佬都寫(xiě)過(guò)關(guān)于 SpringBoot 的教程了,如有雷同,請多多包涵,本教程基于最新的 spring-boot-starter-parent:2.0.1.RELEASE編寫(xiě),包括新版本的特性都會(huì )一起介紹…
全文代碼:https://github.com/battcn/spring-boot2-learning/tree/master/chapter5
如果你對 Dubbo 感興趣,歡迎加入我的知識星球一起交流。
目前在知識星球(https://t.zsxq.com/2VbiaEu)更新了如下 Dubbo 源碼解析如下:
01. 調試環(huán)境搭建
02. 項目結構一覽
03. 配置 Configuration
04. 核心流程一覽
05. 拓展機制 SPI
06. 線(xiàn)程池
07. 服務(wù)暴露 Export
08. 服務(wù)引用 Refer
09. 注冊中心 Registry
10. 動(dòng)態(tài)編譯 Compile
11. 動(dòng)態(tài)代理 Proxy
12. 服務(wù)調用 Invoke
13. 調用特性
14. 過(guò)濾器 Filter
15. NIO 服務(wù)器
16. P2P 服務(wù)器
17. HTTP 服務(wù)器
18. 序列化 Serialization
19. 集群容錯 Cluster
20. 優(yōu)雅停機
21. 日志適配
22. 狀態(tài)檢查
23. 監控中心 Monitor
24. 管理中心 Admin
25. 運維命令 QOS
26. 鏈路追蹤 Tracing
聯(lián)系客服