【官方教程翻译】SpringBoot 通过 Spring Data JPA 使用 MySQL

原文:spring.io/guides/gs/a…

在项目初始化的部分有删减

本文带你了解如何创建一个连接到 MySQL 数据库的 Spring 应用。本文会使用 Spring Data JPA 来连接数据库。用户也可以根据需要选择其他的库(比如直接用 Spring JDBC )

最终目标

本文会带你创建一个 MySQL 数据库和一个 Spring 应用,并在 Spring 应用中连接到新创建的数据库。

示例代码见 github.com/spring-guid…

使用 Spring Initializr 创建项目

访问 start.spring.io ,在依赖列表选中 Spring WebSpring Data JPAMySQL Driver ,然后将初始化好的包下载下来,使用 IDE 打开即可

创建数据库

在终端中打开 MySQL

$ sudo mysql --password
复制代码

在 mysql 命令行界面中,使用下面的命令创建一个新数据库

mysql> create database db_example; -- 创建新数据库
mysql> create user 'springuser'@'%' identified by 'ThePassword'; -- 创建用户
mysql> grant all on db_example.* to 'springuser'@'%'; -- 为新用户赋予所有权限
复制代码

创建 application.properties 文件

Spring Boot 本身做了一大堆的默认设置。例如默认的数据库为 H2 。因此,当我们要换一个数据库的时候,就需要在 application.properties 文件中显式进行配置。

创建资源文件: src/main/resources/application.properties ,添加如下内容:

spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:3306/db_example
spring.datasource.username=springuser
spring.datasource.password=ThePassword
spring,datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.jpa.show-sql: true
复制代码

上面的 spring.jpa.hibernate.ddl-auto 值可以为 none, update, createcreate-drop 。详情请阅读 hibernate 文档

  • noneMySQL 的默认值。不会改变数据库结构;
  • update:Hibernate 将根据给定的实体结构来修改数据库(如果启动时格式不一致,会更新表,并保留原数据);
  • create:每次都创建数据库,如果没有表会新建表,如果表内已经有数据则会更新结构,而且不会在关闭时删库;
  • create-drop:创建数据库并在 SessionFactory 关闭时删库(也就是每次程序关闭时清空表)。

译注:这里的“修改”指的是修改数据库结构

最开始,该值必须设置为 createupdate ——因为此时还没有任何数据库结构。在首次运行后,即可根据应用需要,将该值改为 updatenone ——例如当需要改变数据库结构时,可将该值设置为 update

Spring Boot 为 H2 等嵌入式数据库准备的默认值是 create-drop。对于 MySQL 等其他数据库,默认值是 none

为增强安全性,建议在连接生产环境的数据库时将值改为 none,并收回 Spring Boot 所使用的数据库用户的所有权限,只保留最基本的增删改查权限。更多关于安全的内容可见本文文末。

创建 @Entity 模型

接下来需要创建数据实体的模型(src/main/java/com/example/accessingdatamysql/User.data):

package com.example.accessingdatamysql;
​
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
​
@Entity     // 该注解告诉 Hibernate 从该类中创建一个表
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;
    private String name;
    private String email;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
}
复制代码

Hibernate 会自动将实体翻译为表。

创建仓库

然后需要创建一个存储用户记录的仓库,代码如下:

(代码位于 src/main/java/com/example/accessingdatamysql/UserRepository.java )

package com.example.accessingdatamysql;
​
import org.springframework.data.repository.CrudRepository;
import com.example.accessingdatamysql.User;
​
public interface UserRepository extends CrudRepository<User, Integer> {
    
}
复制代码

创建控制器

我们需要创建一个控制器来处理 HTTP 请求,代码如下:

(代码位于 src/main/java/com/example/accessingdatamysql/MainController.java )

package com.example.accessingdatamysql;
​
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ReponseBody;
​
@Controller        // 表明该类是一个控制器
@RequestMapping(path="/demo")
public class MainController {
    /**
     * 该注解意味着要获取名为 userRepository 的 bean,
     * 该 bean 是由 Spring 自动生成的,我们会用它来处理数据
     */
    @Autowired
    private UserRepository userRepository;
    
    @PostMapping(path="/add")
    public @ResponseBody String addNewUser(@RequestParam String name, @RequestParam String email) {
        /**@ResponseBody 说明该函数返回的字符串是一个 response ,而不是 view 名称
         * @RequestParam 说明该参数是来自 GET 或 POST 的
         */
        User n = new User();
        n.setName(name);
        n.setEmail(email);
        userRepository.save(n);
        return "Saved";
    }
    
    @GetMapping(path="/all")
    public @ResponseBody Iterable<User> getAllUsers() {
        // 该函数返回一个 JSON 或 XML 形式的 user 列表
        return userRepository.findAll();
    }
}
复制代码

上面的例子中为两个请求地址显式指明了 POSTGET 方法。默认情况下,@RequestMapping 能够映射所有类型的 HTTP 操作

创建应用类( Application Class )

Spring Initializr 会为应用创建一个简单的类。如下:

package com.example.accessingdatamysql;
​
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
​
@SpringBootApplication
public class AccessingDataMysqlApplication {
​
    public static void main(String[] args) {
        SpringApplication.run(AccessingDataMysqlApplication.class, args);
    }
    
}
复制代码

在这个例子中,我们不需要修改该类

@SpringBootApplication 是下面三个注解的简写:

  • @Configuration : 将类标记为应用上下文( application context )bean 的定义;
  • @EnableAutoConfiguration :让 Spring Boot 根据 classpath 设置、其他的属性设置( various property settings )等来添加 bean 。例如:如果 classpath 中有一个 spring-webmvc ,那么该标记就会将应用程序标记为一个 web 应用,并启用相关的行为——比如启动一个 DispatcherServlet
  • @ComponentScan :让 Spring 寻找在 com/example 包下面的其他组件、配置、服务等,并找到所有的控制器。

main() 方法使用 Spring Boot 的 SpringApplication.run() 函数来启动应用。

创建可运行的 JAR 文件

译注:本节与 juejin.cn/post/707639… 相同,此处略

测试应用

启动应用后,我们可以用 curl 这类工具来进行测试:

GET localhost:8080/demo/all 获取所有数据。POST localhost:8080/demo/add向数据中添加一个新用户。

例如,下面的命令将添加一个新用户:

$ curl localhost:8080/demo/add -d name=First -d [email protected]
复制代码

服务器将返回:

Saved
复制代码

下面的命令将展示所有已有的用户:

$ curl 'localhost:8080/demo/all'
复制代码

服务器将返回:

[{"id":1,"name":"First","email":"[email protected]"}]
复制代码

增强安全性

在实际的生产环境中,我们需要针对 SQL 注入攻击进行防御——黑客可能会注入如 DROP TABLE 或其他毁灭性的 SQL 指令。因此,我们需要在对外提供应用前对数据库进行一些修改。

下面的命令能够收回所有 Spring 应用使用的数据库用户所拥有的特权:

mysql> revoke all on db_example.* from 'springuser'@'%';
复制代码

这样一来,Spring 应用就无法对数据库本身进行任何修改了。

然而,应用必须有一些最小的权限,下面的命令能够确保应用拥有这些权限:

mysql> grant select, insert, delete, update on db_example.* to 'springuser'@'%';
复制代码

这样将只保留 Spring 应用修改数据内容的权限,而不能对数据库结构( schema )进行修改

当需要修改数据库时,可以:

  1. 重新分配权限;
  2. 修改 spring.jpa.hibernate.ddl-auto 值为 update
  3. 重新运行程序

然后再重复执行上面的两条命令,恢复安全性。如果条件允许,最好使用独立的迁移工具如 Flyway 或 Liquibase

猜你喜欢

转载自juejin.im/post/7076670262317416455