目录
  • springboot整合jpa
    • jpa & spring data jpa
    • hibernate & jpa
    • hibernate vs mybatis
    • 二、简单的crud
      • 2.3 dao层
    • 三、自定义sql

              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("/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:

               /**
                   * 分页查询
                   * @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的的文章就介绍到这了,更多相关springboot整合jpa内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!