一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - SpringBoot整合SpringDataJPA

SpringBoot整合SpringDataJPA

2021-10-13 14:54大仙~猛 Java教程

這篇文章主要介紹了SpringBoot整合SpringDataJPA代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

SpringBoot整合JPA

使用數據庫是開發基本應用的基礎,借助于開發框架,我們已經不用編寫原始的訪問數據庫的代碼,也不用調用JDBC(Java Data Base Connectivity)或者連接池等諸如此類的被稱作底層的代碼,我們將從更高的層次上訪問數據庫,這在Springboot中更是如此,本章我們將詳細介紹在Springboot中使用 Spring Data JPA 來實現對數據庫的操作。

JPA & Spring Data JPA

JPA是Java Persistence API的簡稱,中文名Java持久層API,是Sun官方提出的Java持久化規范.

其設計目標主要是為了簡化現有的持久化開發工作和整合ORM技術。

JPA使用XML文件或注解(JDK 5.0或更高版本)來描述對象-關聯表的映射關系,能夠將運行期的實體對象持久化到數據庫,它為Java開發人員提供了一種ORM工具來管理Java應用中的關系數據。

簡單地說,JPA就是為POJO(Plain Ordinary Java Object)提供持久化的標準規范,即將Java的普通對象通過對象關系映射(Object-Relational Mapping,ORM)持久化到數據庫中。

由于JPA是在充分吸收了現有Hibernate,TopLink,JDO等ORM框架的基礎上發展而來的,因而具有易于使用、伸縮性強等優點。

Spring Data JPA 是 Spring 基于 Spring Data 框架、在JPA 規范的基礎上開發的一個框架,使用 Spring Data JPA 可以極大地簡化JPA 的寫法,可以在幾乎不用寫實現的情況下實現對數據庫的訪問和操作,除了CRUD外,還包括分頁和排序等一些常用的功能。

Spring Data JPA 還提供了對分頁查詢、自定義SQL、查詢指定N條記錄、聯表查詢等功能的支持

JPA不是一種新的ORM框架,它的出現只是用于規范現有的ORM技術,它不能取代現有的Hibernate、TopLink等框架。相反,在采用JPA開發時,我們將仍將使用到這些ORM框架,只是此時開發出來的應用不再依賴于某個持久化提供商。應用可以在不修改代碼的情況下在任何JPA環境下運行,真正做到低耦合,可擴展的程序設計。

Hibernate & JPA

1、JPA

全稱Java Persistence API,通過JDK 5.0注解或XML描述對象-關系表的映射關系,并將運行期的實體對象持久化到數據庫中。

JPA的出現有兩個原因:

其一,簡化現有Java EE和Java SE應用的對象持久化的開發工作;

其二,Sun希望整合對ORM技術,實現持久化領域的統一。

JPA提供的技術:

1)ORM映射元數據:JPA支持XML和JDK 5.0注解兩種元數據的形式,元數據描述對象和表之間的映射關系,框架據此將實體對象持久化到數據庫表中;

2)JPA 的API:用來操作實體對象,執行CRUD操作,框架在后臺替我們完成所有的事情,開發者從繁瑣的JDBC和SQL代碼中解脫出來。

3)查詢語言:通過面向對象而非面向數據庫的查詢語言查詢數據,避免程序的SQL語句緊密耦合。

2、JPA & Hibernate 關系

JPA是規范,Hibernate是框架,JPA是持久化規范,而Hibernate實現了JPA。

Hibernate VS Mybatis

Mybatis:小巧、方便、高效、簡單、直接、半自動

Hibernate:強大、方便、高效、復雜、繞彎子、全自動

一、導入依賴

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<dependencies>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.76</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.21</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

二、簡單的CRUD

1、配置文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/shy
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    hibernate:
      #定義數據庫表的生成策略 create 創建一個表 update 更新或者創建數據表
      ddl-auto: update
      #控制臺顯示sql語句
    show-sql: true
server:
  port: 80

其中,spring.jpa.hibernate.ddl-auto 參數用來配置是否開啟自動更新數據庫表結構,可取create、create-drop、update、validate、none五個值。

  • create 每次加載hibernate時,先刪除已存在的數據庫表結構再重新生成;
  • create-drop 每次加載hibernate時,先刪除已存在的數據庫表結構再重新生成,并且當 sessionFactory關閉時自動刪除生成的數據庫表結構;
  • update 只在第一次加載hibernate時自動生成數據庫表結構,以后再次加載hibernate時根據model類自動更新表結構;
  • validate 每次加載hibernate時,驗證數據庫表結構,只會和數據庫中的表進行比較,不會創建新表,但是會插入新值。
  • none 關閉自動更新

2、實體類

Shop:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.shy.entity;
import lombok.Data;
import javax.persistence.*;
@Data
//使用jpa注解 配置映射關系
@Entity//告訴jpa這是一個實體類 和數據表映射的類
public class Shop{
    @Id//表明這是以一個主鍵
    @GeneratedValue(strategy = GenerationType.IDENTITY)//自增
    private Integer shopId;
    @Column(length = 20)
    private String shopName;
    private double price;
    private Integer shopClassId;
    private Integer num;
}

ShopClass,商品類別

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.shy.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Data
@Entity
public class ShopClass {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer shopClassId;
    private String shopClassName;
}

3、Dao層

編寫dao繼承JpaRepository類,泛型傳入 要操作的實體類,和主鍵類型

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.example.dao;
import com.shy.entity.Shop;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
/* 參數一 T :當前需要映射的實體
 * 參數二 ID :當前映射的實體中的OID(映射對象標識符,數據庫主鍵)的類型*/
@Repository
public interface ShopRepository extends JpaRepository<Shop,Integer> {
    /*
     * 我們在這里直接繼承 JpaRepository
     * 這里面已經有很多現成的方法了
     * 這也是JPA的一大優點
     * 我們可以直接使用這些方法,包括其父類的好多方法。
     * */
}

JpaRepository:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package org.springframework.data.jpa.repository;
import java.util.List;
import javax.persistence.EntityManager;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.QueryByExampleExecutor;
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
    @Override
    List<T> findAll();// 查詢所有實體
    @Override
    List<T> findAll(Sort sort);// 查詢所有實體并排序
    @Override
    List<T> findAllById(Iterable<ID> ids);// 根據ID集合查詢實體
    @Override
    <S extends T> List<S> saveAll(Iterable<S> entities);// 保存并返回(修改后的)實體集合
    void flush();// 提交事務
    <S extends T> S saveAndFlush(S entity); // 保存實體并立即提交事務
    <S extends T> List<S> saveAllAndFlush(Iterable<S> entities);
    @Deprecated
    default void deleteInBatch(Iterable<T> entities){deleteAllInBatch(entities);}
    void deleteAllInBatch(Iterable<T> entities); // 批量刪除實體集合
    void deleteAllByIdInBatch(Iterable<ID> ids);
    void deleteAllInBatch();// 批量刪除所有實體
    @Deprecated
    T getOne(ID id);// 根據ID查詢實體
    T getById(ID id);
    @Override
    <S extends T> List<S> findAll(Example<S> example);// 查詢與指定Example匹配的所有實體
    @Override
    <S extends T> List<S> findAll(Example<S> example, Sort sort);// 查詢與指定Example匹配的所有實體并排序
}

4、service層

service:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.shy.service;
import com.shy.entity.Shop;
import com.shy.vo.ShopAndShopClassVo;
import java.util.List;
public interface ShopService {
    //查詢所有商品
    List<Shop> findAll();
    //增加商品
    Shop addShop(Shop shop);
    //通過商品id修改商品名
    Shop updateShop();
    //通過商品id刪除商品
    void delShop(Integer id);
}

Impl:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.shy.service;
import com.shy.dao.ShopRepository;
import com.shy.entity.Shop;
import com.shy.vo.ShopAndShopClassVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ShopServiceImpl implements ShopService{
    @Autowired
    private ShopRepository shopRepository;
    @Override
    public List<Shop> findAll() {
        return shopRepository.findAll();
    }
    @Override
    public Shop addShop(Shop shop) {
        shop.setPrice(333);
        shop.setShopClassId(3);
        shop.setNum(30);
        shop.setShopName("耳機");
        return shopRepository.save(shop);
    }
    @Override
    public Shop updateShop() {
        Shop shop = new Shop();
        shop.setShopId(11);
        shop.setShopName("平板");
        shop.setShopClassId(3);
        shop.setNum(40);
        return shopRepository.save(shop);
    }
    @Override
    public void delShop(Integer id) {
        shopRepository.deleteById(id);
        System.out.println("刪除成功");
    }
}

5、controller

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.shy.controller;
import com.alibaba.fastjson.JSON;
import com.shy.entity.Shop;
import com.shy.service.ShopService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ShopController {
    @Autowired
    private ShopService shopService;
    @GetMapping("/list")
    public String findAll(){
        return JSON.toJSONString(shopService.findAll());
    }
    @GetMapping("/save")
    public String save(Shop shop){
        return JSON.toJSONString(shopService.addShop(shop));
    }
    @GetMapping("/saveAndFlush")
    public String saveAndFlush(){
        return JSON.toJSONString(shopService.updateShop());
    }
    @GetMapping("/delShop/{id}")
    public void delShop(@PathVariable Integer id){
        shopService.delShop(id);
    }
}

全程用postman測試

三、自定義SQL

在ShopRepository中添加

?
1
2
3
4
5
6
7
8
9
//使用原生sql需要加上,nativeQuery = true
//?1代表第一個參數
@Query(value="select * from shop where shop.price = ?1",nativeQuery = true)
Shop findByPrice(Double price);
//修改商品,@Modifying+@Query執行更新操作,serviceImpl不要忘記加上,要使用hql的話,需要把entity別名刪掉
@Transactional//設計修改表的操作需要開啟事務支持
@Modifying//這個注解只支持返回值為int/Integer
@Query("update Shop s set s.shopName = ?1 where s.shopId = ?2")
int updateshop2(String name,Integer shopId);

service:

?
1
2
3
4
//通過價格查詢商品
Shop findByPrice(Double price);
//修改商品名原生sql方法
int updateshop2(String name,Integer shopId);

Impl:

?
1
2
3
4
5
6
7
8
@Override
public Shop findByPrice(Double price) {
    return shopRepository.findByPrice(price);
}
@Override
public int updateshop2(String name, Integer shopId) {
    return shopRepository.updateshop2(name, shopId);
}

controller:

?
1
2
3
4
5
6
7
8
9
@GetMapping("/listPrice/{price}")
public String findByPrice(@PathVariable Double price){
    return JSON.toJSONString(shopService.findByPrice(price));
}
@GetMapping("/saveAndFlush2/{id}/{name}")
public String saveAndFlush2(@PathVariable(value = "id") Integer shopId,
                           @PathVariable String name){
    return shopService.updateshop2(name, shopId)>0?"修改成功":"修改失敗";
}

四、分頁查詢

Pageable 是 Spring 封裝的分頁實現類,使用的時候需要傳入頁數、每頁條數和排序規則。

Spring Data JPA 已經幫我們內置了分頁功能,在查詢的方法中,需要傳入參數 Pageable,當查詢中有多個參數的時候 Pageable 建議作為最后一個參數傳入,

Pageable使用的時候需要傳入頁數、每頁條數和排序規則,排序規則可省略

service:

?
1
2
3
4
5
6
7
8
/**
   * 分頁查詢
   * @param pageNo 第幾頁
   * @param pageSize 每頁有多少條數據
   * @param pageable Spring 封裝的分頁實現類
   * @return 數據
   */
  Page<Shop> pageShop(Integer pageNo,Integer pageSize,Pageable pageable);

Impl:

?
1
2
3
4
5
6
7
@Override
public Page<Shop> pageShop(Integer pageNo, Integer pageSize, Pageable pageable) {
    //注意排序這找的是實體類中的字段,不是數據庫里的
    //分頁頁碼從0開始
    pageable = PageRequest.of(pageNo,pageSize, Sort.Direction.DESC, "shopId");
    return shopRepository.findAll(pageable);
}

controller:

?
1
2
3
4
5
@GetMapping("/pageShop/{pageNo}/{pageSize}")
public String pageShop(@PathVariable Integer pageNo,
                       @PathVariable Integer pageSize,Pageable pageable){
    return JSON.toJSONString(shopService.pageShop(pageNo, pageSize, pageable));
}

五、連表查詢

VO(value object)值對象

  • 通常用于業務層之間的數據傳遞,僅僅包含數據而已
  • View object:視圖對象

接受頁面傳遞來的對象,封裝對象

將業務處理完成的對象,封裝成頁面要用的數據

創建ShopAndShopClassVo用來接收連表查詢后的結果

entity,這里的有參構造必須加,要往里賦值

?
1
2
3
4
5
6
7
8
9
10
11
12
package com.shy.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ShopAndShopClassVo {
    private String shopName;
    private double price;
    private String shopClassName;
}

ShopRepository:

?
1
2
3
4
//連表查詢
@Query("select new com.shy.vo.ShopAndShopClassVo(s.shopName,s.price,sc.shopClassName) from Shop             s,ShopClass sc " +
        "where s.shopClassId=sc.shopClassId and sc.shopClassName=?1")
List<ShopAndShopClassVo> findShopInfo(String shopClassName);

JPQL進行查詢,它的特征就是與原生SQL語句類似,完全面向對象,通過類名和屬性訪問,而不是表名和表屬性

service:

?
1
2
//連表查詢
List<ShopAndShopClassVo> findShopInfo(String shopClassName);

Impl:

?
1
2
3
4
@Override
public List<ShopAndShopClassVo> findShopInfo(String shopClassName) {
    return shopRepository.findShopInfo(shopClassName);
}

controller:

?
1
2
3
4
@GetMapping("/andFind/{name}")
public String findShopInfo(@PathVariable("name") String shopClassName){
    return JSON.toJSONString(shopService.findShopInfo(shopClassName));
}

六、分組查詢

接收數據的另一種寫法,創建一個結果集的接口來接收連表查詢后的結果

定義一個結果集的接口類,接口類的內容來自于商品表和商品類別表。

entity:

?
1
2
3
4
5
package com.shy.entity;
public interface GroupShop {
    String getNum();
    String getShopClassName();
}

在運行中 Spring 會給接口(GroupShop)自動生產一個代理類來接收返回的結果,代碼中使用 getXX 的形式來獲取。

ShopRepository:

?
1
2
3
//分組查詢
@Query("select count(s.shopName) as 商品數量,sc.shopClassName as 類別名稱 from Shop s,ShopClass sc where s.shopClassId=sc.shopClassId group by s.shopClassId")
List<GroupShop> groupShop();

service:

?
1
2
//分組查詢
List<GroupShop> groupShop();

Impl:

?
1
2
3
4
@Override
public List<GroupShop> groupShop() {
    return shopRepository.groupShop();
}

controller:

?
1
2
3
4
@GetMapping("/groupShop")
public String groupShop(){
    return JSON.toJSONString(shopService.groupShop());
}

七、與mybatis對比

  • jpa是對象與對象之間的映射,而mybatis是對象和結果集的映射
  • jpa移植性比較好,不用關心用什么數據庫,因為mybatis自由寫sql語句,所以當項目移植的時候還需要改sql。
  • 修改字段時JPA更簡單,mybatis需要修改一堆的xml,mapper等文件很麻煩。
  • mybatis自定義sql,比較靈活,也可以寫復雜的sql,JPA只適合簡單的單表sql

總結

mybatis和JPA各有優勢,如果sql簡單,則jpa使用效率更高,如果sql較復雜,需要自定義,則使用mybatis更加順手。

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!

原文鏈接:https://blog.csdn.net/CSDN_SHY/article/details/117923206

延伸 · 閱讀

精彩推薦
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7472021-02-04
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
主站蜘蛛池模板: 亚洲高清成人 | 成人免费一区二区三区在线观看 | 日本69av| 男女男精品网站免费观看 | 国产麻豆91网在线看 | 美女叽叽| 91久久青青青国产免费 | 贰佰麻豆剧果冻传媒一二三区 | 大胸孕妇孕交pregnantsex 大象视频污 | 二次元美女内裤凹陷太深 | 欧美在线观看视频一区 | 日本免费看| 亚洲精品一区二区观看 | 精品网站一区二区三区网站 | 国产拍拍视频一二三四区 | 亚洲精品午夜级久久久久 | 性夜影院爽黄A爽免费动漫 性色欲情网站IWWW九文堂 | 日b视频免费看 | 好湿好滑好硬好爽好深视频 | aaa一级特黄 | 国产成人精品日本亚洲网址 | 免费观看欧美一级高清 | 午夜尤物 | 日韩久久精品 | 国产自在线观看 | 肉大捧一进一出视频免费播放 | 日本一卡2卡3卡4卡乱 | 91免费高清无砖码区 | 久久久久久久久女黄 | 国产精品免费aⅴ片在线观看 | 日本xxx18hd| 日本三级在线观看免费 | 国产成人夜色影视视频 | 日韩中文字幕在线不卡 | asian4you裸模| 成人18视频在线观看 | 嫩草影院地址一地址二 | 3x3x3x短视频在线看 | 91桃色视频| 日韩在线观看一区二区不卡视频 | 国产成人欧美 |