Java EE( SSM + Spring Boot + Vue.js 3 )框架整合开发 课件 第8章 Spring Boot的数据访问_第1页
Java EE( SSM + Spring Boot + Vue.js 3 )框架整合开发 课件 第8章 Spring Boot的数据访问_第2页
Java EE( SSM + Spring Boot + Vue.js 3 )框架整合开发 课件 第8章 Spring Boot的数据访问_第3页
Java EE( SSM + Spring Boot + Vue.js 3 )框架整合开发 课件 第8章 Spring Boot的数据访问_第4页
Java EE( SSM + Spring Boot + Vue.js 3 )框架整合开发 课件 第8章 Spring Boot的数据访问_第5页
已阅读5页,还剩160页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第八章SpringBoot的数据访问授课教师:陈恒大连外国语大学本章目标掌握SpringDataJPA的解决方案掌握SpringBoot如何整合MyBatis了解SpringBoot如何整合REST了解SpringBoot如何整合MongoDB了解SpringBoot如何整合Redis理解数据缓存Cache的基本原理1本章内容28.1SpringDataJPA8.2SpringBoot整合MyBatis8.3REST8.4MongoDB8.5Redis8.6数据缓存Cache8.1SpringDataJPA8.1.1SpringBoot的支持8.1.2简单条件查询8.1.3关联查询8.1.4@Query和@Modifying注解8.1.5排序与分页查询3JPA(JavaPersistenceAPI)是官方提出的Java持久化规范。JPA通过注解或XML描述对象—关系(表)的映射关系,并将内存中的实体对象持久化到数据库。SpringDataJPA通过提供基于JPA的Repository极大地简化了JPA的写法,在几乎不写实现的情况下,实现数据库的访问和操作。使用SpringDataJPA建立数据访问层十分方便,只需要定义一个继承JpaRepository接口的接口即可。继承了JpaRepository接口的自定义数据访问接口,具有JpaRepository接口的所有数据访问操作方法。48.1SpringDataJPA8.1.1SpringBoot的支持在SpringBoot应用中,如果需要使用SpringDataJPA访问数据库,那么我们可以通过STS创建SpringBoot应用时选择SpringDataJPA模块依赖。51.JDBC的自动配置6spring-boot-starter-data-jpa依赖于spring-boot-starter-jdbc,而SpringBoot对spring-boot-starter-jdbc做了自动配置。JDBC自动配置源码位于org.springframework.boot.autoconfigure.jdbc包下。从该包的DataSourceProperties类可以看出,可以使用“spring.datasource”为前缀的属性在perties配置文件中配置datasource。2.JPA的自动配置SpringBoot对JPA的自动配置位于org.springframework.boot.autoconfigure.orm.jpa包下。从该包的HibernateJpaAutoConfiguration类可以看出,SpringBoot对JPA的默认实现是Hibernate;从该包的JpaProperties类可以看出,可以使用“spring.jpa”为前缀的属性在perties配置文件中配置JPA。73.SpringDataJPA的自动配置SpringBoot对SpringDataJPA的自动配置位于org.springframework.boot.autoconfigure.data.jpa包下。从该包的JpaRepositoriesAutoConfiguration类可以看出,JpaRepositoriesAutoConfiguration依赖于HibernateJpaAutoConfiguration配置;从该包的JpaRepositoriesRegistrar类可以看出,SpringBoot自动开启了对SpringDataJPA的支持,即开发人员无须在配置类中显示声明@EnableJpaRepositories。84.SpringBoot应用的SpringDataJPA从上述分析可知,在SpringBoot应用中使用SpringDataJPA访问数据库时,除了添加spring-boot-starter-data-jpa依赖外,只需定义DataSource、持久化实体类和数据访问层,并在需要使用数据访问的地方(如Service层)依赖注入数据访问层即可。98.1SpringDataJPA8.1.1SpringBoot的支持8.1.2简单条件查询8.1.3关联查询8.1.4@Query和@Modifying注解8.1.5排序与分页查询108.1.2简单条件查询只需定义一个继承JpaRepository接口的接口即可使用SpringDataJPA建立数据访问层。因此,自定义的数据访问接口完全继承了JpaRepository的接口方法。但更重要的是,在自定义的数据访问接口中可以根据查询关键字定义查询方法,这些查询方法需要符合它的命名规则,一般是根据持久化实体类的属性名来确定的。111.查询关键字12关键字示例JPQL代码段AndfindByLastnameAndFirstname…wherex.lastname=?1andx.firstname=?2OrfindByLastnameOrFirstname…wherex.lastname=?1orx.firstname=?2Is,EqualsfindByFirstname,findByFirstnameIs,findByFirstnameEquals…wherex.firstname=?1BetweenfindByStartDateBetween…wherex.startDatebetween?1and?2LessThanfindByAgeLessThan…wherex.age<?1LessThanEqualfindByAgeLessThanEqual…wherex.age<=?1GreaterThanfindByAgeGreaterThan…wherex.age>?1GreaterThanEqualfindByAgeGreaterThanEqual…wherex.age>=?1AfterfindByStartDateAfter…wherex.startDate>?1BeforefindByStartDateBefore…wherex.startDate<?1IsNullfindByAgeIsNull…wherex.ageisnullIsNotNull,NotNullfindByAge(Is)NotNull…wherex.agenotnullLikefindByFirstnameLike…wherex.firstnamelike?1NotLikefindByFirstnameNotLike…wherex.firstnamenotlike?1StartingWithfindByFirstnameStartingWith…wherex.firstnamelike?1参数后加%,即以参数开头的模糊查询EndingWithfindByFirstnameEndingWith…wherex.firstnamelike?1参数前加%,即以参数结尾的模糊查询ContainingfindByFirstnameContaining…wherex.firstnamelike?1参数两边加%,即包含参数的模糊查询OrderByfindByAgeOrderByLastnameDesc…wherex.age=?1orderbyx.lastnamedescNotfindByLastnameNot…wherex.lastname<>?1InfindByAgeIn(Collection<Age>ages)…wherex.agein?1NotInfindByAgeNotIn(Collection<Age>ages)…wherex.agenotin?1TruefindByActiveTrue()…wherex.active=trueFalsefindByActiveFalse()…wherex.active=falseIgnoreCasefindByFirstnameIgnoreCase…whereUPPER(x.firstame)=UPPER(?1)2.限制查询结果数量在SpringDataJPA中,使用Top和First关键字限制查询结果数量。13publicinterfaceUserRepositoryextendsJpaRepository<MyUser,Integer>{ /** *获得符合查询条件的前10条 */ publicList<MyUser>findTop10ByUnameLike(Stringuname); /** *获得符合查询条件的前15条 */ publicList<MyUser>findFirst15ByUnameLike(Stringuname);}3.简单条件查询示例【例8-1】使用SpringDataJPA进行简单条件查询。1)创建数据库本书采用的关系型数据库是MySQL5.x,我们为了演示本例,首先通过命令“CREATEDATABASEspringbootjpa;”创建名为springbootjpa的数据库。2)创建基于Thymeleaf和SpringDataJPA依赖的SpringBootWeb应用ch8_1143)修改pom.xml文件,添加MySQL依赖15<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.45</version></dependency>4)设置Web应用ch8_1的上下文路径及数据源配置信息16server.servlet.context-path=/ch8_1spring.datasource.url=jdbc:mysql://localhost:3306/springbootjpa?characterEncoding=utf8#数据库MySQL为8.x时,url为#jdbc:mysql://localhost:3306/springbootjpa?useSSL=false&serverTimezone=Asia/Beijing&characterEncodi#ng=utf-8#数据库用户名spring.datasource.username=root#数据库密码spring.datasource.password=root#数据库驱动spring.datasource.driver-class-name=com.mysql.jdbc.Driver#数据库MySQL为8.x时,驱动类为com.mysql.cj.jdbc.Driverspring.jpa.database=MYSQL#指定是否在日志中显示SQL语句spring.jpa.show-sql=true#不存在就创建对应的表spring.jpa.hibernate.ddl-auto=update#让控制器输出的JSON字符串格式更美观spring.jackson.serialization.indent-output=true5)创建持久化实体类MyUser17@Entity@Table(name="user_table")publicclassMyUserimplementsSerializable{ privatestaticfinallongserialVersionUID=1L;

@Id @GeneratedValue(strategy=GenerationType.IDENTITY) privateintid;//主键 /**使用@Column注解,可以配置列相关属性(列名,长度等), *可以省略,默认为属性名小写,如果属性名是词组,将在中间加上“_”。 */ privateStringuname; privateStringusex; privateintage; //省略get和set方法}在持久化类中,@Entity注解表明该实体类是一个与数据库表映射的实体类。@Table表示实体类与哪个数据库表映射,如果没有通过name属性指定表名,默认为小写的类名。如果类名为词组,将在中间加上“_”(如MyUser类对应的表名为my_user)。@Id注解的属性表示该属性映射为数据库表的主键。@GeneratedValue注解默认使用主键生成方式为自增,如果是MySQL、SQLServer等关系型数据库可映射成一个递增的主键,如果是Oracle等关系型数据库hibernate将自动生成一个名为HIBERNATE_SEQUENCE的序列。update表示如果数据库中存在持久化类对应的表就不创建,不存在就创建对应的表spring.jpa.hibernate.ddl-auto=update6)创建数据访问层18/***这里不需要使用@Repository注解数据访问层,*因为SpringBoot自动配置了JpaRepository*/publicinterfaceUserRepositoryextendsJpaRepository<MyUser,Integer>{ publicMyUserfindByUname(Stringuname); publicList<MyUser>findByUnameLike(Stringuname);}由于UserRepository接口继承了JpaRepository接口,因此UserRepository接口中除了上述自定义的两个接口方法外(方法名命名规范参照表8.1),还拥有JpaRepository的接口方法。7)创建业务层创建名为com.ch.ch8_1.service的包,并在该包中创建UserService接口和接口的实现类UserServiceImpl。198)创建控制器类UserTestController创建名为com.ch.ch8_1.controller的包,并在该包中创建名为UserTestController的控制器类。209)整理脚本样式静态文件JS脚本、CSS样式、图片等静态文件默认放置在src/main/resources/static目录下,ch8_1应用引入的BootStrap和jQuery与【例7-5】中的一样,不再赘述。2110)创建View视图页面在src/main/resources/templates目录下,创建视图页面showAll.html和showAuser.html。2211)运行首先,运行Ch81Application主类。然后,访问“http://localhost:8080/ch8_1/save/”保存用户数据。“http://localhost:8080/ch6_1/save/”成功运行后,在MySQL的springbootjpa数据库中创建一张名为user_table的数据库表,并插入三条记录。通过访问“http://localhost:8080/ch8_1/findAll”查询所有用户。23通过访问“http://localhost:8080/ch8_1/findByUnameLike?uname=陈”模糊查询所有陈姓用户。24通过访问“http://localhost:8080/ch8_1/findByUname?uname=陈恒2”查询一个名为陈恒2的用户信息。25通过访问“http://localhost:8080/ch8_1/getOne?id=1”查询一个id为1的用户信息268.1SpringDataJPA8.1.1SpringBoot的支持8.1.2简单条件查询8.1.3关联查询8.1.4@Query和@Modifying注解8.1.5排序与分页查询278.1.3关联查询在SpringDataJPA中有一对一、一对多、多对多等关系映射。1.@OneToOne一对一关系,在现实生活中是十分常见的。比如一个大学生只有一张一卡通,一张一卡通只属于一个大学生。再比如人与身份证的关系也是一对一的关系。在SpringDataJPA中,可用两种方式描述一对一关系映射。一种是通过外键的方式(一个实体通过外键关联到另一个实体的主键);一种是通过一张关联表来保存两个实体一对一的关系。【例8-2】使用SpringDataJPA实现人与身份证的一对一关系映射。281.@OneToOne首先,为【例8-2】创建基于SpringDataJPA依赖的SpringBootWeb应用ch8_2。ch8_2应用的数据库、pom.xml以及perties与ch8_1应用基本一样,不再赘述。291)创建持久化实体类30在实体类中,@OneToOne注解有五个属性:targetEntity、cascade、fetch、optional和mappedBy。targetEntity属性:class类型属性。定义关系类的类型,默认是该成员属性对应的类类型,所以通常不需要提供定义。cascade属性:CascadeType[]类型。该属性定义类和类之间的级联关系。定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操作,而且这种关系是递归调用的。cascade的值只能从CascadeType.PERSIST(级联新建)、CascadeType.REMOVE(级联删除)、CascadeType.REFRESH(级联刷新)、CascadeType.MERGE(级联更新)中选择一个或多个。还有一个选择是使用CascadeType.ALL,表示选择全部四项。FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载。FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。optional=true,表示idCard属性可以为null,也就是允许没有身份证,如未成年人没有身份证。mappedBy标签一定是定义在关系的被维护端,它指向关系的维护端;只有@OneToOne,@OneToMany,@ManyToMany上才有mappedBy属性,ManyToOne不存在该属性。拥有mappedBy注解的实体类为关系的被维护端。2)创建数据访问层31publicinterfaceIdCardRepositoryextendsJpaRepository<IdCard,Integer>{ /** *根据人员ID查询身份信息(关联查询,根据person属性的id) *相当于JPQL语句:selecticfromIdCardicwhereic.person.id=?1 */ publicIdCardfindByPerson_id(Integerid); /** *根据地址和身份证号查询身份信息 *相当于JPQL语句:selecticfromIdCardicwhereic.address=?1andic.code=?2 */ publicList<IdCard>findByAddressAndCode(Stringaddress,Stringcode);}按照SpringDataJPA的规则,查询两个有关联关系的对象,可以通过方法名中的“_”下划线来标识。如根据人员ID查询身份信息findByPerson_id。JPQL(JavaPersistenceQueryLanguage)是一种和SQL非常类似的中间性和对象化查询语言,它最终被编译成针对不同底层数据库的SQL查询,从而屏蔽不同数据库的差异。JPQL语句可以是select语句、update语句或delete语句,它们都通过Query接口封装执行。2)创建数据访问层32publicinterfacePersonRepositoryextendsJpaRepository<Person,Integer>{ /** *根据身份证ID查询人员信息(关联查询,根据idCard属性的id) *相当于JPQL语句:selectpfromPersonpwherep.idCard.id=?1 */ publicPersonfindByIdCard_id(Integerid); /** *根据人名和性别查询人员信息 *相当于JPQL语句:selectpfromPersonpwherep.pname=?1andp.psex=?2 */ publicList<Person>findByPnameAndPsex(Stringpname,Stringpsex);}3)创建业务层创建名为com.ch.ch8_2.service的包,并在该包中创建名为PersonAndIdCardService的接口和接口实现类PersonAndIdCardServiceImpl。334)创建控制器类创建名为com.ch.ch8_2.controller的包,并在该包中创建名为TestOneToOneController的控制器类。345)运行首先,运行Ch82Application主类。然后,访问“http://localhost:8080/ch8_2/save/”。“http://localhost:8080/ch8_2/save/”成功运行后,在MySQL的springbootjpa数据库中创建名为idcard_table和person_table的数据库表(实体类成功加载后就已创建好数据表),并分别插入三条记录。通过“http://localhost:8080/ch8_2/findByIdCard_id?id=1”查询身份证id为1的人员信息(关联查询)。355)运行通过“http://localhost:8080/ch8_2/findByPerson_id?id=1”查询人员id为1的身份证信息(关联查询)。362.@OneToMany和@ManyToOne在SpringDataJPA中,使用@OneToMany和@ManyToOne来表示一对多的双向关联。例如,一端(Author)使用@OneToMany,多端(Article)使用@ManyToOne。在JPA规范中,一对多的双向关系由多端(如Article)来维护。就是说多端为关系的维护端,负责关系的增删改查。一端则为关系的被维护端,不能维护关系。一端(Author)使用@OneToMany注解的mappedBy="author"属性表明一端(Author)是关系的被维护端。多端(Article)使用@ManyToOne和@JoinColumn来注解属性author,@ManyToOne表明Article是多端,@JoinColumn设置在article表的关联字段(外键)上。【例8-3】使用SpringDataJPA实现Author与Article的一对多关系映射。371)添加hibernate-validator依赖因为在持久化实体类中,使用hibernate-validator约束数据表,所以需要在ch8_2应用的pom.xml文件中添加hibernate-validator依赖。38<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId></dependency>2)创建持久化实体类在com.ch.ch8_2.entity包中,创建名为Author和Article的持久化实体类。393)创建数据访问层40publicinterfaceAuthorRepositoryextendsJpaRepository<Author,Integer>{ /** *根据文章标题包含的内容,查询作者(关联查询) *相当于JPQL语句:selectafromAuthorainnerjoina.articleListtwheret.titlelike%?1% */ publicAuthorfindByArticleList_titleContaining(Stringtitle);}publicinterfaceArticleRepositoryextendsJpaRepository<Article,Integer>{ /** *根据作者id查询文章信息(关联查询,根据author属性的id) *相当于JPQL语句:selectafromArticleawherea.author.id=?1 */ publicList<Article>findByAuthor_id(Integerid); /** *根据作者名查询文章信息(关联查询,根据author属性的aname) *相当于JPQL语句:selectafromArticleawherea.author.aname=?1 */ publicList<Article>findByAuthor_aname(Stringaname);}4)创建业务层在com.ch.ch8_2.service包中,创建名为AuthorAndArticleService的接口和接口实现类AuthorAndArticleServiceImpl。415)创建控制器类在com.ch.ch8_2.controller包中,创建名为TestOneToManyController的控制器类。426)运行首先,运行Ch82Application主类。然后,访问“http://localhost:8080/ch8_2/saveOneToMany/”。在MySQL的springbootjpa数据库中创建名为author_table和article_table的数据库表,并在author_table表中插入两条记录,同时在article_table表中插入四条记录。通过“http://localhost:8080/ch8_2/findArticleByAuthor_id?id=2”查询作者id为2的文章列表(关联查询)。436)运行通过“http://localhost:8080/ch8_2/findArticleByAuthor_aname?aname=陈恒1”查询作者名为陈恒1的文章列表(关联查询)。446)运行通过“http://localhost:8080/ch8_2/findByArticleList_titleContaining?title=对多1”查询文章标题包含“对多1”的作者(关联查询)。453.@ManyToMany在SpringDataJPA中使用@ManyToMany来注解多对多的映射关系,由一个关联表来维护。关联表的表名默认是:主表名+下划线+从表名(主表是指关系维护端对应的表,从表是指关系被维护端对应的表)。关联表只有两个外键字段,分别指向主表ID和从表ID。字段的名称默认为:主表名+下划线+主表中的主键列名,从表名+下划线+从表中的主键列名。需要注意的是,多对多关系中一般不设置级联保存、级联删除、级联更新等操作。【例8-4】使用SpringDataJPA实现用户(User)与权限(Authority)的多对多关系映射。461)创建持久化实体类在com.ch.ch8_2.entity包中,创建名为User和Authority的持久化实体类。472)创建数据访问层48publicinterfaceUserRepositoryextendsJpaRepository<User,Integer>{ /** *根据权限id查询拥有该权限的用户(关联查询) *相当于JPQL语句:selectufromUseruinnerjoinu.authorityListawherea.id=?1 */ publicList<User>findByAuthorityList_id(intid); /** *根据权限名查询拥有该权限的用户(关联查询) *相当于JPQL语句:selectufromUseruinnerjoinu.authorityListawhere=?1 */ publicList<User>findByAuthorityList_name(Stringname);}publicinterfaceAuthorityRepositoryextendsJpaRepository<Authority,Integer>{ /** *根据用户id查询用户所拥有的权限(关联查询) *相当于JPQL语句:selectafromAuthorityainnerjoina.userListuwhereu.id=?1 */ publicList<Authority>findByUserList_id(intid); /** *根据用户名查询用户所拥有的权限(关联查询) *相当于JPQL语句:selectafromAuthorityainnerjoina.userListuwhereu.username=?1 */ publicList<Authority>findByUserList_Username(Stringusername);}3)创建业务层在com.ch.ch8_2.service包中,创建名为UserAndAuthorityService的接口和接口实现类UserAndAuthorityServiceImpl。494)创建控制器类在com.ch.ch8_2.controller包中,创建名为TestManyToManyController的控制器类。505)运行首先,运行Ch82Application主类。然后,访问“http://localhost:8080/ch8_2/saveManyToMany/”。然后可以通过“http://localhost:8080/ch8_2/findByAuthorityList_id?id=1”查询拥有id为1的权限的用户列表(关联查询);通过“http://localhost:8080/ch8_2/findByAuthorityList_name?name=修改”查询拥有“修改”权限的用户列表(关联查询);通过“http://localhost:8080/ch8_2/findByUserList_id?id=2”查询id为2的用户的权限列表(关联查询);通过“http://localhost:8080/ch8_2/findByUserList_Username?username=陈恒2”查询用户名为“陈恒2”的用户的权限列表(关联查询)。51?请思考如何才能摆脱查询关键字和关联查询命名规范约束呢?8.1SpringDataJPA8.1.1SpringBoot的支持8.1.2简单条件查询8.1.3关联查询8.1.4@Query和@Modifying注解8.1.5排序与分页查询528.1.4@Query和@Modifying注解53publicinterfaceAuthorityRepositoryextendsJpaRepository<Authority,Integer>{ /** *根据用户名查询用户所拥有的权限(关联查询) */

@Query("selectafromAuthorityainnerjoina.userListuwhereu.username=?1") publicList<Authority>findByUserListUsername(Stringusername);}使用@Query注解可以将JPQL语句直接定义在数据访问接口方法上,并且接口方法名不受查询关键字和关联查询命名规范约束。1.@Query注解54/***根据作者id查询文章信息(标题和内容)*/@Query("selectnewMap(a.titleastitle,a.contentascontent)fromArticleawherea.author.id=?1")publicList<Map<String,Object>>findTitleAndContentByAuthorId(Integerid);使用@Query注解定义JPQL语句,可以直接返回List<Map<String,Object>>对象。/***根据作者名和作者id查询文章信息*/@Query("selectafromArticleawherea.author.aname=:aname1anda.author.id=:id1")publicList<Article>findArticleByAuthorAnameAndId(@Param("aname1")Stringaname,@Param("id1")Integerid);使用@Query注解定义JPQL语句,之前的方法是使用参数位置(“?1”指代的是获取方法形参列表中第1个参数值,1代表的是参数位置,以此类推)来获取参数值。除此之外,SpringDataJPA还支持使用名称来获取参数值,使用格式为“:参数名称”。2.@Modifying注解55/***根据作者id删除作者*/@Transactional@Modifying@Query("deletefromAuthorawherea.id=?1")publicintdeleteAuthorByAuthorId(intid);可以使用@Modifying和@Query注解组合定义在数据访问接口方法上,进行更新查询操作

【例8-5】@Query和@Modifying注解的使用方法。

首先,为【例8-5】创建基于SpringDataJPA依赖的SpringBootWeb应用ch8_3。ch6_3应用的数据库、pom.xml以及perties与ch8_2应用基本一样,不再赘述。1)创建持久化实体类创建名为com.ch.ch8_3.entity的包,并在该包中创建名为Article和Author的持久化实体类。具体代码分别与ch8_2应用的Article和Author的代码一样,不再赘述。562)创建数据访问层57publicinterfaceArticleRepositoryextendsJpaRepository<Article,Integer>{ /** *根据作者id查询文章信息(标题和内容) */

@Query("selectnewMap(a.titleastitle,a.contentascontent)fromArticleawherea.author.id=?1") publicList<Map<String,Object>>findTitleAndContentByAuthorId(Integerid); /** *根据作者名和作者id查询文章信息 */

@Query("selectafromArticleawherea.author.aname=:aname1anda.author.id=:id1") publicList<Article>findArticleByAuthorAnameAndId(@Param("aname1")Stringaname,@Param("id1")Integerid); /** *根据作者id删除作者对应的文章 */ @Transactional

@Modifying @Query("deletefromArticleawherea.author.id=:id1") publicintdeleteArticleByAuthorId(@Param("id1")Integerid);}2)创建数据访问层58publicinterfaceAuthorRepositoryextendsJpaRepository<Author,Integer>{ /** *根据文章标题包含的内容,查询作者(关联查询) */

@Query("selectafromAuthorainnerjoina.articleListtwheret.titlelike%?1%") publicAuthorfindAuthorByArticleListtitleContaining(Stringtitle);}3)创建业务层创建名为com.ch.ch8_3.service的包,并在该包中创建名为AuthorAndArticleService的接口和接口实现类AuthorAndArticleServiceImpl。594)创建控制器类创建com.ch.ch8_3.controller的包,并在该包中创建名为TestOneToManyController的控制器类。605)运行首先,运行Ch83Application主类。然后,通过“http://localhost:8080/ch8_3/findTitleAndContentByAuthorId?id=1”查询作者id为1的文章标题和内容;通过“http://localhost:8080/ch8_3/findArticleByAuthorAnameAndId?aname=陈恒2&&id=2”查询作者名为“陈恒2”且作者id为2的文件列表;通过“http://localhost:8080/ch8_3/findAuthorByArticleListtitleContaining?title=对多1”查询文章标题包含“对多1”的作者;通过“http://localhost:8080/ch8_3/deleteArticleByAuthorId?id=1”删除id为1的作者的文章。618.1SpringDataJPA8.1.1SpringBoot的支持8.1.2简单条件查询8.1.3关联查询8.1.4@Query和@Modifying注解8.1.5排序与分页查询628.1.5排序与分页查询63publicinterfaceAuthorRepositoryextendsJpaRepository<Author,Integer>{ List<Author>findByAnameContaining(Stringaname,Sortsort);}publicList<Author>findByAnameContaining(Stringaname,StringsortColum){ //按sortColum降序排序 returnauthorRepository.findByAnameContaining(aname,Sort.by(Direction.DESC,sortColum));}Page<Author>pageData=authorRepository.findAll(PageRequest.of(1,size,Sort.by(Direction.DESC,"id")));//获得当前页面的记录List<Author>allAuthor=pageData.getContent();model.addAttribute("allAuthor",allAuthor);//获得总记录数model.addAttribute("totalCount",pageData.getTotalElements());//获得总页数model.addAttribute("totalPage",pageData.getTotalPages());8.1.5排序与分页查询【例8-6】排序与分页查询的使用方法。首先,为【例8-6】创建基于Thymeleaf和SpringDataJPA依赖的SpringBootWeb应用ch8_4。ch8_4应用的数据库、pom.xml、perties以及静态资源等内容与ch8_1应用基本一样,不再赘述。641.创建持久化实体类创建名为com.ch.ch8_4.entity的包,并在该包中创建名为Article和Author的持久化实体类。具体代码分别与ch8_2应用的Article和Author的代码一样,不再赘述。652.创建数据访问层66publicinterfaceAuthorRepositoryextendsJpaRepository<Author,Integer>{ /** *查询作者名含有name的作者列表,并排序 */ List<Author>findByAnameContaining(Stringaname,Sortsort);}3.创建业务层67@ServicepublicclassArticleAndAuthorServiceImplimplementsArticleAndAuthorService{ @Autowired privateAuthorRepositoryauthorRepository; @Override publicList<Author>findByAnameContaining(Stringaname,StringsortColum){ //按sortColum降序排序 returnauthorRepository.findByAnameContaining(aname,Sort.by(Direction.DESC,sortColum)); } @Override publicStringfindAllAuthorByPage(Integerpage,Modelmodel){ if(page==null){//第一次访问findAllAuthorByPage方法时 page=1; } intsize=2;//每页显示2条//分页查询,of方法的第一个参数代表第几页(比实际小1),第二个参数代表页面大小,第三个参数代表排序规则 Page<Author>pageData=

authorRepository.findAll(PageRequest.of(1,size,Sort.by(Direction.DESC,"id"))); //获得当前页面数据并转换成List<Author>,转发到视图页面显示 List<Author>allAuthor=pageData.getContent(); model.addAttribute("allAuthor",allAuthor); //共多少条记录 model.addAttribute("totalCount",pageData.getTotalElements()); //共多少页 model.addAttribute("totalPage",pageData.getTotalPages()); //当前页 model.addAttribute("page",page); return"index"; }}4.创建控制器类68@ControllerpublicclassTestSortAndPage{ @Autowired privateArticleAndAuthorServicearticleAndAuthorService; @RequestMapping("/findByAnameContaining") @ResponseBody publicList<Author>findByAnameContaining(Stringaname,StringsortColum){ returnarticleAndAuthorService.findByAnameContaining(aname,sortColum); } @RequestMapping("/findAllAuthorByPage") /** *@parampage第几页 */ publicStringfindAllAuthorByPage(Integerpage,Modelmodel){ returnarticleAndAuthorService.findAllAuthorByPage(page,model); }}5.创建View视图页面在src/main/resources/templates目录下,创建视图页面index.html。696.运行首先,运行Ch84Application主类。然后,通过“http://localhost:8080/ch8_4/findByAnameContaining?aname=陈&sortColum=id”查询作者名含有“陈”的作者列表,并按照id降序。706.运行通过“http://localhost:8080/ch8_4/findAllAuthorByPage”分页查询作者,并按照id降序。71本章内容728.1SpringDataJPA8.2SpringBoot整合MyBatis8.3REST8.4MongoDB8.5Redis8.6数据缓存Cache8.2SpringBoot整合MyBatis我们在第三章已学习SSM框架整合开发的流程,那么SpringBoot如何整合MyBatis呢?【例8-7】在SpringBoot应用中使用MyBatis框架操作数据库(基于XML的映射配置)。731.创建SpringBootWeb应用在创建SpringBootWeb应用ch8_5时,选择MyBatisFramework依赖。742.修改pom.xml文件在pom.xml文件中添加MySQL连接器依赖。75<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.45</version></dependency>3.设置Web应用ch8_5的上下文路径及数据源配置信息76server.servlet.context-path=/ch8_5#数据库地址spring.datasource.url=jdbc:mysql://localhost:3306/springbootjpa?characterEncoding=utf8#数据库用户名spring.datasource.username=root#数据库密码spring.datasource.password=root#数据库驱动spring.datasource.driver-class-name=com.mysql.jdbc.Driver#设置包别名(在Mapper映射文件中直接使用实体类名)mybatis.type-aliases-package=com.ch.ch8_5.entity#告诉系统在哪里去找mapper.xml文件(映射文件)mybatis.mapperLocations=classpath:mappers/*.xml#在控制台输出SQL语句日志.ch.ch8_5.repository=debug#让控制器输出的JSON字符串格式更美观spring.jackson.serialization.indent-output=true4.创建实体类77packagecom.ch.ch8_5.entity;publicclassMyUser{ privateIntegerid; privateStringusername; privateStringpassword; //省略get和set方法}5.创建数据访问接口78@RepositorypublicinterfaceMyUserRepository{ publicList<MyUser>findAll();}@Repository可有可无,但有时提示依赖注入找不到(不影响运行),加上后可以消去依赖注入的报错信息。这里不再需要@Mapper,是因为在启动类中使用@MapperScan注解,将数据访问层的接口都注解为Mapper接口的实现类,@Mapper与@MapperScan两者用其一即可6.创建Mapper映射文件

79<mappernamespace="com.ch.ch8_5.repository.MyUserRepository"> <selectid="findAll"resultType="MyUser"> select*fromuser </select></mapper>在src/main/resources目录下,创建名为mappers的包,并在该包中创建SQL映射文件MyUserMapper.xml7.创建业务层创建名为com.ch.ch8_5.service的包,并在该包中创建MyUserService接口和MyUserServiceImpl实现类。80@ServicepublicclassMyUserServiceImplimplementsMyUserService{ @Autowired privateMyUserRepositorymyUserRepository; @Override publicList<MyUser>findAll(){ returnmyUserRepository.findAll(); }}8.创建控制器类MyUserController创建名为com.ch.ch8_5.controller的包,并在该包中创建控制器类MyUserController。81@RestControllerpublicclassMyUserController{ @Autowired privateMyUserServicemyUserService; @RequestMapping("/findAll") publicList<MyUser>findAll(){ returnmyUserService.findAll(); }}9.在应用程序的主类中扫描Mapper接口在应用程序的Ch85Application主类中,使用@MapperScan注解扫描MyBatis的Mapper接口。82@SpringBootApplication//配置扫描MyBatis接口的包路径@MapperScan(basePackages={"com.ch.ch8_5.repository"})publicclassCh85Application{ publicstaticvoidmain(String[]args){ SpringApplication.run(Ch66Application.class,args); }}10.运行首先,运行Ch85Application主类。然后,访问“http://localhost:8080/ch8_5/findAll”。83本章内容848.1SpringDataJPA8.2SpringBoot整合MyBatis8.3REST8.4MongoDB8.5Redis8.6数据缓存Cache8.3REST8.3.1REST简介8.3.2SpringBoot整合REST8.3.3SpringDataREST8.3.4REST服务测试858.3.1REST简介REST是一组架构约束条件和原则。这些约束有:1.使用客户/服务器模型。客户和服务器之间通过一个统一的接口来互相通讯。2.层次化的系统。在一个REST系统中,客户端并不会固定地与一个服务器打交道。3.无状态。在一个REST系统中,服务端并不会保存有关客户的任何状态。也就是说,客户端自身负责用户状态的维持,并在每次发送请求时都需要提供足够的信息。4.可缓存。REST系统需要能够恰当地缓存请求,以尽量减少服务端和客户端之间的信息传输,以提高性能。5.统一的接口。一个REST系统需要使用一个统一的接口来完成子系统之间以及服务与用户之间的交互。这使得REST系统中的各个子系统可以独自完成演化。86满足这些约束条件和原则的应用程序或设计就是RESTful。需要注意的是,REST是设计风格而不是标准。REST通常基于HTTP、URI、XML以及HTML这些现有的广泛流行的协议和标准。资源(Resources)“表现层状态转化”中的“表现层”其实指的是“资源”的“表现层”。“资源”就是网络上的一个实体,或者说是网络上的一个具体信息。“资源”可以是一段文本、一张图片、一段视频,总之就是一个具体的实体。我们可以使用一个URI(统一资源定位符)指向资源,每种资源对应一个特定的URI。我们需要获取资源时,访问它的URI即可,因此URI是每个资源的地址或独一无二的标识符。REST风格的Web服务,是通过一个简洁清晰的URI来提供资源链接,客户端通过对URI发送HTTP请求获得这些资源,而获取和处理资源的过程让客户端应用的状态发生改变。87表现层(Representation)“资源”是一种信息实体,可以有多种外在的表现形式。我们将“资源”呈现出来的形式称为它的“表现层”。例如,文本可以使用txt格式表现,也可以使用XML格式、JSON格式表现。88状态转化(StateTransfer)客户端访问一个网站,就代表了它和服务器的一个互动过程。在这个互动过程中,将涉及数据和状态的变化。我们知道HTTP协议是一个无状态的通信协议,这意味着所有状态都保存在服务器端。因此,如果客户端操作服务器,需要通过某种手段(如HTTP协议)让服务器端发生“状态变化”。而这种转化是建立在表现层之上的,所以就是“表现层状态转化”。89架构风格在流行的各种Web框架中,包括SpringBoot都支持REST开发。REST并不是一种技术或者规范,而是一种架构风格,包括了如何标识资源、如何标识操作接口及操作的版本、如何标识操作的结果等,主要内容如下:901.使用“api”作为上下文在REST架构中,建议使用“api”作为上下文,示例如下;http://localhost:8080/api2.增加一个版本标识在REST架构中,可以通过URL标识版本信息,示例如下:http://localhost:8080/api/v1.03.标识资源在REST架构中,可以将资源名称放到URL中,示例如下:http://localhost:8080/api/v1.0/user4.确定HTTPMethodHTTP协议有5个常用的表示操作方式的动词:GET、POST、PUT、DELETE、PATCH。它们分别对应5种基本操作:GET用来获取资源,POST用来增加资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源,PATCH用来更新资源的部分属性。示例如下:911)新增用户POSThttp://localhost:8080/api/v1.0/user2)查询id为123的用户GEThttp://localhost:8080/api/v1.0/user/1233)更新id为123的用户PUThttp://localhost:8080/api/v1.0/user/1234)删除id为123的用户DELETEhttp://localhost:8080/api/v1.0/user/1235.确定HTTPStatus92服务器向用户返回的状态码和提示信息,常用的如下:1)200OK-[GET]:服务器成功返回用户请求的数据。2)201CREATED-[POST/PUT/PATCH]:用户新建或修改数据成功。3)202Accepted-[*]:表示一个请求已经进入后台排队(异步任务)。4)204NOCONTENT-[DELETE]:用户删除数据成功。5)400INVALIDREQUEST-[POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作。6)401Unauthorized-[*]:表示用户没有权限(令牌、用户名、密码错误)。7)403Forbidden-[*]表示用户得到授权(与401错误相对),但是访问是被禁止的。8)404NOTFOUND-[*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作。9)406NotAcceptable-[GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。10)410Gone-[GET]:用户请求的资源被永久删除,且不会再得到的。11)422Unprocesableentity-[POST/PUT/PATCH]:当创建一个对象时,发生一个验证错误。

12)500INTERNALSERVERERROR-[*]:服务器发生错误,用户将无法判断发出的请求是否成功。8.3REST8.3.1REST简介8.3.2SpringBoot整合REST8.3.3SpringDataREST8.3.4REST服务测试938.3.2SpringBoot整合REST在SpringBoot的Web应用中,自动支持REST。也就是说,只要spring-boot-starter-web依赖在pom.xml中,就支持REST。【例8-8】一个RESTful应用示例假如,在ch8_2应用的控制器类TestOneToManyController中有如下处理方法:94@RequestMapping("/findArticleByAuthor_id1/{id}")publicList<Article>findByAuthor_id1(@PathVariable("id")Integerid){ returnauthorAndArticleService.findByAuthor_id(id);}http://localhost:8080/ch8_2/findArticleByAuthor_id

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论