版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第5章SpringBoot数据库开发——数据库与持久层框架SpringBoot实用教程(第4版)数据库与持久层框架目前最为常用的持久层框架有:MyBatis、JPA、DataRedis和DataMongoDB等,其中MyBatis、JPA通过驱动操作各种关系数据库(如MySQL、SQLServer等),而DataRedis和DataMongoDB则分别用于操作NoSQL型的Redis和MongoDB数据库,如图5.1所示。第5章SpringBoot数据库开发——MyBatis开发基础目录01MyBatis简介MyBatis简介MyBatis是一个支持定制化SQL、存储过程以及高级映射的优秀持久层框架,它避免了几乎所有的JDBC代码、手动设置参数以及获取结果集,可以对配置和原生Map使用简单的注解,将接口和Java的POJO映射成数据库中的记录。MyBatis采用的是一种基于SQL到POJO的模型,它需要开发者提供SQL、映射关系和POJO类。对于SQL与POJO的映射关系,它提供了自动映射和驼峰映射等,大大减少了开发者的工作量;由于没有屏蔽SQL,使开发者可以尽可能地通过SQL去优化性能,也可以做少量的改变以适应灵活多变的互联网环境,这些对于追求高响应和高性能的互联网应用系统是十分重要的。与此同时,它还能支持动态SQL,以适应需求的变化。因而MyBatis随着中国互联网产业的发展日趋流行并成为国内市场的主流持久层框架。MyBatis社区为了整合Spring早就发布了相应的开发包,SpringBoot则进一步将其整合进来作为SQL依赖的一个基本组件,我们可以在开发时勾选MyBatis社区提供的starter,就可以直接在项目中使用MyBatis。目录02MyBatis原理MyBatis原理MyBatis是一个基于SqlSessionFactory构建的框架,SqlSessionFactory的作用是生成SqlSession接口对象,这个接口对象是MyBatis操作的核心。由于SqlSessionFactory的作用是单一(仅用于创建SqlSession)的,故其在MyBatis应用的生命周期中往往会以单例模式(即只存在一个SqlSessionFactory对象)运行。SpringBoot将MyBatis框架整合进来,提供了两个类:MapperFactoryBean和MapperScannerConfigurer,这里的MapperFactoryBean是针对一个接口配置,而MapperScannerConfigurer则负责扫描装配,如图5.2所示。MyBatis原理生成SqlSessionFactory是通过配置类来完成的,它会给予用户在配置文件(perties)中进行配置的选项,从图5.2中可以了解MyBatis可配置的主要内容有:properties(属性):在实际应用中一般采用Spring而非MyBatis来配置属性文件。mappers(映射器):是MyBatis最核心的组件,它提供SQL与POJO类的映射关系,这是MyBatis开发的核心。objectFactory(对象工厂):在MyBatis生成返回的POJO时会调用这个工厂类,实际开发一般使用MyBatis默认提供的对象工厂类(DefaultObjectFactory),无须额外配置。settings(设置):可以配置映射规则(如自动映射或驼峰映射)、执行器类型、缓存等,决定MyBatis的底层行为,比较复杂,具体配置项可参考MyBatis官网说明。plugins(插件):也称为拦截器,它通过动态代理和责任链模式来完成,可以修改MyBatis底层的功能实现。typeAliases(类型别名):MyBatis会对常用的类提供默认别名,由于类的全限定名通常会比较冗长,通过typeAliases配置自定义的别名能增强可读性。databaseIdProvider(数据库厂商标识):允许MyBatis配置多类型数据库的支持,不常用。environments(数据库环境):可配置数据库连接的内容和事务,通常这些都交由Spring托管。typeHandlers(类型处理器):在MyBatis写入和读取数据库的过程中对于不同类型的数据进行自定义转换,但在大多数情况下用不到,因为MyBatis本身就已经定义好了很多现成的typeHandler,框架会自动识别并实现各种常用类型的转换。目录03MyBatis注解1.基础注解2.映射注解3.高级注解MyBatis注解1.基础注解增删改查是所有关系数据库最基本的业务操作,MyBatis提供下面四个基础注解供用户构建自己的SQL语句:@Select:用于构建查询(SELECT)语句。@Insert:用于构建插入(INSERT)语句。@Update:用于构建更新(UPDATE)语句。@Delete:用于构建删除(DELETE)语句。MyBatis注解2.映射注解映射注解用于建立实体与关系的映射,MyBatis提供的映射注解有以下三个:@Result:用于填写结果集的单个字段的映射关系。@Results:用于填写结果集的多个字段的映射关系。@ResultMap:根据ID关联XML里面的<resultMap>。3.高级注解MyBatis对应基础的增删改查提供有以下四个高级注解:@SelectProvider:用于构建动态查询SQL。@InsertProvider:用于构建动态插入SQL。@UpdateProvider:用于构建动态更新SQL。@DeleteProvider:用于构建动态删除SQL。目录04MyBatis应用实例1.准备数据2.创建项目3.配置连接4.MyBatis实现商品管理5.分页功能MyBatis应用实例【实例5.1】通过MyBatis操作MySQL实现“商品信息管理系统”的“商品管理”(包括商品添加、删除、修改、查询和分页显示)功能。1.准备数据本例演示程序功能需要商品表(commodity)及其样本记录,而商品表又以外键关联于商品分类表(category)和商家表(supplier)的记录,故要先分别创建这几个表及录入必需的样本数据。通过NavicatPremium连上MySQL,在其查询编辑器中执行SQL语句。(1)创建商品分类表(category)及录入样本执行SQL语句为:USEnetshop;CREATETABLEcategory( TCode char(3) NOTNULLPRIMARYKEY, /*商品分类编码*/ TName varchar(8) NOTNULL /*商品分类名称*/);INSERTINTOcategory VALUES ('11A','苹果'), ('11B','梨');MyBatis应用实例(2)录入商家表(supplier)的样本商家表在做前面章节实例的时候已经创建好了,此处只须录入样本,执行SQL语句为:USEnetshop;INSERTINTOsupplier(SCode,SName,SweiXin,Tel)VALUES('SDYT002A','山东烟台栖霞苹果批发市场','8234561-','0535-823456X');INSERTINTOsupplier(SCode,SName,SWeiXin,Tel)VALUES('XJAK003A','新疆阿克苏地区红旗坡农场','8345612-','0997-834561X');INSERTINTOsupplier(SCode,SName,SWeiXin,Tel)VALUES('XJAK005B','新疆安利达果业有限公司','8456123-','0996-845612X');INSERTINTOsupplier(SCode,SName,SWeiXin,Tel)VALUES('AHSZ006B','安徽砀山皇冠梨供应公司','8561234-','0557-856123X');(3)创建商品表(commodity)及录入样本执行SQL语句为。MyBatis应用实例2.创建项目创建SpringBoot项目,项目名为MyBatis,在出现的向导界面“Dependencies”列表中勾选SpringBoot基本框架(“Web”→“SpringWeb”)、Thymeleaf引擎组件(“TemplateEngines”→“Thymeleaf”)、Lombok模型简化组件(“DeveloperTools”→“Lombok”)、MyBatis框架(“SQL”→“MyBatisFramework”)以及MySQL的驱动(“SQL”→“MySQLDriver”)。3.配置连接打开项目工程目录树src→main→resources下的perties文件,在其中配置对MySQL数据库的连接,内容如下:spring.datasource.url=jdbc:mysql://:3306/netshop?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=truespring.datasource.username=rootspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.cj.jdbc.DriverMyBatis应用实例4.MyBatis实现商品管理(1)设计模型本例用到的模型就是一个商品类,在项目工程目录树的com.example.mybatis节点下创建model包,其中创建Commodity.java,代码为:packagecom.example.mybatis.model;
importlombok.Data;
@DatapublicclassCommodity{ privateintpid; //商品号 privateStringtcode; //商品分类编码 privateStringscode; //商家编码 privateStringpname; //商品名称 privatefloatpprice; //商品价格 privateintstocks; //商品库存}MyBatis应用实例(2)定义数据接口使用MyBatis的持久层数据接口还是需要由用户自己来开发定义的。在项目工程目录树的com.example.mybatis节点下创建mapper包,其中创建接口ComMapper,在接口中以MyBatis的注解分别构建对商品模型实体增删改查的各个SQL语句。接口ComMapper.java的定义代码为:(3)开发控制器由于本例业务逻辑很简单,且旨在演示MyBatis持久层的操作机制,故省去业务层的开发,直接用控制器来调用Mapper接口中的方法。在项目工程目录树的com.example.mybatis节点下创建controller包,其中创建控制器类MyBController,代码显示。MyBatis应用实例(4)运行启动SpringBoot项目,打开浏览器,分别测试MyBatis对商品记录增删改查的操作。①查询商品号为1的商品记录地址栏输入http://localhost:8080/com/get?pid=1回车,看到1号商品记录信息如图5.3所示。MyBatis应用实例②查询所有的商品记录地址栏输入http://localhost:8080/com/getall回车,看到当前数据库商品表中所有的商品记录信息如图5.4所示。MyBatis应用实例③添加商品记录添加一个商品号为1002的商品,通过URL请求参数传递该商品的各项基本信息,在地址栏输入http://localhost:8080/com/add?pid=1002&tcode=11B&scode=AHSZ006B&pname=砀山梨5斤箱装特大果&pprice=17.90&stocks=6834回车,运行结果如图5.5所示,打开数据库商品表,可看到新添加的商品。MyBatis应用实例④更新商品库存修改新添加的1002号商品的库存(增加1000),地址栏输入http://localhost:8080/com/set?pid=1002&stocks=7834回车,运行结果如图5.6所示,打开数据库商品表,看到库存已更新。MyBatis应用实例⑤删除商品记录删除刚添加的1002号商品,地址栏输入http://localhost:8080/com/del?pid=1002回车,运行结果如图5.7所示。运行完再次打开商品表,看到已没有了1002号商品记录。MyBatis应用实例5.分页功能在实际开发中,如果要显示的商品信息记录数很多,就要采用分页显示,分页功能可以通过PageHelper来实现,步骤如下。(1)添加PageHelper插件PageHelper是MyBatis框架的一个插件,专用于支持在MyBatis应用中执行分页操作,使用前需要先添加依赖到项目中。打开项目的pom.xml文件,添加内容如下:<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>4.1.6</version></dependency>MyBatis应用实例(2)开发配置类PageHelper需要以Java配置的方式注入SpringBoot容器中才能使用,为此要先开发一个配置类。在项目工程目录树的com.example.mybatis节点下创建configer包,其中创建配置类PageConfiger.java,代码显示。说明:Properties为PageHelper设置属性,这里设了3个属性:“offsetAsPageNum”设为true,将RowBounds第1个参数offset作为页码(pageNum);“rowBoundsWithCount”设为true,在使用RowBounds分页时进行count查询;“reasonable”启用合理化,若pageNum小于1,查询首页,若pageNum大于总页数(pages),则查询尾页。MyBatis应用实例(3)开发控制器在项目controller包中创建分页控制器类PageController,代码显示。说明:①控制器方法通过两个参数start和size分别接收当前页码及每页要显示的记录数。②调用PageHelper的startPage方法(传入start和size参数)执行分页,还可以设置排序方式,这里设为“"PidDESC"”表示按商品号降序排列。③分页插件通过一个PageInfo类型的对象来创建分页形式的数据集合,将其直接传递(通过addAttribute方法添加)给视图即可在前端页面上显示。(4)设计前端页面在项目工程目录树的src→main→resources→templates节点下创建前端页面index.html,代码显示。MyBatis应用实例(5)运行启动项目,打开浏览器,地址栏输入http://localhost:8080/compage/getall回车,看到分页表格显示的商品信息,可以通过点击表格底部的“下一页”、“上一页”、“尾页”和“首页”等链接翻看不同页的记录,如图5.8所示。第5章SpringBoot数据库开发——JPA开发基础目录01JPA简
介JPA简介JPA(JavaPersistenceAPI)最初是由Java官方提出的一个持久化规范,它通过注解或XML描述对象—关系(表)的映射关系,并将内存中的实体对象持久化到数据库。JPA属于JSR-220(EJB3.0)规范的一部分,但是JSR-220规定实体对象(EntityBean)由JPA进行支持,所以JPA不仅仅局限于EJB3.0,在传统轻量级JavaEE开发时代,著名的持久层框架Hibernate实现了完全的JPA规范,JPA也就随着Hibernate的广泛应用而流行起来。后来,Spring推出了一个名为SpringData的子项目,旨在统一和简化各类型数据的持久化存储方式,其中的SpringDataJPA封装了Hibernate作为JPA规范的默认实现,这也就是当前SpringBoot中所支持的JPA,即通常所谓的“JPA框架”,如图5.9所示。目录02JPA实现“一对一”关联1.创建关联表2.创建项目3.配置连接4.设计关联实体5.开发持久层6.编写控制器7.运行演示“一对一”JPA实现“一对一”关联【实例5.2】保存商品图片的同时向商品表中添加对应商品的记录,删除图片时也联动一起删除该商品记录。1.创建关联表之前做实例时已经在数据库中创建了商品表(commodity),现在还需要建一个与之关联的商品图片表(commodityimage)。执行如下SQL语句:USEnetshop;CREATETABLEcommodityimage( Pid int(8) NOTNULLPRIMARYKEY, /*商品号*/ Image blob NOTNULL, /*商品图片(最大64KB)*/
FOREIGNKEY(Pid)REFERENCEScommodity(Pid) ONDELETECASCADEONUPDATECASCADE);JPA实现“一对一”关联2.创建项目创建SpringBoot项目,项目名为JpaOneToOne,在出现的向导界面“Dependencies”列表中勾选SpringBoot基本框架(“Web”→“SpringWeb”)、Lombok模型简化组件(“DeveloperTools”→“Lombok”)、JPA框架(“SQL”→“SpringDataJPA”)以及MySQL的驱动(“SQL”→“MySQLDriver”)。3.配置连接在项目perties文件中配置对MySQL数据库的连接,内容如下:spring.datasource.url=jdbc:mysql://:3306/netshop?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=truespring.datasource.username=rootspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.jpa.show-sql=trueJPA实现“一对一”关联4.设计关联实体在项目工程目录树的com.example.jpaonetoone节点下创建entity包,其中创建两个关联的实体类。(1)商品实体商品实体对应的是商品表(commodity),设计实体类Commodity.java,代码如下:packagecom.example.jpaonetoone.entity;
importlombok.Data;
importjavax.persistence.*;
@Entity //@Entity注解声明该模型类为一个实体@Data@Table(name="commodity") //@Table注解声明实体所对应的数据库表名publicclassCommodity{ @Id //@Id注解标注表的主键所对应的实体类属性(这里是商品号pid) privateintpid; privateStringtcode; privateStringscode; privateStringpname; privatefloatpprice; privateintstocks;}JPA实现“一对一”关联(2)商品图片实体商品图片实体对应的是商品图片表(commodityimage),设计实体类Commodityimage.java,代码如下:packagecom.example.jpaonetoone.entity;
importlombok.Data;
importjavax.persistence.*;
@Entity@Data@Table(name="commodityimage")publicclassCommodityimage{ @Id privateintpid; privatebyte[]image; @OneToOne(cascade=CascadeType.ALL) @JoinColumn(name="Pid") privateCommoditycommodity; //添加定义与之对应的商品实体对象属性}JPA实现“一对一”关联5.开发持久层有了JPA框架,持久层的开发就变得极为简单,只须定义接口继承JPA的JpaRepository接口即可,用户完全不用自己去编写任何实现代码。在项目工程目录树的com.example.jpaonetoone节点下创建repository包,其中创建两个接口,分别对应操作两个实体。(1)操作商品实体的接口创建接口ComRepository.java,其定义代码如下:packagecom.example.jpaonetoone.repository;
importcom.example.jpaonetoone.entity.Commodity;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceComRepositoryextendsJpaRepository<Commodity,Integer>{ CommodityqueryByPid(intpid); //根据商品号查询商品实体}JPA实现“一对一”关联(2)操作商品图片实体的接口创建接口ImgRepository.java,其定义代码如下:packagecom.example.jpaonetoone.repository;
importcom.example.jpaonetoone.entity.Commodityimage;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceImgRepositoryextendsJpaRepository<Commodityimage,Integer>{ voiddeleteById(intpid); //根据商品号删除商品图片实体}JPA实现“一对一”关联说明:上面接口中的两个方法queryByPid和deleteById都是JPA框架内置的,只要用户自定义的接口继承了JPA的JpaRepository就可以直接拿来用,在编程时由JPA按默认约定自动提示用户键入所需的方法名,如图5.10所示操作即可。JPA实现“一对一”关联6.编写控制器要测试以上建立的一对一关联是否成立,需要编写测试程序,本例的测试主程序代码写在控制器中。在项目工程目录树的com.example.jpaonetoone节点下创建controller包,其中创建控制器类JpaController.java,代码显示。7.运行演示“一对一”(1)准备本例需要用到的商品图片保存在C:\CommodityPictures\(与控制器代码中指定的要一致)目录,图片名为“砀山梨.jpg”,如图5.11所示。启动项目,打开浏览器。JPA实现“一对一”关联(2)测试关联添加地址栏输入http://localhost:8080/com/add?pid=1002&tcode=11B&scode=AHSZ006B&pname=砀山梨5斤箱装特大果&pprice=17.90&stocks=6834回车,商品号1002的记录随着图片一起保存到了数据库,前端显示从数据库查到的商品记录,如图5.12所示。JPA实现“一对一”关联打开数据库,可看到同步保存的图片与商品记录,如图5.13所示。JPA实现“一对一”关联从IDEA开发环境底部子窗口的输出中可看到,JPA先后执行了两条INSERT语句,如图5.14所示。JPA实现“一对一”关联(3)测试联动删除地址栏输入http://localhost:8080/com/del?pid=1002回车,前端显示信息如图5.15所示。再次打开数据库,可看到图片及商品记录都已经一并删除了。从IDEA输出中也可看到JPA是先后执行了两条DELETE语句,如图5.16所示。目录03JPA实现“一对多”关联1.创建项目2.配置连接3.设计关联实体4.开发持久层5.编写控制器6.运行演示“一对多”JPA实现“一对多”关联【实例5.3】向商品表中添加商品记录,并显示某商家所提供的全部商品的信息。本例所涉及的关联表:商家表(supplier)和商品表(commodity)在之前做实例的时候都已经建好了。1.创建项目创建SpringBoot项目,项目名为JpaOneToMany,在出现的向导界面“Dependencies”列表中勾选SpringBoot基本框架(“Web”→“SpringWeb”)、Lombok模型简化组件(“DeveloperTools”→“Lombok”)、JPA框架(“SQL”→“SpringDataJPA”)以及MySQL的驱动(“SQL”→“MySQLDriver”)。2.配置连接在项目perties文件中配置MySQL数据库连接,配置内容与【实例5.2】的完全相同,略。JPA实现“一对多”关联3.设计关联实体在项目工程目录树的com.example.jpaonetomany节点下创建entity包,其中创建关联实体类。(1)商品实体商品实体对应商品表(commodity),实体类Commodity.java,其设计代码与【实例5.2】相同,可直接拿来复用(仅所在包名修改一致即可),略。JPA实现“一对多”关联(2)商家实体商家实体对应商家表(supplier),设计实体类Supplier.java,代码如下:packagecom.example.jpaonetomany.entity;
importlombok.Data;
importjavax.persistence.*;importjava.util.List;
@Entity@Data@Table(name="supplier")publicclassSupplier{ @Id privateStringscode; privateStringsname; @OneToMany(cascade=CascadeType.ALL)//单向关系的一对多注解,用于“一”(商家)一方 @JoinColumn(name="SCode") //商品表通过外键SCode(商家编码)关联商家表 privateList<Commodity>commodityList;//添加定义列表(集合)类型的属性}JPA实现“一对多”关联4.开发持久层在项目工程目录树的com.example.jpaonetomany节点下创建repository包,其中创建两个接口。(1)操作商品实体的接口创建接口ComRepository.java,其定义代码如下:packagecom.example.jpaonetomany.repository;
importcom.example.jpaonetomany.entity.Commodity;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceComRepositoryextendsJpaRepository<Commodity,Integer>{}(2)操作商家实体的接口创建接口SupRepository.java,其定义代码如下:packagecom.example.jpaonetomany.repository;
importcom.example.jpaonetomany.entity.Supplier;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceSupRepositoryextendsJpaRepository<Supplier,String>{ SupplierfindSupplierByScode(Stringscode); //根据商家编码查询商家实体}JPA实现“一对多”关联5.编写控制器在控制器中编写程序来测试以上一对多的关联。在项目工程目录树的com.example.jpaonetomany节点下创建controller包,其中创建控制器类JpaController.java,代码显示。6.运行演示“一对多”启动项目,打开浏览器。(1)添加商品地址栏输入http://localhost:8080/sup/addcom?pid=1002&tcode=11B&scode=AHSZ006B&pname=砀山梨5斤箱装特大果&pprice=17.90&stocks=6834回车,将商品号1002的记录添加到数据库,前端显示如图5.17所示。JPA实现“一对多”关联而数据库商家表中,1002号商品的商家编码“AHSZ006B”所对应的商家名称也正是“安徽砀山皇冠梨供应公司”,如图5.18所示。JPA实现“一对多”关联(2)显示某商家提供的商品信息地址栏输入http://localhost:8080/sup/findcom?scode=AHSZ006B回车,显示出商家“AHSZ006B”所提供的全部商品信息,如图5.19所示,这与数据库中的记录也是一致的。目录04JPA实现“多对多”关联1.创建关联表2.创建项目3.配置连接4.设计关联实体5.开发持久层6.编写控制器7.运行演示“多对多”JPA实现“多对多”关联【实例5.4】创建两个用户,将同一种商品加入购物车。1.创建关联表“多对多”关联只能通过中间表的方式进行映射,而不能通过外键。于是在本例中,就要涉及到用户表(user)、商品表(commodity)以及它们的中间表购物车表(preshop),一共是3个表。其中,用户表和商品表在之前做实例时已经创建好了,下面来创建购物车表。执行如下SQL语句:USEnetshop;CREATETABLEpreshop( UCode char(16) NOTNULL, /*用户编码*/ Pid int(8) NOTNULL, /*商品号*/ PRIMARY KEY(UCode,Pid));为了后面运行程序的需要,先删除前面已经添加的商品号1002的记录,执行语句:DELETEFROMcommodityWHEREPid=1002;JPA实现“多对多”关联2.创建项目创建SpringBoot项目,项目名为JpaManyToMany,在出现的向导界面“Dependencies”列表中勾选SpringBoot基本框架(“Web”→“SpringWeb”)、Lombok模型简化组件(“DeveloperTools”→“Lombok”)、JPA框架(“SQL”→“SpringDataJPA”)以及MySQL的驱动(“SQL”→“MySQLDriver”)。3.配置连接在项目perties文件中配置MySQL数据库连接,配置内容与【实例5.2】的完全相同,略。JPA实现“多对多”关联4.设计关联实体由于是“多对多”关联,关系的任何一方都可以作为主控方,故在双方的实体中都要定义一个集合类型的对方的对象属性。在项目工程目录树的com.example.jpamanytomany节点下创建entity包,其中创建实体类。(1)用户实体用户实体对应用户表(user),设计实体类User.java,代码显示。(2)商品实体商品实体对应商品表(commodity),设计实体类Commodity.java,代码显示。JPA实现“多对多”关联5.开发持久层在项目工程目录树的com.example.jpamanytomany节点下创建repository包,其中创建两个接口。(1)操作用户实体的接口创建接口UserRepository.java,定义代码为:packagecom.example.jpamanytomany.repository;
importcom.example.jpamanytomany.entity.User;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceUserRepositoryextendsJpaRepository<User,String>{}(2)操作商品实体的接口创建接口ComRepository.java,定义代码为:packagecom.example.jpamanytomany.repository;
importcom.example.jpamanytomany.entity.Commodity;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceComRepositoryextendsJpaRepository<Commodity,Integer>{}JPA实现“多对多”关联6.编写控制器在控制器中编写程序来测试以上多对多的关联。在项目工程目录树的com.example.jpamanytomany节点下创建controller包,其中创建控制器类JpaController.java,代码如下:7.运行演示“多对多”启动项目,打开浏览器,地址栏输入http://localhost:8080/user/add?pid=1002&tcode=11B&scode=AHSZ006B&pname=砀山梨5斤箱装特大果&pprice=17.90&stocks=6834回车,前端显示如图5.20所示。JPA实现“多对多”关联此时,用户表里添加了两条新的用户记录,商品表里也添加进了1002号商品,这些都是在控制器主程序中通过持久层接口调用save方法显式保存进数据库的,如图5.21所示。JPA实现“多对多”关联因为在用户实体与商品实体间存在“多对多”关联,而我们在程序中用“commodity.setUsers(users)”设置了与1002号商品关联的用户实体集,相当于这个实体集中的用户都要购买1002号商品(加入购物车),故JPA还会自动在购物车表中添加记录,如图5.22所示。JPA实现“多对多”关联另外,从IDEA输出中也可看到JPA操作购物车表的SQL语句,如图5.23所示。第5章SpringBoot数据库开发——NoSQL开发基础目录01Redis开发入门与应用1.Redis简介2.Redis安装3.模板操作Redis实例4.缓存注解操作Redis实例Redis开发入门与应用1.Redis简介Redis是一种运行在内存的数据库,它是开源的、使用ANSIC语言编写、遵守BSD协议、支持网络、并提供多种语言的API。由于Redis是基于内存的,所以它的运行速度很快(大约是关系数据库几倍到几十倍),在已报道的某些测试中,甚至可以完成每秒10万次的读写,性能十分高效。现实应用中,数据的查询要远多于更新,据统计,一个正常网站日常查询与更新之比大约是9:1到7:3,若是将常用的数据存储在Redis中来代替关系数据库的査询访问,将可以大幅提高网站的性能。Redis开发入门与应用Redis拥有十分丰富的应用场景,主要如下:计数器电商APP商品的浏览量、短视频APP视频的播放次数等信息都会被统计,以便用于运营或产品市场分析。为了保证数据实时生效,对用户的每一次浏览都得计数,这会导致非常高的并发量。这时可以用Redis提供的incr命令来实现计数器功能,由于一切操作都在内存中进行,所以性能极佳。社交互动使用Redis提供的散列、集合等数据类型,可以很方便地实现网站(或APP)中的点赞、踩、关注共同好友等社交场景的基本功能。排行榜可以利用Redis提供的有序集合数据类型实现各种复杂的排行榜应用,如京东、淘宝的销量榜,将商品按时间、销量排行等。Redis开发入门与应用最新列表Redis可以通过LPUSH在列表头部插入一个内容ID作为关键字,通过LTRIM限制列表的数量,这样列表永远为N个ID,无须查询最新的列表,直接根据ID查找对应的内容即可。分布式会话在集群模式下,一般都会搭建以Redis等内存数据库为中心的会话(Session)服务,它不再由容器管理,而是由会话服务及内存数据库管理。高并发读写Redis特别适合将方法的运行结果放入缓存,以便后续在请求方法时直接去缓存中读取。这对执行耗时、但结果不频繁变动的SQL查询的支持极好。在高并发的情况下,应尽量避免请求直接访问关系数据库,这时可以使用Redis进行缓存操作,让请求先访问Redis。Redis开发入门与应用2.Redis安装(1)下载RedisRedis下载地址为/tporadowski/redis/releases,如图5.24所示,点页面上的“Redis-x64-5.0.10.zip”链接下载ZIP压缩版。Redis开发入门与应用本书使用Redis5.0的Windows版,下载得到的压缩包文件名为Redis-x64-5.0.10.zip。解压后将其中所有文件复制存盘到一个指定的目录(笔者保存在C:\redis),如图5.25所示。Redis开发入门与应用(2)启动Redis打开Windows命令行,用cd命令进入保存Redis的目录,输入如下命令启动Redis:redis-server.exeredis.windows.conf命令行输出如图5.26所示信息,表示成功启动Redis。Redis开发入门与应用(3)安装Redis服务图5.26虽然启动了Redis,但关闭命令行窗口后Redis也就关停了,为方便使用,需要把Redis安装成Windows操作系统下的一个服务。关闭命令行窗口,重新打开,再次进入保存Redis的目录,执行如下命令:redis-server--service-installredis.windows-service.conf--loglevelverbose稍候片刻,如果没有报错,如图5.27所示,表示安装成功。Redis开发入门与应用此时,打开操作系统的“计算机管理”窗口,在系统服务列表中可以找到一个名为“Redis”的Windows服务,如图5.28所示。Redis开发入门与应用(4)试用Redis在Redis服务启动的情况下,通过命令行进入保存Redis的目录,输入以下命令连接到Redis:redis-cli.exe-h-p6379该命令创建了一个地址为(本地)、端口号6379的Redis数据库连接,然后就可以使用setkeyvalue和getkey命令保存和获得数据。这里先试着往Redis数据库中保存一个键名username、值为zhouhejun的记录,依次输入如下命令:setusernamezhouhejun
getusername以上整个过程的命令行输入和显示内容如图5.29所示。Redis开发入门与应用(5)客户端操作Redis以上对Redis的操作都是通过命令行执行,比较麻烦且不够直观。目前,已经有一些第三方开发的专用于操作Redis的可视化客户端软件。本书提供一个用Java开发的Redis客户端RedisClient,下载地址是/caoxinyu/RedisClient,如图5.30所示。Redis开发入门与应用下载得到的压缩包文件名为RedisClient-windows.zip,解压后直接双击运行RedisClient-windows\release目录下的redisclient-win32.x86_64.2.0.jar,打开如图5.31所示的界面。Redis开发入门与应用右击左侧子窗口中的“Redisservers”节点,点击弹出的“Addserver”选项(或者选择主菜单“Server”→“Add”),出现“Addserver”设置对话框,如图5.32所示,在其中配置Redis连接。Redis开发入门与应用创建连接后,可看到“Redisservers”节点下面多了个“MyRedis”节点,双击展开可看到其中的数据库,Redis中预置了db0~db15共16个数据库。其中,db0是默认的当前数据库,也就是说,前面通过命令行存进去的键名username的记录就在该数据库中。双击db0,在右边区域“Redisdataexplorer”选项页中即可看到username条目,点击记录条目,在下方打开的选项页中就可以看到该记录的键名(Key)和值(Value),与命令行存入的一模一样,如图5.33所示。Redis开发入门与应用3.模板操作Redis实例SpringBoot提供了StringRedisTemplate和RedisTemplate两个模板来进行Redis数据操作,其中,StringRedisTemplate只针对键值都是字符串类型的数据,而RedisTemplate则可以操作对象类型的数据。这两个模板提供的主要数据访问方法如表5.1所示。方法功能opsForValue()操作只有简单属性的数据opsForHash()操作含有散列的数据opsForList()操作含有列表类型的数据opsForSet()操作含有集合类型的数据opsForZSet()操作含有有序集合的数据Redis开发入门与应用【实例5.5】通过模板方式操作Redis,向其中存入商品信息。本例程序先用MyBatis从MySQL数据库中读取商品信息,然后再通过StringRedisTemplate/RedisTemplate模板操作将读取的商品信息转存入Redis内存数据库。(1)创建项目创建SpringBoot项目,项目名为RedisTemplate,在出现的向导界面“Dependencies”列表中勾选SpringBoot基本框架(“Web”→“SpringWeb”)、Lombok模型简化组件(“DeveloperTools”→“Lombok”)、MyBatis框架(“SQL”→“MyBatisFramework”)以及MySQL的驱动(“SQL”→“MySQLDriver”)、Redis框架(“NoSQL”→“SpringDataRedis(Access+Driver)”)。(2)配置连接在项目perties文件中配置MySQL数据库连接,配置内容与【实例5.1】的相同,略。Redis开发入门与应用(3)设计模型由于存储到Redis的数据必须序列化,所以本例的商品模型类也要实现Java的序列化接口Serializable。在项目工程目录树的com.example.redistemplate节点下创建model包,其中创建Commodity.java,代码为:packagecom.example.redistemplate.model;
importlombok.Data;
importjava.io.Serializable;
@DatapublicclassCommodityimplementsSerializable{ //必须序列化 privateintpid; //商品号 privateStringtcode; //商品分类编码 privateStringscode; //商家编码 privateStringpname; //商品名称 privatefloatpprice; //商品价格 privateintstocks; //商品库存}Redis开发入门与应用(4)定义数据接口在项目工程目录树的com.example.redistemplate节点下创建mapper包,其中创建接口ComMapper.java,定义为:packagecom.example.redistemplate.mapper;
importcom.example.redistemplate.model.Commodity;importorg.apache.ibatis.annotations.*;
@MapperpublicinterfaceComMapper{ @Select("SELECT*FROMcommodityWHEREPid=#{pid}") CommodityqueryByPid(@Param("pid")intpid);}Redis开发入门与应用(5)开发操作Redis的业务层通常开发中,读取关系数据库(如MySQL)的操作在持久层进行,而操作NoSQL的工作却是由业务层的服务实体来承担的,这样做使代码分工明确,各模块职能清晰。①定义业务接口在项目工程目录树的com.example.redistemplate节点下创建service包,其下定义名为ComService的接口,代码为:packagecom.example.redistemplate.service;
importcom.example.redistemplate.model.Commodity;
publicinterfaceComService{ publicStringgetPNameFromRedis(intpid); //从Redis获取商品名称 publicCommoditygetComFromRedis(intpid); //从Redis获取商品记录对象}②开发服务实体在service包下创建业务接口的实现类ComServiceImpl,代码显示。Redis开发入门与应用(6)编写控制器在项目工程目录树的com.example.redistemplate节点下创建controller包,其中创建控制器类ComController,代码显示。(7)自定义配置RedisTemplateSpringBoot默认配置的RedisTemplate使用JdkSerializationRedisSerializer来序列化数据,由于JdkSerializationRedisSerializer是以二进制形式存储数据的,这对我们通过RedisClient可视化查看很不方便,故需要对RedisTemplate进行配置,自定义其序列化器。在项目主启动文件RedisTemplateApplication.java中进行配置,添加代码(加黑)如下。Redis开发入门与应用(8)运行启动项目,打开浏览器。①从Redis获取商品名称地址栏输入http://localhost:8080/com/getpname?pid=1回车,获取商品号1的记录的商品名称,显示如图5.34所示。Redis开发入门与应用此时,打开Redis客户端,可看到其中存储的键名为pname的商品名称字符串,与前端显示是一致的,如图5.35所示。Redis开发入门与应用②从Redis获取商品记录对象地址栏输入http://localhost:8080/com/getcom?pid=1回车,获取商品号1的记录对象,显示如图5.36所示。Redis开发入门与应用此时,打开Redis客户端,可看到其中存储的键名为1的商品记录对象,其各字段内容与前端显示也是一致的,如图5.37所示。Redis开发入门与应用4.缓存注解操作Redis实例模板虽然能够有效地操作Redis,但仍然需要用户自己编程调用方法来实现操作,并不能完全自动化。为了进一步简化Redis的使用,SpringBoot提供了缓存注解,只要将注解加在需要操作Redis的方法上,在程序执行方法代码的时候就会自动进行Redis的存取而无须用户干预,这种方式在实际中用得更加普遍。【实例5.6】用缓存注解方式操作Redis,实现内存中商品信息的增删改查。(1)创建项目创建SpringBoot项目,项目名为RedisCache,在出现的向导界面“Dependencies”列表中勾选SpringBoot基本框架(“Web”→“SpringWeb”)、Lombok模型简化组件(“DeveloperTools”→“Lombok”)、MyBatis框架(“SQL”→“MyBatisFramework”)以及MySQL的驱动(“SQL”→“MySQLDriver”)、Redis框架(“NoSQL”→“SpringDataRedis(Access+Driver)”)。Redis开发入门与应用(2)配置连接在项目perties文件中配置MySQL数据库连接,内容如下:spring.datasource.url=jdbc:mysql://:3306/netshop?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=truespring.datasource.username=rootspring.datasource.password=123456spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver.example.rediscache=debug(3)设计模型本例也只用到了商品模型类Commodity.java,与【实例5.5】的完全一样,也需要实现Java序列化Serializable接口,可以直接复用【实例5.5】的模型类,将其复制到项目的com.example.rediscache.model包下,改一下包路径即可,代码略。Redis开发入门与应用(4)定义数据接口在项目工程目录树的com.example.rediscache节点下创建mapper包,其中创建接口ComMapper.java,定义为:packagecom.example.rediscache.mapper;
importcom.example.rediscache.model.Commodity;importorg.apache.ibatis.annotations.*;
@MapperpublicinterfaceComMapper{ @Select("SELECT*FROMcommodityWHEREPid=#{pid}") CommodityqueryByPid(@Param("pid")intpid);
@Insert("INSERTINTOcommodity(Pid,TCode,SCode,Pname,PPrice,Stocks)VALUES(#{pid},#{tcode},#{scode},#{pname},#{pprice},#{stocks})") intinsertOne(Commoditycommodity);
@Update("UPDATEcommoditySETStocks=#{stocks}WHEREPid=#{pid}") intupdateByPid(@Param("pid")intpid,@Param("stocks")intstocks);
@Delete("DELETEFROMcommodityWHEREPid=#{pid}") intdeleteByPid(intpid);}Redis开发入门与应用(5)开发业务层①定义业务接口在项目工程目录树的com.example.rediscache节点下创建service包,其下定义名为ComService的接口,代码为:packagecom.example.rediscache.service;
importcom.example.rediscache.model.Commodity;
publicinterfaceComService{ publicCommoditygetComFromRedis(intpid); //从Redis获取商品记录
publicintaddComToRedis(intpid,Commoditycommodity); //往Redis添加商品记录
publicintsetComToRedis(intpid,intstocks); //更新Redis中的商品库存
publicintdelComFromRedis(intpid); //从Redis删除商品记录}②开发服务实体在service包下创建业务接口的实现类ComServiceImpl,代码显示。Redis开发入门与应用说明:(a)@Cacheable(value="commoditys",key="#pid"):注解@Cacheable标注在getComFromRedis方法上,表示当该方法中的代码执行从关系数据库查询(这里是通过调用MyBatis接口的queryByPid方法)数据操作的同时,就自动将查到的结果存一份进Redis,下一次再执行该方法时就直接从Redis得到数据,不再访问关系数据库。注解的key属性指定查询所依据的键为#pid(商品号)。(b)@CachePut(value="commoditys",key="#pid"):注解@CachePut通常标注在对关系数据库进行插入或更新操作的方法上,方法中的程序代码每操作一次关系数据库,SpringBoot都会自动将操作的结果(插入的记录、更新后的记录)存入一份进Redis或替换掉Redis中原有的旧数据,使得Redis内容始终保持与关系数据库中的最新值同步一致。(c)@CachePut(value="commoditys",condition="#result!='null'",key="#pid"):condition属性指定当结果返回为空(比如关系数据库中并不存在要更新的记录)时,不操作Redis。(d)@CacheEvict(value="commoditys",key="#pid"):注解@CacheEvict标注的方法在对关系数据库执行了删除操作之后,SpringBoot也会同步删除Redis中指定键(#pid)的记录。Redis开发入门与应用(6)编写控制器在项目工程目录树的com.example.rediscache节点下创建controller包,其中创建控制器类ComController,代码显示。(7)启用缓存注解最后,还要在项目主启动文件RedisCacheApplication.java中用@EnableCaching来启用缓存注解,使之生效,如下:packagecom.example.rediscache;
importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.cache.annotation.EnableCaching;
@EnableCaching //启用缓存注解@SpringBootApplicationpublicclassRedisCacheApplication{ publicstaticvoidmain(String[]args){ SpringApplication.run(RedisCacheApplication.class,args); }}Redis开发入门与应用(8)运行①获取商品记录(未用缓存)为了对比说明,先来测试一下未使用缓存时的情形。注释掉程序中的“@Cacheable(value="commoditys",key="#pid")”,如图5.38所示,然后启动项目。打开浏览器,地址栏输入http://localhost:8080/com/getcom?pid=1002回车,获取商品号1002的记录对象,显示如图5.39所示。Redis开发入门与应用在上图5.39的浏览器页面上右击鼠标,点“重新加载”,向后台再请求获取一次该商品的记录对象。回到IDEA环境,从底部子窗口的输出中可以看到,系统先后执行了两次SELECT语句查询MySQL的商品表,而并未使用Redis缓存。Redis开发入门与应用②获取商品记录(启用缓存)将代码“//@Cacheable(value="commoditys",key="#pid")”前的注释去掉,重新启动项目,打开浏览器。地址栏输入http://localhost:8080/com/getcom?pid=1002回车,看到页面显示记录对象后,再重新加载一次页面。此时打开Redis客户端,可看到其中db0数据库节点下多了个“commoditys”子节点,点开后就能看到Redis中缓存的1002号商品记录,如图5.41所示。Redis开发入门与应用再回到IDEA环境,从底部子窗口输出中看到整个过程中系统仅执行了一次SELECT语句查询MySQL商品表,如图5.42所示。Redis开发入门与应用③删除商品记录(同步清除缓存)地址栏输入http://localhost:8
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年个人汽车销售合同
- 2024年分期赔偿损失合同
- 2024年5G网络基站建设项目合作合同
- 2024年广告代理与发布合同(含媒体投放)
- 2024年PLC技术培训与技术支持服务合同
- 2024年修订版:知识产权许可协议
- 2024年冰淇淋配送服务协议书
- 2024年商业空间装修协议下载
- 2024年二手房交易分期付款合同
- 2024年城市轨道交通建设与维护长期供应合同
- 新青岛版五四制2021-2022四年级科学上册实验指导
- 副神经节瘤图文.ppt
- 业务流程绘制方法IDEF和IDEFPPT课件
- (完整版)垃圾自动分拣机构PLC控制毕业设计.doc
- 小学四年级音乐课程标准
- 我的一次教研经历
- 双向细目表和单元测试卷及组卷说明
- 工业厂房中英文对照施工组织设计(土建、水电安装)范本
- PCR仪使用手册
- 离子色谱法测定空气中二氧化硫
- 水蒸汽热力性质表
评论
0/150
提交评论