版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第5章SpringBoot數(shù)據(jù)庫開發(fā)——數(shù)據(jù)庫與持久層框架SpringBoot實(shí)用教程(第4版)數(shù)據(jù)庫與持久層框架目前最為常用的持久層框架有:MyBatis、JPA、DataRedis和DataMongoDB等,其中MyBatis、JPA通過驅(qū)動操作各種關(guān)系數(shù)據(jù)庫(如MySQL、SQLServer等),而DataRedis和DataMongoDB則分別用于操作NoSQL型的Redis和MongoDB數(shù)據(jù)庫,如圖5.1所示。第5章SpringBoot數(shù)據(jù)庫開發(fā)——MyBatis開發(fā)基礎(chǔ)目錄01MyBatis簡介MyBatis簡介MyBatis是一個支持定制化SQL、存儲過程以及高級映射的優(yōu)秀持久層框架,它避免了幾乎所有的JDBC代碼、手動設(shè)置參數(shù)以及獲取結(jié)果集,可以對配置和原生Map使用簡單的注解,將接口和Java的POJO映射成數(shù)據(jù)庫中的記錄。MyBatis采用的是一種基于SQL到POJO的模型,它需要開發(fā)者提供SQL、映射關(guān)系和POJO類。對于SQL與POJO的映射關(guān)系,它提供了自動映射和駝峰映射等,大大減少了開發(fā)者的工作量;由于沒有屏蔽SQL,使開發(fā)者可以盡可能地通過SQL去優(yōu)化性能,也可以做少量的改變以適應(yīng)靈活多變的互聯(lián)網(wǎng)環(huán)境,這些對于追求高響應(yīng)和高性能的互聯(lián)網(wǎng)應(yīng)用系統(tǒng)是十分重要的。與此同時,它還能支持動態(tài)SQL,以適應(yīng)需求的變化。因而MyBatis隨著中國互聯(lián)網(wǎng)產(chǎn)業(yè)的發(fā)展日趨流行并成為國內(nèi)市場的主流持久層框架。MyBatis社區(qū)為了整合Spring早就發(fā)布了相應(yīng)的開發(fā)包,SpringBoot則進(jìn)一步將其整合進(jìn)來作為SQL依賴的一個基本組件,我們可以在開發(fā)時勾選MyBatis社區(qū)提供的starter,就可以直接在項(xiàng)目中使用MyBatis。目錄02MyBatis原理MyBatis原理MyBatis是一個基于SqlSessionFactory構(gòu)建的框架,SqlSessionFactory的作用是生成SqlSession接口對象,這個接口對象是MyBatis操作的核心。由于SqlSessionFactory的作用是單一(僅用于創(chuàng)建SqlSession)的,故其在MyBatis應(yīng)用的生命周期中往往會以單例模式(即只存在一個SqlSessionFactory對象)運(yùn)行。SpringBoot將MyBatis框架整合進(jìn)來,提供了兩個類:MapperFactoryBean和MapperScannerConfigurer,這里的MapperFactoryBean是針對一個接口配置,而MapperScannerConfigurer則負(fù)責(zé)掃描裝配,如圖5.2所示。MyBatis原理生成SqlSessionFactory是通過配置類來完成的,它會給予用戶在配置文件(perties)中進(jìn)行配置的選項(xiàng),從圖5.2中可以了解MyBatis可配置的主要內(nèi)容有:properties(屬性):在實(shí)際應(yīng)用中一般采用Spring而非MyBatis來配置屬性文件。mappers(映射器):是MyBatis最核心的組件,它提供SQL與POJO類的映射關(guān)系,這是MyBatis開發(fā)的核心。objectFactory(對象工廠):在MyBatis生成返回的POJO時會調(diào)用這個工廠類,實(shí)際開發(fā)一般使用MyBatis默認(rèn)提供的對象工廠類(DefaultObjectFactory),無須額外配置。settings(設(shè)置):可以配置映射規(guī)則(如自動映射或駝峰映射)、執(zhí)行器類型、緩存等,決定MyBatis的底層行為,比較復(fù)雜,具體配置項(xiàng)可參考MyBatis官網(wǎng)說明。plugins(插件):也稱為攔截器,它通過動態(tài)代理和責(zé)任鏈模式來完成,可以修改MyBatis底層的功能實(shí)現(xiàn)。typeAliases(類型別名):MyBatis會對常用的類提供默認(rèn)別名,由于類的全限定名通常會比較冗長,通過typeAliases配置自定義的別名能增強(qiáng)可讀性。databaseIdProvider(數(shù)據(jù)庫廠商標(biāo)識):允許MyBatis配置多類型數(shù)據(jù)庫的支持,不常用。environments(數(shù)據(jù)庫環(huán)境):可配置數(shù)據(jù)庫連接的內(nèi)容和事務(wù),通常這些都交由Spring托管。typeHandlers(類型處理器):在MyBatis寫入和讀取數(shù)據(jù)庫的過程中對于不同類型的數(shù)據(jù)進(jìn)行自定義轉(zhuǎn)換,但在大多數(shù)情況下用不到,因?yàn)镸yBatis本身就已經(jīng)定義好了很多現(xiàn)成的typeHandler,框架會自動識別并實(shí)現(xiàn)各種常用類型的轉(zhuǎn)換。目錄03MyBatis注解1.基礎(chǔ)注解2.映射注解3.高級注解MyBatis注解1.基礎(chǔ)注解增刪改查是所有關(guān)系數(shù)據(jù)庫最基本的業(yè)務(wù)操作,MyBatis提供下面四個基礎(chǔ)注解供用戶構(gòu)建自己的SQL語句:@Select:用于構(gòu)建查詢(SELECT)語句。@Insert:用于構(gòu)建插入(INSERT)語句。@Update:用于構(gòu)建更新(UPDATE)語句。@Delete:用于構(gòu)建刪除(DELETE)語句。MyBatis注解2.映射注解映射注解用于建立實(shí)體與關(guān)系的映射,MyBatis提供的映射注解有以下三個:@Result:用于填寫結(jié)果集的單個字段的映射關(guān)系。@Results:用于填寫結(jié)果集的多個字段的映射關(guān)系。@ResultMap:根據(jù)ID關(guān)聯(lián)XML里面的<resultMap>。3.高級注解MyBatis對應(yīng)基礎(chǔ)的增刪改查提供有以下四個高級注解:@SelectProvider:用于構(gòu)建動態(tài)查詢SQL。@InsertProvider:用于構(gòu)建動態(tài)插入SQL。@UpdateProvider:用于構(gòu)建動態(tài)更新SQL。@DeleteProvider:用于構(gòu)建動態(tài)刪除SQL。目錄04MyBatis應(yīng)用實(shí)例1.準(zhǔn)備數(shù)據(jù)2.創(chuàng)建項(xiàng)目3.配置連接4.MyBatis實(shí)現(xiàn)商品管理5.分頁功能MyBatis應(yīng)用實(shí)例【實(shí)例5.1】通過MyBatis操作MySQL實(shí)現(xiàn)“商品信息管理系統(tǒng)”的“商品管理”(包括商品添加、刪除、修改、查詢和分頁顯示)功能。1.準(zhǔn)備數(shù)據(jù)本例演示程序功能需要商品表(commodity)及其樣本記錄,而商品表又以外鍵關(guān)聯(lián)于商品分類表(category)和商家表(supplier)的記錄,故要先分別創(chuàng)建這幾個表及錄入必需的樣本數(shù)據(jù)。通過NavicatPremium連上MySQL,在其查詢編輯器中執(zhí)行SQL語句。(1)創(chuàng)建商品分類表(category)及錄入樣本執(zhí)行SQL語句為:USEnetshop;CREATETABLEcategory( TCode char(3) NOTNULLPRIMARYKEY, /*商品分類編碼*/ TName varchar(8) NOTNULL /*商品分類名稱*/);INSERTINTOcategory VALUES ('11A','蘋果'), ('11B','梨');MyBatis應(yīng)用實(shí)例(2)錄入商家表(supplier)的樣本商家表在做前面章節(jié)實(shí)例的時候已經(jīng)創(chuàng)建好了,此處只須錄入樣本,執(zhí)行SQL語句為:USEnetshop;INSERTINTOsupplier(SCode,SName,SweiXin,Tel)VALUES('SDYT002A','山東煙臺棲霞蘋果批發(fā)市場','8234561-','0535-823456X');INSERTINTOsupplier(SCode,SName,SWeiXin,Tel)VALUES('XJAK003A','新疆阿克蘇地區(qū)紅旗坡農(nóng)場','8345612-','0997-834561X');INSERTINTOsupplier(SCode,SName,SWeiXin,Tel)VALUES('XJAK005B','新疆安利達(dá)果業(yè)有限公司','8456123-','0996-845612X');INSERTINTOsupplier(SCode,SName,SWeiXin,Tel)VALUES('AHSZ006B','安徽碭山皇冠梨供應(yīng)公司','8561234-','0557-856123X');(3)創(chuàng)建商品表(commodity)及錄入樣本執(zhí)行SQL語句為。MyBatis應(yīng)用實(shí)例2.創(chuàng)建項(xiàng)目創(chuàng)建SpringBoot項(xiàng)目,項(xiàng)目名為MyBatis,在出現(xiàn)的向?qū)Ы缑妗癉ependencies”列表中勾選SpringBoot基本框架(“Web”→“SpringWeb”)、Thymeleaf引擎組件(“TemplateEngines”→“Thymeleaf”)、Lombok模型簡化組件(“DeveloperTools”→“Lombok”)、MyBatis框架(“SQL”→“MyBatisFramework”)以及MySQL的驅(qū)動(“SQL”→“MySQLDriver”)。3.配置連接打開項(xiàng)目工程目錄樹src→main→resources下的perties文件,在其中配置對MySQL數(shù)據(jù)庫的連接,內(nèi)容如下: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應(yīng)用實(shí)例4.MyBatis實(shí)現(xiàn)商品管理(1)設(shè)計(jì)模型本例用到的模型就是一個商品類,在項(xiàng)目工程目錄樹的com.example.mybatis節(jié)點(diǎn)下創(chuàng)建model包,其中創(chuàng)建Commodity.java,代碼為:packagecom.example.mybatis.model;
importlombok.Data;
@DatapublicclassCommodity{ privateintpid; //商品號 privateStringtcode; //商品分類編碼 privateStringscode; //商家編碼 privateStringpname; //商品名稱 privatefloatpprice; //商品價(jià)格 privateintstocks; //商品庫存}MyBatis應(yīng)用實(shí)例(2)定義數(shù)據(jù)接口使用MyBatis的持久層數(shù)據(jù)接口還是需要由用戶自己來開發(fā)定義的。在項(xiàng)目工程目錄樹的com.example.mybatis節(jié)點(diǎn)下創(chuàng)建mapper包,其中創(chuàng)建接口ComMapper,在接口中以MyBatis的注解分別構(gòu)建對商品模型實(shí)體增刪改查的各個SQL語句。接口ComMapper.java的定義代碼為:(3)開發(fā)控制器由于本例業(yè)務(wù)邏輯很簡單,且旨在演示MyBatis持久層的操作機(jī)制,故省去業(yè)務(wù)層的開發(fā),直接用控制器來調(diào)用Mapper接口中的方法。在項(xiàng)目工程目錄樹的com.example.mybatis節(jié)點(diǎn)下創(chuàng)建controller包,其中創(chuàng)建控制器類MyBController,代碼顯示。MyBatis應(yīng)用實(shí)例(4)運(yùn)行啟動SpringBoot項(xiàng)目,打開瀏覽器,分別測試MyBatis對商品記錄增刪改查的操作。①查詢商品號為1的商品記錄地址欄輸入http://localhost:8080/com/get?pid=1回車,看到1號商品記錄信息如圖5.3所示。MyBatis應(yīng)用實(shí)例②查詢所有的商品記錄地址欄輸入http://localhost:8080/com/getall回車,看到當(dāng)前數(shù)據(jù)庫商品表中所有的商品記錄信息如圖5.4所示。MyBatis應(yīng)用實(shí)例③添加商品記錄添加一個商品號為1002的商品,通過URL請求參數(shù)傳遞該商品的各項(xiàng)基本信息,在地址欄輸入http://localhost:8080/com/add?pid=1002&tcode=11B&scode=AHSZ006B&pname=碭山梨5斤箱裝特大果&pprice=17.90&stocks=6834回車,運(yùn)行結(jié)果如圖5.5所示,打開數(shù)據(jù)庫商品表,可看到新添加的商品。MyBatis應(yīng)用實(shí)例④更新商品庫存修改新添加的1002號商品的庫存(增加1000),地址欄輸入http://localhost:8080/com/set?pid=1002&stocks=7834回車,運(yùn)行結(jié)果如圖5.6所示,打開數(shù)據(jù)庫商品表,看到庫存已更新。MyBatis應(yīng)用實(shí)例⑤刪除商品記錄刪除剛添加的1002號商品,地址欄輸入http://localhost:8080/com/del?pid=1002回車,運(yùn)行結(jié)果如圖5.7所示。運(yùn)行完再次打開商品表,看到已沒有了1002號商品記錄。MyBatis應(yīng)用實(shí)例5.分頁功能在實(shí)際開發(fā)中,如果要顯示的商品信息記錄數(shù)很多,就要采用分頁顯示,分頁功能可以通過PageHelper來實(shí)現(xiàn),步驟如下。(1)添加PageHelper插件PageHelper是MyBatis框架的一個插件,專用于支持在MyBatis應(yīng)用中執(zhí)行分頁操作,使用前需要先添加依賴到項(xiàng)目中。打開項(xiàng)目的pom.xml文件,添加內(nèi)容如下:<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>4.1.6</version></dependency>MyBatis應(yīng)用實(shí)例(2)開發(fā)配置類PageHelper需要以Java配置的方式注入SpringBoot容器中才能使用,為此要先開發(fā)一個配置類。在項(xiàng)目工程目錄樹的com.example.mybatis節(jié)點(diǎn)下創(chuàng)建configer包,其中創(chuàng)建配置類PageConfiger.java,代碼顯示。說明:Properties為PageHelper設(shè)置屬性,這里設(shè)了3個屬性:“offsetAsPageNum”設(shè)為true,將RowBounds第1個參數(shù)offset作為頁碼(pageNum);“rowBoundsWithCount”設(shè)為true,在使用RowBounds分頁時進(jìn)行count查詢;“reasonable”啟用合理化,若pageNum小于1,查詢首頁,若pageNum大于總頁數(shù)(pages),則查詢尾頁。MyBatis應(yīng)用實(shí)例(3)開發(fā)控制器在項(xiàng)目controller包中創(chuàng)建分頁控制器類PageController,代碼顯示。說明:①控制器方法通過兩個參數(shù)start和size分別接收當(dāng)前頁碼及每頁要顯示的記錄數(shù)。②調(diào)用PageHelper的startPage方法(傳入start和size參數(shù))執(zhí)行分頁,還可以設(shè)置排序方式,這里設(shè)為“"PidDESC"”表示按商品號降序排列。③分頁插件通過一個PageInfo類型的對象來創(chuàng)建分頁形式的數(shù)據(jù)集合,將其直接傳遞(通過addAttribute方法添加)給視圖即可在前端頁面上顯示。(4)設(shè)計(jì)前端頁面在項(xiàng)目工程目錄樹的src→main→resources→templates節(jié)點(diǎn)下創(chuàng)建前端頁面index.html,代碼顯示。MyBatis應(yīng)用實(shí)例(5)運(yùn)行啟動項(xiàng)目,打開瀏覽器,地址欄輸入http://localhost:8080/compage/getall回車,看到分頁表格顯示的商品信息,可以通過點(diǎn)擊表格底部的“下一頁”、“上一頁”、“尾頁”和“首頁”等鏈接翻看不同頁的記錄,如圖5.8所示。第5章SpringBoot數(shù)據(jù)庫開發(fā)——JPA開發(fā)基礎(chǔ)目錄01JPA簡
介JPA簡介JPA(JavaPersistenceAPI)最初是由Java官方提出的一個持久化規(guī)范,它通過注解或XML描述對象—關(guān)系(表)的映射關(guān)系,并將內(nèi)存中的實(shí)體對象持久化到數(shù)據(jù)庫。JPA屬于JSR-220(EJB3.0)規(guī)范的一部分,但是JSR-220規(guī)定實(shí)體對象(EntityBean)由JPA進(jìn)行支持,所以JPA不僅僅局限于EJB3.0,在傳統(tǒng)輕量級JavaEE開發(fā)時代,著名的持久層框架Hibernate實(shí)現(xiàn)了完全的JPA規(guī)范,JPA也就隨著Hibernate的廣泛應(yīng)用而流行起來。后來,Spring推出了一個名為SpringData的子項(xiàng)目,旨在統(tǒng)一和簡化各類型數(shù)據(jù)的持久化存儲方式,其中的SpringDataJPA封裝了Hibernate作為JPA規(guī)范的默認(rèn)實(shí)現(xiàn),這也就是當(dāng)前SpringBoot中所支持的JPA,即通常所謂的“JPA框架”,如圖5.9所示。目錄02JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)1.創(chuàng)建關(guān)聯(lián)表2.創(chuàng)建項(xiàng)目3.配置連接4.設(shè)計(jì)關(guān)聯(lián)實(shí)體5.開發(fā)持久層6.編寫控制器7.運(yùn)行演示“一對一”JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)【實(shí)例5.2】保存商品圖片的同時向商品表中添加對應(yīng)商品的記錄,刪除圖片時也聯(lián)動一起刪除該商品記錄。1.創(chuàng)建關(guān)聯(lián)表之前做實(shí)例時已經(jīng)在數(shù)據(jù)庫中創(chuàng)建了商品表(commodity),現(xiàn)在還需要建一個與之關(guān)聯(lián)的商品圖片表(commodityimage)。執(zhí)行如下SQL語句:USEnetshop;CREATETABLEcommodityimage( Pid int(8) NOTNULLPRIMARYKEY, /*商品號*/ Image blob NOTNULL, /*商品圖片(最大64KB)*/
FOREIGNKEY(Pid)REFERENCEScommodity(Pid) ONDELETECASCADEONUPDATECASCADE);JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)2.創(chuàng)建項(xiàng)目創(chuàng)建SpringBoot項(xiàng)目,項(xiàng)目名為JpaOneToOne,在出現(xiàn)的向?qū)Ы缑妗癉ependencies”列表中勾選SpringBoot基本框架(“Web”→“SpringWeb”)、Lombok模型簡化組件(“DeveloperTools”→“Lombok”)、JPA框架(“SQL”→“SpringDataJPA”)以及MySQL的驅(qū)動(“SQL”→“MySQLDriver”)。3.配置連接在項(xiàng)目perties文件中配置對MySQL數(shù)據(jù)庫的連接,內(nèi)容如下: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實(shí)現(xiàn)“一對一”關(guān)聯(lián)4.設(shè)計(jì)關(guān)聯(lián)實(shí)體在項(xiàng)目工程目錄樹的com.example.jpaonetoone節(jié)點(diǎn)下創(chuàng)建entity包,其中創(chuàng)建兩個關(guān)聯(lián)的實(shí)體類。(1)商品實(shí)體商品實(shí)體對應(yīng)的是商品表(commodity),設(shè)計(jì)實(shí)體類Commodity.java,代碼如下:packagecom.example.jpaonetoone.entity;
importlombok.Data;
importjavax.persistence.*;
@Entity //@Entity注解聲明該模型類為一個實(shí)體@Data@Table(name="commodity") //@Table注解聲明實(shí)體所對應(yīng)的數(shù)據(jù)庫表名publicclassCommodity{ @Id //@Id注解標(biāo)注表的主鍵所對應(yīng)的實(shí)體類屬性(這里是商品號pid) privateintpid; privateStringtcode; privateStringscode; privateStringpname; privatefloatpprice; privateintstocks;}JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)(2)商品圖片實(shí)體商品圖片實(shí)體對應(yīng)的是商品圖片表(commodityimage),設(shè)計(jì)實(shí)體類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; //添加定義與之對應(yīng)的商品實(shí)體對象屬性}JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)5.開發(fā)持久層有了JPA框架,持久層的開發(fā)就變得極為簡單,只須定義接口繼承JPA的JpaRepository接口即可,用戶完全不用自己去編寫任何實(shí)現(xiàn)代碼。在項(xiàng)目工程目錄樹的com.example.jpaonetoone節(jié)點(diǎn)下創(chuàng)建repository包,其中創(chuàng)建兩個接口,分別對應(yīng)操作兩個實(shí)體。(1)操作商品實(shí)體的接口創(chuàng)建接口ComRepository.java,其定義代碼如下:packagecom.example.jpaonetoone.repository;
importcom.example.jpaonetoone.entity.Commodity;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceComRepositoryextendsJpaRepository<Commodity,Integer>{ CommodityqueryByPid(intpid); //根據(jù)商品號查詢商品實(shí)體}JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)(2)操作商品圖片實(shí)體的接口創(chuàng)建接口ImgRepository.java,其定義代碼如下:packagecom.example.jpaonetoone.repository;
importcom.example.jpaonetoone.entity.Commodityimage;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceImgRepositoryextendsJpaRepository<Commodityimage,Integer>{ voiddeleteById(intpid); //根據(jù)商品號刪除商品圖片實(shí)體}JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)說明:上面接口中的兩個方法queryByPid和deleteById都是JPA框架內(nèi)置的,只要用戶自定義的接口繼承了JPA的JpaRepository就可以直接拿來用,在編程時由JPA按默認(rèn)約定自動提示用戶鍵入所需的方法名,如圖5.10所示操作即可。JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)6.編寫控制器要測試以上建立的一對一關(guān)聯(lián)是否成立,需要編寫測試程序,本例的測試主程序代碼寫在控制器中。在項(xiàng)目工程目錄樹的com.example.jpaonetoone節(jié)點(diǎn)下創(chuàng)建controller包,其中創(chuàng)建控制器類JpaController.java,代碼顯示。7.運(yùn)行演示“一對一”(1)準(zhǔn)備本例需要用到的商品圖片保存在C:\CommodityPictures\(與控制器代碼中指定的要一致)目錄,圖片名為“碭山梨.jpg”,如圖5.11所示。啟動項(xiàng)目,打開瀏覽器。JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)(2)測試關(guān)聯(lián)添加地址欄輸入http://localhost:8080/com/add?pid=1002&tcode=11B&scode=AHSZ006B&pname=碭山梨5斤箱裝特大果&pprice=17.90&stocks=6834回車,商品號1002的記錄隨著圖片一起保存到了數(shù)據(jù)庫,前端顯示從數(shù)據(jù)庫查到的商品記錄,如圖5.12所示。JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)打開數(shù)據(jù)庫,可看到同步保存的圖片與商品記錄,如圖5.13所示。JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)從IDEA開發(fā)環(huán)境底部子窗口的輸出中可看到,JPA先后執(zhí)行了兩條INSERT語句,如圖5.14所示。JPA實(shí)現(xiàn)“一對一”關(guān)聯(lián)(3)測試聯(lián)動刪除地址欄輸入http://localhost:8080/com/del?pid=1002回車,前端顯示信息如圖5.15所示。再次打開數(shù)據(jù)庫,可看到圖片及商品記錄都已經(jīng)一并刪除了。從IDEA輸出中也可看到JPA是先后執(zhí)行了兩條DELETE語句,如圖5.16所示。目錄03JPA實(shí)現(xiàn)“一對多”關(guān)聯(lián)1.創(chuàng)建項(xiàng)目2.配置連接3.設(shè)計(jì)關(guān)聯(lián)實(shí)體4.開發(fā)持久層5.編寫控制器6.運(yùn)行演示“一對多”JPA實(shí)現(xiàn)“一對多”關(guān)聯(lián)【實(shí)例5.3】向商品表中添加商品記錄,并顯示某商家所提供的全部商品的信息。本例所涉及的關(guān)聯(lián)表:商家表(supplier)和商品表(commodity)在之前做實(shí)例的時候都已經(jīng)建好了。1.創(chuàng)建項(xiàng)目創(chuàng)建SpringBoot項(xiàng)目,項(xiàng)目名為JpaOneToMany,在出現(xiàn)的向?qū)Ы缑妗癉ependencies”列表中勾選SpringBoot基本框架(“Web”→“SpringWeb”)、Lombok模型簡化組件(“DeveloperTools”→“Lombok”)、JPA框架(“SQL”→“SpringDataJPA”)以及MySQL的驅(qū)動(“SQL”→“MySQLDriver”)。2.配置連接在項(xiàng)目perties文件中配置MySQL數(shù)據(jù)庫連接,配置內(nèi)容與【實(shí)例5.2】的完全相同,略。JPA實(shí)現(xiàn)“一對多”關(guān)聯(lián)3.設(shè)計(jì)關(guān)聯(lián)實(shí)體在項(xiàng)目工程目錄樹的com.example.jpaonetomany節(jié)點(diǎn)下創(chuàng)建entity包,其中創(chuàng)建關(guān)聯(lián)實(shí)體類。(1)商品實(shí)體商品實(shí)體對應(yīng)商品表(commodity),實(shí)體類Commodity.java,其設(shè)計(jì)代碼與【實(shí)例5.2】相同,可直接拿來復(fù)用(僅所在包名修改一致即可),略。JPA實(shí)現(xiàn)“一對多”關(guān)聯(lián)(2)商家實(shí)體商家實(shí)體對應(yīng)商家表(supplier),設(shè)計(jì)實(shí)體類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)//單向關(guān)系的一對多注解,用于“一”(商家)一方 @JoinColumn(name="SCode") //商品表通過外鍵SCode(商家編碼)關(guān)聯(lián)商家表 privateList<Commodity>commodityList;//添加定義列表(集合)類型的屬性}JPA實(shí)現(xiàn)“一對多”關(guān)聯(lián)4.開發(fā)持久層在項(xiàng)目工程目錄樹的com.example.jpaonetomany節(jié)點(diǎn)下創(chuàng)建repository包,其中創(chuàng)建兩個接口。(1)操作商品實(shí)體的接口創(chuàng)建接口ComRepository.java,其定義代碼如下:packagecom.example.jpaonetomany.repository;
importcom.example.jpaonetomany.entity.Commodity;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceComRepositoryextendsJpaRepository<Commodity,Integer>{}(2)操作商家實(shí)體的接口創(chuàng)建接口SupRepository.java,其定義代碼如下:packagecom.example.jpaonetomany.repository;
importcom.example.jpaonetomany.entity.Supplier;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceSupRepositoryextendsJpaRepository<Supplier,String>{ SupplierfindSupplierByScode(Stringscode); //根據(jù)商家編碼查詢商家實(shí)體}JPA實(shí)現(xiàn)“一對多”關(guān)聯(lián)5.編寫控制器在控制器中編寫程序來測試以上一對多的關(guān)聯(lián)。在項(xiàng)目工程目錄樹的com.example.jpaonetomany節(jié)點(diǎn)下創(chuàng)建controller包,其中創(chuàng)建控制器類JpaController.java,代碼顯示。6.運(yùn)行演示“一對多”啟動項(xiàng)目,打開瀏覽器。(1)添加商品地址欄輸入http://localhost:8080/sup/addcom?pid=1002&tcode=11B&scode=AHSZ006B&pname=碭山梨5斤箱裝特大果&pprice=17.90&stocks=6834回車,將商品號1002的記錄添加到數(shù)據(jù)庫,前端顯示如圖5.17所示。JPA實(shí)現(xiàn)“一對多”關(guān)聯(lián)而數(shù)據(jù)庫商家表中,1002號商品的商家編碼“AHSZ006B”所對應(yīng)的商家名稱也正是“安徽碭山皇冠梨供應(yīng)公司”,如圖5.18所示。JPA實(shí)現(xiàn)“一對多”關(guān)聯(lián)(2)顯示某商家提供的商品信息地址欄輸入http://localhost:8080/sup/findcom?scode=AHSZ006B回車,顯示出商家“AHSZ006B”所提供的全部商品信息,如圖5.19所示,這與數(shù)據(jù)庫中的記錄也是一致的。目錄04JPA實(shí)現(xiàn)“多對多”關(guān)聯(lián)1.創(chuàng)建關(guān)聯(lián)表2.創(chuàng)建項(xiàng)目3.配置連接4.設(shè)計(jì)關(guān)聯(lián)實(shí)體5.開發(fā)持久層6.編寫控制器7.運(yùn)行演示“多對多”JPA實(shí)現(xiàn)“多對多”關(guān)聯(lián)【實(shí)例5.4】創(chuàng)建兩個用戶,將同一種商品加入購物車。1.創(chuàng)建關(guān)聯(lián)表“多對多”關(guān)聯(lián)只能通過中間表的方式進(jìn)行映射,而不能通過外鍵。于是在本例中,就要涉及到用戶表(user)、商品表(commodity)以及它們的中間表購物車表(preshop),一共是3個表。其中,用戶表和商品表在之前做實(shí)例時已經(jīng)創(chuàng)建好了,下面來創(chuàng)建購物車表。執(zhí)行如下SQL語句:USEnetshop;CREATETABLEpreshop( UCode char(16) NOTNULL, /*用戶編碼*/ Pid int(8) NOTNULL, /*商品號*/ PRIMARY KEY(UCode,Pid));為了后面運(yùn)行程序的需要,先刪除前面已經(jīng)添加的商品號1002的記錄,執(zhí)行語句:DELETEFROMcommodityWHEREPid=1002;JPA實(shí)現(xiàn)“多對多”關(guān)聯(lián)2.創(chuàng)建項(xiàng)目創(chuàng)建SpringBoot項(xiàng)目,項(xiàng)目名為JpaManyToMany,在出現(xiàn)的向?qū)Ы缑妗癉ependencies”列表中勾選SpringBoot基本框架(“Web”→“SpringWeb”)、Lombok模型簡化組件(“DeveloperTools”→“Lombok”)、JPA框架(“SQL”→“SpringDataJPA”)以及MySQL的驅(qū)動(“SQL”→“MySQLDriver”)。3.配置連接在項(xiàng)目perties文件中配置MySQL數(shù)據(jù)庫連接,配置內(nèi)容與【實(shí)例5.2】的完全相同,略。JPA實(shí)現(xiàn)“多對多”關(guān)聯(lián)4.設(shè)計(jì)關(guān)聯(lián)實(shí)體由于是“多對多”關(guān)聯(lián),關(guān)系的任何一方都可以作為主控方,故在雙方的實(shí)體中都要定義一個集合類型的對方的對象屬性。在項(xiàng)目工程目錄樹的com.example.jpamanytomany節(jié)點(diǎn)下創(chuàng)建entity包,其中創(chuàng)建實(shí)體類。(1)用戶實(shí)體用戶實(shí)體對應(yīng)用戶表(user),設(shè)計(jì)實(shí)體類User.java,代碼顯示。(2)商品實(shí)體商品實(shí)體對應(yīng)商品表(commodity),設(shè)計(jì)實(shí)體類Commodity.java,代碼顯示。JPA實(shí)現(xiàn)“多對多”關(guān)聯(lián)5.開發(fā)持久層在項(xiàng)目工程目錄樹的com.example.jpamanytomany節(jié)點(diǎn)下創(chuàng)建repository包,其中創(chuàng)建兩個接口。(1)操作用戶實(shí)體的接口創(chuàng)建接口UserRepository.java,定義代碼為:packagecom.example.jpamanytomany.repository;
importcom.example.jpamanytomany.entity.User;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceUserRepositoryextendsJpaRepository<User,String>{}(2)操作商品實(shí)體的接口創(chuàng)建接口ComRepository.java,定義代碼為:packagecom.example.jpamanytomany.repository;
importcom.example.jpamanytomany.entity.Commodity;importorg.springframework.data.jpa.repository.JpaRepository;
publicinterfaceComRepositoryextendsJpaRepository<Commodity,Integer>{}JPA實(shí)現(xiàn)“多對多”關(guān)聯(lián)6.編寫控制器在控制器中編寫程序來測試以上多對多的關(guān)聯(lián)。在項(xiàng)目工程目錄樹的com.example.jpamanytomany節(jié)點(diǎn)下創(chuàng)建controller包,其中創(chuàng)建控制器類JpaController.java,代碼如下:7.運(yùn)行演示“多對多”啟動項(xiàng)目,打開瀏覽器,地址欄輸入http://localhost:8080/user/add?pid=1002&tcode=11B&scode=AHSZ006B&pname=碭山梨5斤箱裝特大果&pprice=17.90&stocks=6834回車,前端顯示如圖5.20所示。JPA實(shí)現(xiàn)“多對多”關(guān)聯(lián)此時,用戶表里添加了兩條新的用戶記錄,商品表里也添加進(jìn)了1002號商品,這些都是在控制器主程序中通過持久層接口調(diào)用save方法顯式保存進(jìn)數(shù)據(jù)庫的,如圖5.21所示。JPA實(shí)現(xiàn)“多對多”關(guān)聯(lián)因?yàn)樵谟脩魧?shí)體與商品實(shí)體間存在“多對多”關(guān)聯(lián),而我們在程序中用“commodity.setUsers(users)”設(shè)置了與1002號商品關(guān)聯(lián)的用戶實(shí)體集,相當(dāng)于這個實(shí)體集中的用戶都要購買1002號商品(加入購物車),故JPA還會自動在購物車表中添加記錄,如圖5.22所示。JPA實(shí)現(xiàn)“多對多”關(guān)聯(lián)另外,從IDEA輸出中也可看到JPA操作購物車表的SQL語句,如圖5.23所示。第5章SpringBoot數(shù)據(jù)庫開發(fā)——NoSQL開發(fā)基礎(chǔ)目錄01Redis開發(fā)入門與應(yīng)用1.Redis簡介2.Redis安裝3.模板操作Redis實(shí)例4.緩存注解操作Redis實(shí)例Redis開發(fā)入門與應(yīng)用1.Redis簡介Redis是一種運(yùn)行在內(nèi)存的數(shù)據(jù)庫,它是開源的、使用ANSIC語言編寫、遵守BSD協(xié)議、支持網(wǎng)絡(luò)、并提供多種語言的API。由于Redis是基于內(nèi)存的,所以它的運(yùn)行速度很快(大約是關(guān)系數(shù)據(jù)庫幾倍到幾十倍),在已報(bào)道的某些測試中,甚至可以完成每秒10萬次的讀寫,性能十分高效?,F(xiàn)實(shí)應(yīng)用中,數(shù)據(jù)的查詢要遠(yuǎn)多于更新,據(jù)統(tǒng)計(jì),一個正常網(wǎng)站日常查詢與更新之比大約是9:1到7:3,若是將常用的數(shù)據(jù)存儲在Redis中來代替關(guān)系數(shù)據(jù)庫的査詢訪問,將可以大幅提高網(wǎng)站的性能。Redis開發(fā)入門與應(yīng)用Redis擁有十分豐富的應(yīng)用場景,主要如下:計(jì)數(shù)器電商APP商品的瀏覽量、短視頻APP視頻的播放次數(shù)等信息都會被統(tǒng)計(jì),以便用于運(yùn)營或產(chǎn)品市場分析。為了保證數(shù)據(jù)實(shí)時生效,對用戶的每一次瀏覽都得計(jì)數(shù),這會導(dǎo)致非常高的并發(fā)量。這時可以用Redis提供的incr命令來實(shí)現(xiàn)計(jì)數(shù)器功能,由于一切操作都在內(nèi)存中進(jìn)行,所以性能極佳。社交互動使用Redis提供的散列、集合等數(shù)據(jù)類型,可以很方便地實(shí)現(xiàn)網(wǎng)站(或APP)中的點(diǎn)贊、踩、關(guān)注共同好友等社交場景的基本功能。排行榜可以利用Redis提供的有序集合數(shù)據(jù)類型實(shí)現(xiàn)各種復(fù)雜的排行榜應(yīng)用,如京東、淘寶的銷量榜,將商品按時間、銷量排行等。Redis開發(fā)入門與應(yīng)用最新列表Redis可以通過LPUSH在列表頭部插入一個內(nèi)容ID作為關(guān)鍵字,通過LTRIM限制列表的數(shù)量,這樣列表永遠(yuǎn)為N個ID,無須查詢最新的列表,直接根據(jù)ID查找對應(yīng)的內(nèi)容即可。分布式會話在集群模式下,一般都會搭建以Redis等內(nèi)存數(shù)據(jù)庫為中心的會話(Session)服務(wù),它不再由容器管理,而是由會話服務(wù)及內(nèi)存數(shù)據(jù)庫管理。高并發(fā)讀寫Redis特別適合將方法的運(yùn)行結(jié)果放入緩存,以便后續(xù)在請求方法時直接去緩存中讀取。這對執(zhí)行耗時、但結(jié)果不頻繁變動的SQL查詢的支持極好。在高并發(fā)的情況下,應(yīng)盡量避免請求直接訪問關(guān)系數(shù)據(jù)庫,這時可以使用Redis進(jìn)行緩存操作,讓請求先訪問Redis。Redis開發(fā)入門與應(yīng)用2.Redis安裝(1)下載RedisRedis下載地址為/tporadowski/redis/releases,如圖5.24所示,點(diǎn)頁面上的“Redis-x64-5.0.10.zip”鏈接下載ZIP壓縮版。Redis開發(fā)入門與應(yīng)用本書使用Redis5.0的Windows版,下載得到的壓縮包文件名為Redis-x64-5.0.10.zip。解壓后將其中所有文件復(fù)制存盤到一個指定的目錄(筆者保存在C:\redis),如圖5.25所示。Redis開發(fā)入門與應(yīng)用(2)啟動Redis打開Windows命令行,用cd命令進(jìn)入保存Redis的目錄,輸入如下命令啟動Redis:redis-server.exeredis.windows.conf命令行輸出如圖5.26所示信息,表示成功啟動Redis。Redis開發(fā)入門與應(yīng)用(3)安裝Redis服務(wù)圖5.26雖然啟動了Redis,但關(guān)閉命令行窗口后Redis也就關(guān)停了,為方便使用,需要把Redis安裝成Windows操作系統(tǒng)下的一個服務(wù)。關(guān)閉命令行窗口,重新打開,再次進(jìn)入保存Redis的目錄,執(zhí)行如下命令:redis-server--service-installredis.windows-service.conf--loglevelverbose稍候片刻,如果沒有報(bào)錯,如圖5.27所示,表示安裝成功。Redis開發(fā)入門與應(yīng)用此時,打開操作系統(tǒng)的“計(jì)算機(jī)管理”窗口,在系統(tǒng)服務(wù)列表中可以找到一個名為“Redis”的Windows服務(wù),如圖5.28所示。Redis開發(fā)入門與應(yīng)用(4)試用Redis在Redis服務(wù)啟動的情況下,通過命令行進(jìn)入保存Redis的目錄,輸入以下命令連接到Redis:redis-cli.exe-h-p6379該命令創(chuàng)建了一個地址為(本地)、端口號6379的Redis數(shù)據(jù)庫連接,然后就可以使用setkeyvalue和getkey命令保存和獲得數(shù)據(jù)。這里先試著往Redis數(shù)據(jù)庫中保存一個鍵名username、值為zhouhejun的記錄,依次輸入如下命令:setusernamezhouhejun
getusername以上整個過程的命令行輸入和顯示內(nèi)容如圖5.29所示。Redis開發(fā)入門與應(yīng)用(5)客戶端操作Redis以上對Redis的操作都是通過命令行執(zhí)行,比較麻煩且不夠直觀。目前,已經(jīng)有一些第三方開發(fā)的專用于操作Redis的可視化客戶端軟件。本書提供一個用Java開發(fā)的Redis客戶端RedisClient,下載地址是/caoxinyu/RedisClient,如圖5.30所示。Redis開發(fā)入門與應(yīng)用下載得到的壓縮包文件名為RedisClient-windows.zip,解壓后直接雙擊運(yùn)行RedisClient-windows\release目錄下的redisclient-win32.x86_64.2.0.jar,打開如圖5.31所示的界面。Redis開發(fā)入門與應(yīng)用右擊左側(cè)子窗口中的“Redisservers”節(jié)點(diǎn),點(diǎn)擊彈出的“Addserver”選項(xiàng)(或者選擇主菜單“Server”→“Add”),出現(xiàn)“Addserver”設(shè)置對話框,如圖5.32所示,在其中配置Redis連接。Redis開發(fā)入門與應(yīng)用創(chuàng)建連接后,可看到“Redisservers”節(jié)點(diǎn)下面多了個“MyRedis”節(jié)點(diǎn),雙擊展開可看到其中的數(shù)據(jù)庫,Redis中預(yù)置了db0~db15共16個數(shù)據(jù)庫。其中,db0是默認(rèn)的當(dāng)前數(shù)據(jù)庫,也就是說,前面通過命令行存進(jìn)去的鍵名username的記錄就在該數(shù)據(jù)庫中。雙擊db0,在右邊區(qū)域“Redisdataexplorer”選項(xiàng)頁中即可看到username條目,點(diǎn)擊記錄條目,在下方打開的選項(xiàng)頁中就可以看到該記錄的鍵名(Key)和值(Value),與命令行存入的一模一樣,如圖5.33所示。Redis開發(fā)入門與應(yīng)用3.模板操作Redis實(shí)例SpringBoot提供了StringRedisTemplate和RedisTemplate兩個模板來進(jìn)行Redis數(shù)據(jù)操作,其中,StringRedisTemplate只針對鍵值都是字符串類型的數(shù)據(jù),而RedisTemplate則可以操作對象類型的數(shù)據(jù)。這兩個模板提供的主要數(shù)據(jù)訪問方法如表5.1所示。方法功能opsForValue()操作只有簡單屬性的數(shù)據(jù)opsForHash()操作含有散列的數(shù)據(jù)opsForList()操作含有列表類型的數(shù)據(jù)opsForSet()操作含有集合類型的數(shù)據(jù)opsForZSet()操作含有有序集合的數(shù)據(jù)Redis開發(fā)入門與應(yīng)用【實(shí)例5.5】通過模板方式操作Redis,向其中存入商品信息。本例程序先用MyBatis從MySQL數(shù)據(jù)庫中讀取商品信息,然后再通過StringRedisTemplate/RedisTemplate模板操作將讀取的商品信息轉(zhuǎn)存入Redis內(nèi)存數(shù)據(jù)庫。(1)創(chuàng)建項(xiàng)目創(chuàng)建SpringBoot項(xiàng)目,項(xiàng)目名為RedisTemplate,在出現(xiàn)的向?qū)Ы缑妗癉ependencies”列表中勾選SpringBoot基本框架(“Web”→“SpringWeb”)、Lombok模型簡化組件(“DeveloperTools”→“Lombok”)、MyBatis框架(“SQL”→“MyBatisFramework”)以及MySQL的驅(qū)動(“SQL”→“MySQLDriver”)、Redis框架(“NoSQL”→“SpringDataRedis(Access+Driver)”)。(2)配置連接在項(xiàng)目perties文件中配置MySQL數(shù)據(jù)庫連接,配置內(nèi)容與【實(shí)例5.1】的相同,略。Redis開發(fā)入門與應(yīng)用(3)設(shè)計(jì)模型由于存儲到Redis的數(shù)據(jù)必須序列化,所以本例的商品模型類也要實(shí)現(xiàn)Java的序列化接口Serializable。在項(xiàng)目工程目錄樹的com.example.redistemplate節(jié)點(diǎn)下創(chuàng)建model包,其中創(chuàng)建Commodity.java,代碼為:packagecom.example.redistemplate.model;
importlombok.Data;
importjava.io.Serializable;
@DatapublicclassCommodityimplementsSerializable{ //必須序列化 privateintpid; //商品號 privateStringtcode; //商品分類編碼 privateStringscode; //商家編碼 privateStringpname; //商品名稱 privatefloatpprice; //商品價(jià)格 privateintstocks; //商品庫存}Redis開發(fā)入門與應(yīng)用(4)定義數(shù)據(jù)接口在項(xiàng)目工程目錄樹的com.example.redistemplate節(jié)點(diǎn)下創(chuàng)建mapper包,其中創(chuàng)建接口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開發(fā)入門與應(yīng)用(5)開發(fā)操作Redis的業(yè)務(wù)層通常開發(fā)中,讀取關(guān)系數(shù)據(jù)庫(如MySQL)的操作在持久層進(jìn)行,而操作NoSQL的工作卻是由業(yè)務(wù)層的服務(wù)實(shí)體來承擔(dān)的,這樣做使代碼分工明確,各模塊職能清晰。①定義業(yè)務(wù)接口在項(xiàng)目工程目錄樹的com.example.redistemplate節(jié)點(diǎn)下創(chuàng)建service包,其下定義名為ComService的接口,代碼為:packagecom.example.redistemplate.service;
importcom.example.redistemplate.model.Commodity;
publicinterfaceComService{ publicStringgetPNameFromRedis(intpid); //從Redis獲取商品名稱 publicCommoditygetComFromRedis(intpid); //從Redis獲取商品記錄對象}②開發(fā)服務(wù)實(shí)體在service包下創(chuàng)建業(yè)務(wù)接口的實(shí)現(xiàn)類ComServiceImpl,代碼顯示。Redis開發(fā)入門與應(yīng)用(6)編寫控制器在項(xiàng)目工程目錄樹的com.example.redistemplate節(jié)點(diǎn)下創(chuàng)建controller包,其中創(chuàng)建控制器類ComController,代碼顯示。(7)自定義配置RedisTemplateSpringBoot默認(rèn)配置的RedisTemplate使用JdkSerializationRedisSerializer來序列化數(shù)據(jù),由于JdkSerializationRedisSerializer是以二進(jìn)制形式存儲數(shù)據(jù)的,這對我們通過RedisClient可視化查看很不方便,故需要對RedisTemplate進(jìn)行配置,自定義其序列化器。在項(xiàng)目主啟動文件RedisTemplateApplication.java中進(jìn)行配置,添加代碼(加黑)如下。Redis開發(fā)入門與應(yīng)用(8)運(yùn)行啟動項(xiàng)目,打開瀏覽器。①從Redis獲取商品名稱地址欄輸入http://localhost:8080/com/getpname?pid=1回車,獲取商品號1的記錄的商品名稱,顯示如圖5.34所示。Redis開發(fā)入門與應(yīng)用此時,打開Redis客戶端,可看到其中存儲的鍵名為pname的商品名稱字符串,與前端顯示是一致的,如圖5.35所示。Redis開發(fā)入門與應(yīng)用②從Redis獲取商品記錄對象地址欄輸入http://localhost:8080/com/getcom?pid=1回車,獲取商品號1的記錄對象,顯示如圖5.36所示。Redis開發(fā)入門與應(yīng)用此時,打開Redis客戶端,可看到其中存儲的鍵名為1的商品記錄對象,其各字段內(nèi)容與前端顯示也是一致的,如圖5.37所示。Redis開發(fā)入門與應(yīng)用4.緩存注解操作Redis實(shí)例模板雖然能夠有效地操作Redis,但仍然需要用戶自己編程調(diào)用方法來實(shí)現(xiàn)操作,并不能完全自動化。為了進(jìn)一步簡化Redis的使用,SpringBoot提供了緩存注解,只要將注解加在需要操作Redis的方法上,在程序執(zhí)行方法代碼的時候就會自動進(jìn)行Redis的存取而無須用戶干預(yù),這種方式在實(shí)際中用得更加普遍。【實(shí)例5.6】用緩存注解方式操作Redis,實(shí)現(xiàn)內(nèi)存中商品信息的增刪改查。(1)創(chuàng)建項(xiàng)目創(chuàng)建SpringBoot項(xiàng)目,項(xiàng)目名為RedisCache,在出現(xiàn)的向?qū)Ы缑妗癉ependencies”列表中勾選SpringBoot基本框架(“Web”→“SpringWeb”)、Lombok模型簡化組件(“DeveloperTools”→“Lombok”)、MyBatis框架(“SQL”→“MyBatisFramework”)以及MySQL的驅(qū)動(“SQL”→“MySQLDriver”)、Redis框架(“NoSQL”→“SpringDataRedis(Access+Driver)”)。Redis開發(fā)入門與應(yīng)用(2)配置連接在項(xiàng)目perties文件中配置MySQL數(shù)據(jù)庫連接,內(nèi)容如下: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)設(shè)計(jì)模型本例也只用到了商品模型類Commodity.java,與【實(shí)例5.5】的完全一樣,也需要實(shí)現(xiàn)Java序列化Serializable接口,可以直接復(fù)用【實(shí)例5.5】的模型類,將其復(fù)制到項(xiàng)目的com.example.rediscache.model包下,改一下包路徑即可,代碼略。Redis開發(fā)入門與應(yīng)用(4)定義數(shù)據(jù)接口在項(xiàng)目工程目錄樹的com.example.rediscache節(jié)點(diǎn)下創(chuàng)建mapper包,其中創(chuàng)建接口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開發(fā)入門與應(yīng)用(5)開發(fā)業(yè)務(wù)層①定義業(yè)務(wù)接口在項(xiàng)目工程目錄樹的com.example.rediscache節(jié)點(diǎn)下創(chuàng)建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刪除商品記錄}②開發(fā)服務(wù)實(shí)體在service包下創(chuàng)建業(yè)務(wù)接口的實(shí)現(xiàn)類ComServiceImpl,代碼顯示。Redis開發(fā)入門與應(yīng)用說明:(a)@Cacheable(value="commoditys",key="#pid"):注解@Cacheable標(biāo)注在getComFromRedis方法上,表示當(dāng)該方法中的代碼執(zhí)行從關(guān)系數(shù)據(jù)庫查詢(這里是通過調(diào)用MyBatis接口的queryByPid方法)數(shù)據(jù)操作的同時,就自動將查到的結(jié)果存一份進(jìn)Redis,下一次再執(zhí)行該方法時就直接從Redis得到數(shù)據(jù),不再訪問關(guān)系數(shù)據(jù)庫。注解的key屬性指定查詢所依據(jù)的鍵為#pid(商品號)。(b)@CachePut(value="commoditys",key="#pid"):注解@CachePut通常標(biāo)注在對關(guān)系數(shù)據(jù)庫進(jìn)行插入或更新操作的方法上,方法中的程序代碼每操作一次關(guān)系數(shù)據(jù)庫,SpringBoot都會自動將操作的結(jié)果(插入的記錄、更新后的記錄)存入一份進(jìn)Redis或替換掉Redis中原有的舊數(shù)據(jù),使得Redis內(nèi)容始終保持與關(guān)系數(shù)據(jù)庫中的最新值同步一致。(c)@CachePut(value="commoditys",condition="#result!='null'",key="#pid"):condition屬性指定當(dāng)結(jié)果返回為空(比如關(guān)系數(shù)據(jù)庫中并不存在要更新的記錄)時,不操作Redis。(d)@CacheEvict(value="commoditys",key="#pid"):注解@CacheEvict標(biāo)注的方法在對關(guān)系數(shù)據(jù)庫執(zhí)行了刪除操作之后,SpringBoot也會同步刪除Redis中指定鍵(#pid)的記錄。Redis開發(fā)入門與應(yīng)用(6)編寫控制器在項(xiàng)目工程目錄樹的com.example.rediscache節(jié)點(diǎn)下創(chuàng)建controller包,其中創(chuàng)建控制器類ComController,代碼顯示。(7)啟用緩存注解最后,還要在項(xiàng)目主啟動文件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開發(fā)入門與應(yīng)用(8)運(yùn)行①獲取商品記錄(未用緩存)為了對比說明,先來測試一下未使用緩存時的情形。注釋掉程序中的“@Cacheable(value="commoditys",key="#pid")”,如圖5.38所示,然后啟動項(xiàng)目。打開瀏覽器,地址欄輸入http://localhost:8080/com/getcom?pid=1002回車,獲取商品號1002的記錄對象,顯示如圖5.39所示。Redis開發(fā)入門與應(yīng)用在上圖5.39的瀏覽器頁面上右擊鼠標(biāo),點(diǎn)“重新加載”,向后臺再請求獲取一次該商品的記錄對象。回到IDEA環(huán)境,從底部子窗口的輸出中可以看到,系統(tǒng)先后執(zhí)行了兩次SELECT語句查詢MySQL的商品表,而并未使用Redis緩存。Redis開發(fā)入門與應(yīng)用②獲取商品記錄(啟用緩存)將代碼“//@Cacheable(value="commoditys",key="#pid")”前的注釋去掉,重新啟動項(xiàng)目,打開瀏覽器。地址欄輸入http://localhost:8080/com/getcom?pid=1002回車,看到頁面顯示記錄對象后,再重新加載一次頁面。此時打開Redis客戶端,可看到其中db0數(shù)據(jù)庫節(jié)點(diǎn)下多了個“commoditys”子節(jié)點(diǎn),點(diǎn)開后就能看到Redis中緩存的1002號商品記錄,如圖5.41所示。Redis開發(fā)入門與應(yīng)用再回到IDEA環(huán)境,從底部子窗口輸出中看到整個過程中系統(tǒng)僅執(zhí)行了一次SELECT語句查詢MySQL商品表,如圖5.42所示。Redis開發(fā)入門與應(yīng)用③刪除商品記錄(同步清除緩存)地址欄輸入http://localhost:8
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年離婚財(cái)產(chǎn)分割及孩子撫養(yǎng)協(xié)議書
- 施工勞務(wù)承包合同協(xié)議書樣本
- 產(chǎn)業(yè)孵化基地入住協(xié)議
- 使用授權(quán)協(xié)議書要點(diǎn)解析
- 房屋互換合同格式
- 員工實(shí)習(xí)期勞務(wù)協(xié)議
- 中外專有技術(shù)轉(zhuǎn)讓協(xié)議
- 標(biāo)準(zhǔn)版委托檢驗(yàn)檢測協(xié)議書
- 5.2 凝聚價(jià)值追求 (大單元教學(xué)設(shè)計(jì)) 2024-2025學(xué)年統(tǒng)編版道德與法治九年級上冊
- 建筑項(xiàng)目施工合同書范本
- 【道法】認(rèn)識生命 課件-2024-2025學(xué)年統(tǒng)編版道德與法治七年級上冊
- 貴州省建筑與裝飾工程計(jì)價(jià)定額(2016版)
- JGT 486-2015 混凝土用復(fù)合摻合料
- 世界急救日常見的急救基本知識科普講座課件
- 鄉(xiāng)村振興民宿產(chǎn)業(yè)項(xiàng)目可行性研究報(bào)告
- 某縣紀(jì)委書記在整頓農(nóng)村三資管理工作會議上的講話
- DL∕T 1736-2017 光纖光柵儀器基本技術(shù)條件
- 茶藝上課教案
- 中秋國慶燈會彩燈設(shè)計(jì)方案
- 人教版部編語文一年級上冊全冊教學(xué)課件
- 外匯交易居間合同范本
評論
0/150
提交評論