溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

SpringBoot整合JPA的過程是怎樣的

發(fā)布時(shí)間:2021-06-21 09:19:54 來源:億速云 閱讀:203 作者:chen 欄目:開發(fā)技術(shù)

這篇文章主要介紹“SpringBoot整合JPA的過程是怎樣的”,在日常操作中,相信很多人在SpringBoot整合JPA的過程是怎樣的問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對(duì)大家解答”SpringBoot整合JPA的過程是怎樣的”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

目錄
  • SpringBoot整合JPA

    • JPA & Spring Data JPA

    • Hibernate & JPA

    • Hibernate VS Mybatis

  • 一、導(dǎo)入依賴

    • 二、簡單的CRUD

      • 2.1 配置文件

      • 2.2 實(shí)體類

      • 2.3 Dao層

      • 2.4 service層

      • 2.5 controller

    • 三、自定義SQL

      • 四、分頁查詢

        • 五、連表查詢

          • 六、分組查詢

            • 七、與mybatis對(duì)比

              SpringBoot整合JPA

              JPA & Spring Data JPA

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

              其設(shè)計(jì)目標(biāo)主要是為了簡化現(xiàn)有的持久化開發(fā)工作和整合ORM技術(shù)。

              JPA使用XML文件或注解(JDK 5.0或更高版本)來描述對(duì)象-關(guān)聯(lián)表的映射關(guān)系,能夠?qū)⑦\(yùn)行期的實(shí)體對(duì)象持久化到數(shù)據(jù)庫,它為Java開發(fā)人員提供了一種ORM工具來管理Java應(yīng)用中的關(guān)系數(shù)據(jù)。

              簡單地說,JPA就是為POJO(Plain Ordinary Java Object)提供持久化的標(biāo)準(zhǔn)規(guī)范,即將Java的普通對(duì)象通過對(duì)象關(guān)系映射(Object-Relational Mapping,ORM)持久化到數(shù)據(jù)庫中。

              由于JPA是在充分吸收了現(xiàn)有Hibernate,TopLink,JDO等ORM框架的基礎(chǔ)上發(fā)展而來的,因而具有易于使用、伸縮性強(qiáng)等優(yōu)點(diǎn)。

              Spring Data JPA 是 Spring 基于 Spring Data 框架、在JPA 規(guī)范的基礎(chǔ)上開發(fā)的一個(gè)框架,使用 Spring Data JPA 可以極大地簡化JPA 的寫法,可以在幾乎不用寫實(shí)現(xiàn)的情況下實(shí)現(xiàn)對(duì)數(shù)據(jù)庫的訪問和操作,除了CRUD外,還包括分頁和排序等一些常用的功能。

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

              JPA不是一種新的ORM框架,它的出現(xiàn)只是用于規(guī)范現(xiàn)有的ORM技術(shù),它不能取代現(xiàn)有的Hibernate、TopLink等框架。相反,在采用JPA開發(fā)時(shí),我們將仍將使用到這些ORM框架,只是此時(shí)開發(fā)出來的應(yīng)用不再依賴于某個(gè)持久化提供商。應(yīng)用可以在不修改代碼的情況下在任何JPA環(huán)境下運(yùn)行,真正做到低耦合,可擴(kuò)展的程序設(shè)計(jì)。

              Hibernate & JPA

              1、JPA

              全稱Java Persistence API,通過JDK 5.0注解或XML描述對(duì)象-關(guān)系表的映射關(guān)系,并將運(yùn)行期的實(shí)體對(duì)象持久化到數(shù)據(jù)庫中。

              JPA的出現(xiàn)有兩個(gè)原因:

              其一,簡化現(xiàn)有Java EE和Java SE應(yīng)用的對(duì)象持久化的開發(fā)工作;

              其二,Sun希望整合對(duì)ORM技術(shù),實(shí)現(xiàn)持久化領(lǐng)域的統(tǒng)一。

              JPA提供的技術(shù):

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

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

              3)查詢語言:通過面向?qū)ο蠖敲嫦驍?shù)據(jù)庫的查詢語言查詢數(shù)據(jù),避免程序的SQL語句緊密耦合。

              2、JPA & Hibernate 關(guān)系

              JPA是規(guī)范,Hibernate是框架,JPA是持久化規(guī)范,而Hibernate實(shí)現(xiàn)了JPA。

              Hibernate VS Mybatis

              Mybatis:小巧、方便、高效、簡單、直接、半自動(dòng)

              Hibernate:強(qiáng)大、方便、高效、復(fù)雜、繞彎子、全自動(dòng)

              一、導(dǎo)入依賴

              <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

              2.1 配置文件

              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:
                    #定義數(shù)據(jù)庫表的生成策略 create 創(chuàng)建一個(gè)表 update 更新或者創(chuàng)建數(shù)據(jù)表
                    ddl-auto: update
                    #控制臺(tái)顯示sql語句
                  show-sql: true
              server:
                port: 80

              其中,spring.jpa.hibernate.ddl-auto 參數(shù)用來配置是否開啟自動(dòng)更新數(shù)據(jù)庫表結(jié)構(gòu),可取create、create-drop、update、validate、none五個(gè)值。

              • create 每次加載hibernate時(shí),先刪除已存在的數(shù)據(jù)庫表結(jié)構(gòu)再重新生成;

              • create-drop 每次加載hibernate時(shí),先刪除已存在的數(shù)據(jù)庫表結(jié)構(gòu)再重新生成,并且當(dāng) sessionFactory關(guān)閉時(shí)自動(dòng)刪除生成的數(shù)據(jù)庫表結(jié)構(gòu);

              • update 只在第一次加載hibernate時(shí)自動(dòng)生成數(shù)據(jù)庫表結(jié)構(gòu),以后再次加載hibernate時(shí)根據(jù)model類自動(dòng)更新表結(jié)構(gòu);

              • validate 每次加載hibernate時(shí),驗(yàn)證數(shù)據(jù)庫表結(jié)構(gòu),只會(huì)和數(shù)據(jù)庫中的表進(jìn)行比較,不會(huì)創(chuàng)建新表,但是會(huì)插入新值。

              • none 關(guān)閉自動(dòng)更新

              2.2 實(shí)體類

              Shop:

              package com.shy.entity;
              import lombok.Data;
              import javax.persistence.*;
              @Data
              //使用jpa注解 配置映射關(guān)系
              @Entity//告訴jpa這是一個(gè)實(shí)體類 和數(shù)據(jù)表映射的類
              public class Shop{
                  @Id//表明這是以一個(gè)主鍵
                  @GeneratedValue(strategy = GenerationType.IDENTITY)//自增
                  private Integer shopId;
              
                  @Column(length = 20)
                  private String shopName;
              
                  private double price;
              
                  private Integer shopClassId;
              
                  private Integer num;
              }

              ShopClass,商品類別

              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;
              }

              2.3 Dao層

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

              package com.example.dao;
              import com.shy.entity.Shop;
              import org.springframework.data.jpa.repository.JpaRepository;
              import org.springframework.stereotype.Repository;
              
              /* 參數(shù)一 T :當(dāng)前需要映射的實(shí)體
               * 參數(shù)二 ID :當(dāng)前映射的實(shí)體中的OID(映射對(duì)象標(biāo)識(shí)符,數(shù)據(jù)庫主鍵)的類型*/
              
              @Repository
              public interface ShopRepository extends JpaRepository<Shop,Integer> {
                  /*
                   * 我們?cè)谶@里直接繼承 JpaRepository
                   * 這里面已經(jīng)有很多現(xiàn)成的方法了
                   * 這也是JPA的一大優(yōu)點(diǎn)
                   * 我們可以直接使用這些方法,包括其父類的好多方法。
                   * */
              }

              JpaRepository:

              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();// 查詢所有實(shí)體
              
              	@Override
              	List<T> findAll(Sort sort);// 查詢所有實(shí)體并排序
              
              	@Override
              	List<T> findAllById(Iterable<ID> ids);// 根據(jù)ID集合查詢實(shí)體
              
              	@Override
              	<S extends T> List<S> saveAll(Iterable<S> entities);// 保存并返回(修改后的)實(shí)體集合
              
              	void flush();// 提交事務(wù)
              
              	<S extends T> S saveAndFlush(S entity); // 保存實(shí)體并立即提交事務(wù)
              
              	<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);
              
              	@Deprecated
              	default void deleteInBatch(Iterable<T> entities){deleteAllInBatch(entities);}
              
              	void deleteAllInBatch(Iterable<T> entities); // 批量刪除實(shí)體集合
              
              	void deleteAllByIdInBatch(Iterable<ID> ids);
              
              	void deleteAllInBatch();// 批量刪除所有實(shí)體
              
              	@Deprecated
              	T getOne(ID id);// 根據(jù)ID查詢實(shí)體
              
              	T getById(ID id);
              
              	@Override
              	<S extends T> List<S> findAll(Example<S> example);// 查詢與指定Example匹配的所有實(shí)體
              
              	@Override
              	<S extends T> List<S> findAll(Example<S> example, Sort sort);// 查詢與指定Example匹配的所有實(shí)體并排序
              }

              2.4 service層

              service:

              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:

              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("耳機(jī)");
                      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("刪除成功");
                  }
              }

              2.5 controller

              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中添加

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

              service:

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

              Impl:

              @Override
                  public Shop findByPrice(Double price) {
                      return shopRepository.findByPrice(price);
                  }
              
              	@Override
                  public int updateshop2(String name, Integer shopId) {
                      return shopRepository.updateshop2(name, shopId);
                  }

              controller:

              @GetMapping("/listPrice/{price}")
                  public String findByPrice(@PathVariable Double price){
                      return JSON.toJSONString(shopService.findByPrice(price));
                  }
              
              	@GetMapping("/saveAndFlush3/{id}/{name}")
                  public String saveAndFlush3(@PathVariable(value = "id") Integer shopId,
                                             @PathVariable String name){
                      return shopService.updateshop2(name, shopId)>0?"修改成功":"修改失敗";
                  }

              四、分頁查詢

              Pageable 是 Spring 封裝的分頁實(shí)現(xiàn)類,使用的時(shí)候需要傳入頁數(shù)、每頁條數(shù)和排序規(guī)則。

              Spring Data JPA 已經(jīng)幫我們內(nèi)置了分頁功能,在查詢的方法中,需要傳入?yún)?shù) Pageable,當(dāng)查詢中有多個(gè)參數(shù)的時(shí)候 Pageable 建議作為最后一個(gè)參數(shù)傳入,

              Pageable使用的時(shí)候需要傳入頁數(shù)、每頁條數(shù)和排序規(guī)則,排序規(guī)則可省略

              service:

               /**
                   * 分頁查詢
                   * @param pageNo 第幾頁
                   * @param pageSize 每頁有多少條數(shù)據(jù)
                   * @param pageable Spring 封裝的分頁實(shí)現(xiàn)類
                   * @return 數(shù)據(jù)
                   */
                  Page<Shop> pageShop(Integer pageNo,Integer pageSize,Pageable pageable);

              Impl:

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

              controller:

              @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)值對(duì)象

              • 通常用于業(yè)務(wù)層之間的數(shù)據(jù)傳遞,僅僅包含數(shù)據(jù)而已

              • View object:視圖對(duì)象

              接受頁面?zhèn)鬟f來的對(duì)象,封裝對(duì)象

              將業(yè)務(wù)處理完成的對(duì)象,封裝成頁面要用的數(shù)據(jù)

              創(chuàng)建ShopAndShopClassVo用來接收連表查詢后的結(jié)果

              entity,這里的有參構(gòu)造必須加,要往里賦值

              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:

              //連表查詢
                  @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進(jìn)行查詢,它的特征就是與原生SQL語句類似,完全面向?qū)ο?,通過類名和屬性訪問,而不是表名和表屬性

              service:

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

              Impl:

              @Override
                  public List<ShopAndShopClassVo> findShopInfo(String shopClassName) {
                      return shopRepository.findShopInfo(shopClassName);
                  }

              controller:

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

              六、分組查詢

              接收數(shù)據(jù)的另一種寫法,創(chuàng)建一個(gè)結(jié)果集的接口來接收連表查詢后的結(jié)果

              定義一個(gè)結(jié)果集的接口類,接口類的內(nèi)容來自于商品表和商品類別表。

              entity:

              package com.shy.entity;
              
              public interface GroupShop {
                  String getNum();
                  String getShopClassName();
              }

              在運(yùn)行中 Spring 會(huì)給接口(GroupShop)自動(dòng)生產(chǎn)一個(gè)代理類來接收返回的結(jié)果,代碼中使用 getXX 的形式來獲取。

              ShopRepository:

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

              service:

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

              Impl:

              @Override
                  public List<GroupShop> groupShop() {
                      return shopRepository.groupShop();
                  }

              controller:

              @GetMapping("/groupShop")
                  public String groupShop(){
                      return JSON.toJSONString(shopService.groupShop());
                  }

              七、與mybatis對(duì)比

              • jpa是對(duì)象與對(duì)象之間的映射,而mybatis是對(duì)象和結(jié)果集的映射

              • jpa移植性比較好,不用關(guān)心用什么數(shù)據(jù)庫,因?yàn)閙ybatis自由寫sql語句,所以當(dāng)項(xiàng)目移植的時(shí)候還需要改sql。

              • 修改字段時(shí)JPA更簡單,mybatis需要修改一堆的xml,mapper等文件很麻煩。

              • mybatis自定義sql,比較靈活,也可以寫復(fù)雜的sql,JPA只適合簡單的單表sql

              • 總結(jié):mybatis和JPA各有優(yōu)勢,如果sql簡單,則jpa使用效率更高,如果sql較復(fù)雜,需要自定義,則使用mybatis更加順手。

              到此,關(guān)于“SpringBoot整合JPA的過程是怎樣的”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

              向AI問一下細(xì)節(jié)

              免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

              AI