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