SpringBoot整合JPA的过程是怎样的
更新:HHH   时间:2023-1-7


这篇文章主要介绍“SpringBoot整合JPA的过程是怎样的”,在日常操作中,相信很多人在SpringBoot整合JPA的过程是怎样的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoot整合JPA的过程是怎样的”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

目录
  • SpringBoot整合JPA

    • JPA & Spring Data JPA

    • Hibernate & JPA

    • Hibernate VS Mybatis

  • 一、导入依赖

    • 二、简单的CRUD

      • 2.1 配置文件

      • 2.2 实体类

      • 2.3 Dao层

      • 2.4 service层

      • 2.5 controller

    • 三、自定义SQL

      • 四、分页查询

        • 五、连表查询

          • 六、分组查询

            • 七、与mybatis对比

              SpringBoot整合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:强大、方便、高效、复杂、绕弯子、全自动

              一、导入依赖

              <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:
                    #定义数据库表的生成策略 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.2 实体类

              Shop:

              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,商品类别

              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类,泛型传入 要操作的实体类,和主键类型

              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:

              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匹配的所有实体并排序
              }

              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("耳机");
                      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代表第一个参数
                  @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:

              //通过价格查询商品
                  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 封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则。

              Spring Data JPA 已经帮我们内置了分页功能,在查询的方法中,需要传入参数 Pageable,当查询中有多个参数的时候 Pageable 建议作为最后一个参数传入,

              Pageable使用的时候需要传入页数、每页条数和排序规则,排序规则可省略

              service:

               /**
                   * 分页查询
                   * @param pageNo 第几页
                   * @param pageSize 每页有多少条数据
                   * @param pageable Spring 封装的分页实现类
                   * @return 数据
                   */
                  Page<Shop> pageShop(Integer pageNo,Integer pageSize,Pageable pageable);

              Impl:

              @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:

              @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,这里的有参构造必须加,要往里赋值

              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进行查询,它的特征就是与原生SQL语句类似,完全面向对象,通过类名和属性访问,而不是表名和表属性

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

              六、分组查询

              接收数据的另一种写法,创建一个结果集的接口来接收连表查询后的结果

              定义一个结果集的接口类,接口类的内容来自于商品表和商品类别表。

              entity:

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

              在运行中 Spring 会给接口(GroupShop)自动生产一个代理类来接收返回的结果,代码中使用 getXX 的形式来获取。

              ShopRepository:

              //分组查询
                  @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:

              //分组查询
                  List<GroupShop> groupShop();

              Impl:

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

              controller:

              @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更加顺手。

              到此,关于“SpringBoot整合JPA的过程是怎样的”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注天达云网站,小编会继续努力为大家带来更多实用的文章!

              返回开发技术教程...