• 吴裕雄天生自然Spring BootSpring Data JPA的事务支持


        我们可以从org.springframework.data.jpa.repository.support.SimpleJpaRepository的源代码中看出,Spring Data JPA对所有的默认接口方法都开启了事务支持,并且对查询类事务默认启用readOnly。
    Spring Boot的事务支持
    
        在Spring Boot中,自动配置了事务管理器,并自动开启了注解事务的支持。
        1.自动配置的事务管理器
        在使用JDBC访问数据库时,Spring Boot定义了DataSourceTransactionManager的Bean(org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration)。
        在使用JPA访问数据库时,Spring Boot定义了PlatformTransactionManager的实现
    JpaTransactionManager的Bean(org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration)。
        从上述源码可以看出,如果添加的是spring-boot-starter-jdbc依赖,框架会默认注入DataSourceTransactionManager实例。如果添加的是spring-boot-starter-data-jpa依赖,框架会默认注入JpaTransactionManager实例。
        2.自动开启注解事务的支持
        Spring Boot使用org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration类配置事务的支持,并在该类中自动开启注解事务的支持。
    REST简介
    
        REST即表现层状态转化(英文:Representational State Transfer,简称REST)是Roy Thomas Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。
        REST是一组架构约束条件和原则。这些约束有:
        1.使用客户/服务器模型。客户和服务器之间通过一个统一的接口来互相通讯。
        2.层次化的系统。在一个REST系统中,客户端并不会固定地与一个服务器打交道。
        3.无状态。在一个REST系统中,服务端并不会保存有关客户的任何状态。也就是说,客户端自身负责用户状态的维持,并在每次发送请求时都需要提供足够的信息。
        4.可缓存。REST系统需要能够恰当地缓存请求,以尽量减少服务端和客户端之间的信息传输,以提高性能。
        5.统一的接口。一个REST系统需要使用一个统一的接口来完成子系统之间以及服务与用户之间的交互。这使得REST系统中的各个子系统可以独自完成演化。
        满足这些约束条件和原则的应用程序或设计就是RESTful。需要注意的是,REST是设计风格而不是标准。REST通常基于HTTP、URI、XML以及HTML这些现有的广泛流行的协议和标准。
        “表现层状态转化”中的“表现层”其实指的是“资源”的“表现层”。
        “资源”就是网络上的一个实体,或者说是网络上的一个具体信息。“资源”可以是一段文本、一张图片、一段视频,总之就是一个具体的实体。我们可以使用一个URI(统一资源定位符)指向资源,每种资源对应一个特定的URI。我们需要获取资源时,访问它的URI即可,因此URI是每个资源的地址或独一无二的标识符。REST风格的Web服务,是通过一个简洁清晰的URI来提供资源链接,客户端通过对URI发送HTTP请求获得这些资源,而获取和处理资源的过程让客户端应用的状态发生改变。
    表现层(Representation)
    
        “资源”是一种信息实体,可以有多种外在的表现形式。我们将“资源”呈现出来的形式称为它的“表现层”。例如,文本可以使用txt格式表现,也可以使用XML格式、JSON格式表现。
    状态转化(State Transfer)
    
        客户端访问一个网站,就代表了它和服务器的一个互动过程。在这个互动过程中,将涉及数据和状态的变化。我们知道HTTP协议是一个无状态的通信协议,这意味着所有状态都保存在服务器端。因此,如果客户端操作服务器,需要通过某种手段(如HTTP协议)让服务器端发生“状态变化”。而这种转化是建立在表现层之上的,所以就是“表现层状态转化”
        在流行的各种Web框架中,包括Spring Boot都支持REST开发。REST并不是一种技术或者规范,而是一种架构风格,包括了如何标识资源、如何标识操作接口及操作的版本、如何标识操作的结果等,主要内容如下:
        1.使用“api”作为上下文
        在REST架构中,建议使用“api”作为上下文,示例如下;
        http://localhost:8080/api
        2.增加一个版本标识
        在REST架构中,可以通过URL标识版本信息,示例如下:
        http://localhost:8080/api/v1.0
        3.标识资源
        在REST架构中,可以将资源名称放到URL中,示例如下:
        http://localhost:8080/api/v1.0/user
        4.确定HTTP Method
        HTTP协议有5个常用的表示操作方式的动词:GET、POST、PUT、DELETE、PATCH。它们分别对应5种基本操作:GET用来获取资源,POST用来增加资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源,PATCH用来更新资源的部分属性。示例如下:
        1)新增用户
        POST http://localhost:8080/api/v1.0/user
        2)查询id为123的用户
        GET http://localhost:8080/api/v1.0/user/123
        3)更新id为123的用户
        PUT http://localhost:8080/api/v1.0/user/123
        4)删除id为123的用户
        DELETE http://localhost:8080/api/v1.0/user/123
    5.确定HTTP Status 
    服务器向用户返回的状态码和提示信息,常用的如下:
    1)200 OK - [GET]:服务器成功返回用户请求的数据。
    2)201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
    3)202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)。
    4)204 NO CONTENT - [DELETE]:用户删除数据成功。
    5)400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作。
    6)401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
    7)403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
    8)404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作。
    9)406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
    10)410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
    11)422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
    12)500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
    Spring Boot整合REST
    
    在Spring Boot的Web应用中,自动支持REST。也就是说,只要spring-boot-starter-web依赖在pom中,就支持REST。
    
    假如,在应用的控制器类中有如下处理方法:
        @RequestMapping("/findArticleByAuthor_id/{id}")
        public List<Article> findByAuthor_id(@PathVariable("id") Integer id) {
            return authorAndArticleService.findByAuthor_id(id);
        }
         那么,我们可以使用如下所示的REST风格的URL访问上述处理方法:
        http://localhost:8080/ch6_2/findArticleByAuthor_id/2
    使用了URL模板模式映射@RequestMapping("/findArticleByAuthor_id/{id}"),其中{XXX}为占位符,请求的URL可以是“/findArticleByAuthor_id/1”或“/findArticleByAuthor_id/2”。通过在处理方法中使用@PathVariable获取{XXX}中的XXX变量值。@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。如果{XXX}中的变量名XXX和形参名称一致,则@PathVariable不用指定名称。
    Spring Data REST
    
    目前,Spring Data REST支持将Spring Data JPA、Spring Data MongoDB、Spring Data Neo4j、Spring Data GemFire以及Spring Data Cassandra的repository自动转换成REST服务。
    
    通过SpringBootRepositoryRestConfigurer类的源码我们可以得出,Spring Boot已经自动配置了RepositoryRestConfiguration,所以在Spring Boot应用中使用Spring Data REST只需引入spring-boot-starter-data-rest的依赖即可使用。
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.rest</groupId>
      <artifactId>SpringBootRest</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      
      <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.0.RELEASE</version>
            <relativePath /> <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <!-- 声明项目配置依赖编码格式为 utf-8 -->
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <fastjson.version>1.2.24</fastjson.version>
        </properties>
    
        <dependencies>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- 添加MySQL依赖 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
                <version>8.0.13</version><!--$NO-MVN-MAN-VER$ -->
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <!-- 添加jdbc依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
    
            <!--devtools热部署 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <optional>true</optional>
                <scope>true</scope>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-rest</artifactId>
            </dependency>
    
        </dependencies>
      
      <build>
        <plugins>
          <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    server.port=8089
    
    server.servlet.context-path=/api
    
    spring.datasource.url=jdbc:mysql://localhost:3306/springbootjpa?serverTimezone=UTC&autoReconnect=true
    spring.datasource.username=root
    spring.datasource.password=admin
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.jpa.database=MYSQL
    spring.jpa.show-sql=true
    spring.jpa.hibernate.ddl-auto=update
    spring.jackson.serialization.indent-output=true 
    package com.ch.ch6_7.entity;
    
    import java.io.Serializable;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    @Entity
    @Table(name = "student_table")
    public class Student implements Serializable {
        private static final long serialVersionUID = 1L;
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;// 主键
        private String sno;
        private String sname;
        private String ssex;
    
        public Student() {
            super();
        }
    
        public Student(int id, String sno, String sname, String ssex) {
            super();
            this.id = id;
            this.sno = sno;
            this.sname = sname;
            this.ssex = ssex;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getSno() {
            return sno;
        }
    
        public void setSno(String sno) {
            this.sno = sno;
        }
    
        public String getSname() {
            return sname;
        }
    
        public void setSname(String sname) {
            this.sname = sname;
        }
    
        public String getSsex() {
            return ssex;
        }
    
        public void setSsex(String ssex) {
            this.ssex = ssex;
        }
    }
    package com.ch.ch6_7.repository;
    
    import java.util.List;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.repository.query.Param;
    import org.springframework.data.rest.core.annotation.RestResource;
    
    import com.ch.ch6_7.entity.Student;
    
    public interface StudentRepository extends JpaRepository<Student, Integer> {
        /**
         * 自定义接口查询方法,暴露为REST资源
         */
        @RestResource(path = "snameStartsWith", rel = "snameStartsWith")
        List<Student> findBySnameStartsWith(@Param("sname") String sname);
    }
    1.获得列表数据
    
        在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与实体名对应。一般来说,数据库中的表都是同种记录的“集合”(collection),所以API中的名词也应该使用复数,如students。
    
        在Wisdom REST Client中,使用GET方式访问“http://localhost:8089/api/students”请求路径获得所有学生信息。

    2.获得单一对象
    
        在Wisdom REST Client中,使用GET方式访问“http://localhost:8080/api/students/1”请求路径获得id为1的学生信息。

    3.查询
    
        在Wisdom REST Client中,search调用自定义的接口查询方法。因此,可以使用GET访问“http://localhost:8080/api/students/search/snameStartsWith?sname=陈”请求路径调用List<Student> findBySnameStartsWith(@Param("sname") String sname)接口方法,获得姓名前缀为“陈”的学生信息。

    4.分页查询
    
       在Wisdom REST Client中,使用GET方式访问“http://localhost:8080/api/students/?page=0&size=2”请求路径获得第一页的学生信息(page=0即第一页,size=2即每页数量为2)。

    5.排序
    
        在Wisdom REST Client中,使用GET方式访问“http://localhost:8080/api/students/?sort=sno,desc”请求路径获得按照sno属性倒序的列表。

    6.保存
    
        在Wisdom REST Client中,发起POST方式请求实现新增功能,将要保存的数据放置在请求体中,数据类型为JSON。

    7.更新
    
        假如,我们需要更新新增的id为5的数据,可以在Wisdom REST Client中,使用PUT方式访问“http://localhost:8080/api/students/5”,修改提交的数据。

     

    8.删除
    
        假如,我们需要删除新增的id为5的数据,可以在Wisdom REST Client中,使用DELETE方式访问“http://localhost:8080/api/students/5”,删除数据。

  • 相关阅读:
    ERP系统模块完全解析──主生产计划MPS
    样式兼容问题
    Js中 关于top、clientTop、scrollTop、offsetTop
    C# 中的委托和事件
    面试题大全
    常用Web服务
    CSS兼容IE6,IE7,FF的技巧
    C#图片处理基本应用(裁剪,缩放,清晰度,水印)
    数据库导入excel数据出现问题解决方案
    JS调用webservice的通用函数
  • 原文地址:https://www.cnblogs.com/tszr/p/15340482.html
Copyright © 2020-2023  润新知