一起來學SpringBoot | 第五篇:整合SpringDataJpa

SpringBoot 是為了簡化 Spring 應用的創(chuàng)建福澡、運行万栅、調試、部署等一系列問題而誕生的產物悠鞍,自動裝配的特性讓我們可以更好的關注業(yè)務本身而不是外部的XML配置染簇,我們只需遵循規(guī)范参滴,引入相關的依賴就可以輕易的搭建出一個 WEB 工程

上一篇介紹了Spring JdbcTemplate的使用,對比原始的JDBC而言锻弓,它更加的簡潔砾赔。但隨著表的增加,重復的CRUD工作讓我們苦不堪言青灼,這時候Spring Data Jpa的作用就體現(xiàn)出來了…..

JPA

JPA是Java Persistence API的簡稱暴心,中文名Java持久層API,是官方(Sun)在JDK5.0后提出的Java持久化規(guī)范杂拨。其目的是為了簡化現(xiàn)有JAVA EEJAVA SE應用開發(fā)工作专普,以及整合現(xiàn)有的ORM技術實現(xiàn)規(guī)范統(tǒng)一

JPA的總體思想和現(xiàn)有HibernateTopLink弹沽、JDO等ORM框架大體一致檀夹。總的來說策橘,JPA包括以下3方面的技術:

  • ORM映射元數(shù)據(jù): 支持XML和注解兩種元數(shù)據(jù)的形式炸渡,元數(shù)據(jù)描述對象和表之間的映射關系,框架據(jù)此將實體對象持久化到數(shù)據(jù)庫表中丽已;
  • API: 操作實體對象來執(zhí)行CRUD操作偶摔,框架在后臺替代我們完成所有的事情,開發(fā)者從繁瑣的JDBC和SQL代碼中解脫出來促脉。
  • 查詢語言: 通過面向對象而非面向數(shù)據(jù)庫的查詢語言查詢數(shù)據(jù)辰斋,避免程序的SQL語句緊密耦合。

JPA只是一種規(guī)范瘸味,它需要第三方自行實現(xiàn)其功能宫仗,在眾多框架中Hibernate是最為強大的一個。從功能上來說旁仿,JPA就是Hibernate功能的一個子集藕夫。Hibernate 從3.2開始,就開始兼容JPA枯冈。同時Hibernate3.2獲得了Sun TCK的JPA(Java Persistence API) 兼容認證毅贮。

Spring Data JPA

常見的ORM框架中Hibernate的JPA最為完整,因此Spring Data JPA 是采用基于JPA規(guī)范的Hibernate框架基礎下提供了Repository層的實現(xiàn)尘奏。Spring Data Repository極大地簡化了實現(xiàn)各種持久層的數(shù)據(jù)庫訪問而寫的樣板代碼量滩褥,同時CrudRepository提供了豐富的CRUD功能去管理實體類。

優(yōu)點

  • 豐富的API炫加,簡單操作無需編寫額外的代碼
  • 豐富的SQL日志輸出

缺點

  • 學習成本較大瑰煎,需要學習HQL
  • 配置復雜,雖然SpringBoot簡化的大量的配置俗孝,關系映射多表查詢配置依舊不容易
  • 性能較差酒甸,對比JdbcTemplateMybatis等ORM框架赋铝,它的性能無異于是最差的

導入依賴

pom.xml 中添加 spring-boot-starter-data-jpa 的依賴

<!-- Spring JDBC 的依賴包插勤,使用 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa 將會自動獲得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>
<!-- 默認就內嵌了Tomcat 容器,如需要更換容器也極其簡單-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 測試包,當我們使用 mvn package 的時候該包并不會被打入,因為它的生命周期只在 test 之內-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

連接數(shù)據(jù)庫
在application.properties中添加如下配置革骨。值得注意的是农尖,SpringBoot默認會自動配置DataSource,它將優(yōu)先采用HikariCP連接池苛蒲,如果沒有該依賴的情況則選取tomcat-jdbc卤橄,如果前兩者都不可用最后選取Commons DBCP2。通過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ù)庫類型
spring.jpa.database=mysql

ddl-auto 幾種屬性

  • create: 每次運行程序時臂外,都會重新創(chuàng)建表窟扑,故而數(shù)據(jù)會丟失
  • create-drop: 每次運行程序時會先創(chuàng)建表結構,然后待程序結束時清空表
  • upadte: 每次運行程序漏健,沒有表時會創(chuàng)建表嚎货,如果對象發(fā)生改變會更新表結構,原有數(shù)據(jù)不會清空蔫浆,只會更新(推薦使用)
  • validate: 運行程序會校驗數(shù)據(jù)與數(shù)據(jù)庫的字段類型是否相同殖属,字段不同會報錯

具體編碼

由于上面我們采用的是spring.jpa.hibernate.ddl-auto=update方式,因此這里可以跳過手動建表的操作

實體類

JPA規(guī)范注解坐落在javax.persistence包下瓦盛,@Id注解一定不要引用錯了洗显,否則會報錯外潜。@GeneratedValue(strategy = GenerationType.IDENTITY)自增策略,不需要映射的字段可以通過@Transient注解排除掉
常見的幾種自增策略

TABLE: 使用一個特定的數(shù)據(jù)庫表格來保存主鍵
SEQUENCE: 根據(jù)底層數(shù)據(jù)庫的序列來生成主鍵挠唆,條件是數(shù)據(jù)庫支持序列处窥。這個值要與generator一起使用,generator 指定生成主鍵使用的生成器(可能是orcale中自己編寫的序列)玄组。
IDENTITY: 主鍵由數(shù)據(jù)庫自動生成(主要是支持自動增長的數(shù)據(jù)庫滔驾,如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
 */
@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ù)訪問層接口哆致,需要繼承JpaRepository<T,K>,第一個泛型參數(shù)是實體對象的名稱患膛,第二個是主鍵類型摊阀。只需要這樣簡單的配置,該UserRepository就擁常用的CRUD功能剩瓶,JpaRepository本身就包含了常用功能驹溃,剩下的查詢我們按照規(guī)范寫接口即可,JPA支持@Query注解寫HQL延曙,也支持findAllByUsername這種根據(jù)字段名命名的方式(強烈推薦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 
 */
@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    /**
     * 根據(jù)用戶名查詢用戶信息
     *
     * @param username 用戶名
     * @return 查詢結果
     */
    List<User> findAllByUsername(String username);
}

測試
完成數(shù)據(jù)訪問層接口后豌鹤,最后編寫一個junit測試類來檢驗代碼的正確性。

下面的幾個操作中枝缔,只有findAllByUsername是我們自己編寫的代碼布疙,其它的都是繼承自JpaRepository接口中的方法,更關鍵的是分頁及排序是如此的簡單實例化一個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("[分頁+排序+查詢所有] - [{}]", 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());
    }
}

總結

更多內容請參考官方文檔

目前很多大佬都寫過關于 SpringBoot 的教程了愿卸,如有雷同灵临,請多多包涵,本教程基于最新的 spring-boot-starter-parent:2.0.1.RELEASE編寫趴荸,包括新版本的特性都會一起介紹…

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末儒溉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子发钝,更是在濱河造成了極大的恐慌顿涣,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酝豪,死亡現(xiàn)場離奇詭異涛碑,居然都是意外死亡,警方通過查閱死者的電腦和手機孵淘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門蒲障,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事揉阎∽椋” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵余黎,是天一觀的道長重窟。 經常有香客問我,道長惧财,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任扭仁,我火速辦了婚禮垮衷,結果婚禮上,老公的妹妹穿的比我還像新娘乖坠。我一直安慰自己搀突,他們只是感情好,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布熊泵。 她就那樣靜靜地躺著仰迁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪顽分。 梳的紋絲不亂的頭發(fā)上徐许,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機與錄音卒蘸,去河邊找鬼雌隅。 笑死,一個胖子當著我的面吹牛缸沃,可吹牛的內容都是我干的恰起。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼趾牧,長吁一口氣:“原來是場噩夢啊……” “哼检盼!你這毒婦竟也來了?” 一聲冷哼從身側響起翘单,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吨枉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后县恕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體东羹,經...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年忠烛,在試婚紗的時候發(fā)現(xiàn)自己被綠了属提。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖冤议,靈堂內的尸體忽然破棺而出斟薇,到底是詐尸還是另有隱情,我是刑警寧澤恕酸,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布堪滨,位于F島的核電站,受9級特大地震影響蕊温,放射性物質發(fā)生泄漏袱箱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一义矛、第九天 我趴在偏房一處隱蔽的房頂上張望发笔。 院中可真熱鬧,春花似錦凉翻、人聲如沸了讨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽前计。三九已至,卻和暖如春垃杖,著一層夾襖步出監(jiān)牢的瞬間男杈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工缩滨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留势就,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓脉漏,卻偏偏與公主長得像苞冯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子侧巨,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359