使用Spring Boot和PostgreSQL进行数据注册的技巧(附有解释)

首先

辛苦了!我是@Keichan_15!

我想使用Spring Boot和PostgreSQL开发一个功能,可以将表单中输入的值存入数据库并显示注册的数据。

因为曾经接触过Rails,所以对于开发经验较好的Spring Boot也相当喜欢。

我们开始吧!

环境 –

    • Windows11(Windows10でもほぼ同じ)

 

    • Eclipse 2022-12 (4.26.0)

 

    • Spring Boot

 

    PostgreSQL v15.3

创建项目

我們將從創建Spring Boot項目開始。雖然有多種安裝方法,但本次我們將使用Spring官方提供的教程《Spring Initializr》。

 

点击文件 > 新建 > 选择Spring Starter项目 (Spring Initializr)。

image.png

特定のデフォルトでは問題ありません。次に進むを選択します。

image.png

将依赖关系添加进去。除了默认添加的之外,还会添加以下三种依赖关系。

    • Thymeleaf

 

    • PostgreSQL Driver

 

    Spring Data JPA

为了确保不会遗漏任何选择,尤其要确保PostgreSQL驱动程序和Spring Data JPA,因为它们对于连接PostgreSQL是必需的。

顺便提一句,关于构建工具,是选择Gradle还是Maven好呢?实际上我只用过Gradle,所以无法评判…

 

我們稍微偏離了一下…(-_-;) 讓我們重新集中注意力。

项目创建后的目录结构如下。

demo
│  .classpath
│  .gitignore
│  .project
│  build.gradle
│  gradlew
│  gradlew.bat
│  HELP.md
│  settings.gradle
│
├─.gradle
│  ├─7.6.1
│  │  │  gc.properties
│  │  │
│  │  ├─checksums
│  │  │      checksums.lock
│  │  │
│  │  ├─dependencies-accessors
│  │  │      dependencies-accessors.lock
│  │  │      gc.properties
│  │  │
│  │  ├─executionHistory
│  │  │      executionHistory.lock
│  │  │
│  │  ├─fileChanges
│  │  │      last-build.bin
│  │  │
│  │  ├─fileHashes
│  │  │      fileHashes.lock
│  │  │
│  │  └─vcsMetadata
│  ├─buildOutputCleanup
│  │      buildOutputCleanup.lock
│  │      cache.properties
│  │
│  └─vcs-1
│          gc.properties
│
├─.settings
│      org.eclipse.buildship.core.prefs
│
├─bin
│  ├─main
│  │  │  application.properties
│  │  │
│  │  ├─com
│  │  │  └─example
│  │  │      └─demo
│  │  │              DemoApplication.class
│  │  │
│  │  └─templates
│  └─test
│      └─com
│          └─example
│              └─demo
│                      DemoApplicationTests.class
│
├─gradle
│  └─wrapper
│          gradle-wrapper.jar
│          gradle-wrapper.properties
│
└─src
    ├─main
    │  ├─java
    │  │  └─com
    │  │      └─example
    │  │          └─demo
    │  │                  DemoApplication.java
    │  │
    │  └─resources
    │      │  application.properties
    │      │
    │      ├─static
    │      └─templates
    └─test
        └─java
            └─com
                └─example
                    └─demo
                            DemoApplicationTests.java

另外,在build.gradle中确保依赖关系已经正确添加。

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	developmentOnly 'org.springframework.boot:spring-boot-devtools'
	runtimeOnly 'org.postgresql:postgresql'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

如果按照上述方式做了,就意味着Spring Boot的引入已经完成了。辛苦你了。

接下来,我们会进行PostgreSQL的准备工作。

安装PostgreSQL

如果您还没有下载PostgreSQL,可以从EDB下载。

 

image.png

我已经下载了 Windows x86-64 最新版本的 v15.3。请注意,由于操作系统的不同,可能存在不支持或者下载链接在另一个页面中的情况,请仔细确认。

由于涉及到PostgreSQL的下载方法跑题了,因此我们将省略不提。

以下是一些参考资料,可供您参考,包括日本PostgreSQL用户组介绍的安装指南和下面的文章。

 

PostgreSQL下载完成后,我们立即准备用于CRUD操作的数据注册用数据库吧!

数据库准备

首先,我们将构建适用于本篇文章的数据库。

个人觉得,最开始使用命令行界面并紧盯着黑屏进展,会更有助于学习。以下文章等都是如此。

 

为了快速构建,我们将使用方便的GUI工具pgAdmin4。后面你就会知道为什么选择pgAdmin4了。(笑)

如果在默认情况下下载了 PostgreSQL,那么 PGAdmin4 的 exe 文件将位于 C:\Program Files\PostgreSQL\15\pgAdmin4\runtime 目录下。

执行exe文件,打开pgAdmin4时会提示输入密码,请在此处输入您在安装时设置的密码。

如果屏幕上显示出如下内容就可以了。

image.png

这样一来,由于可以以视觉方式操作数据库和具有漂亮的用户界面,所以我个人推荐它。
除非特别注重命令行界面,或者希望通过输入命令来学习的人,否则我认为应该使用它。

下一步是创建数据库。这次我们将创建一个名为testdb的数据库。

请点击左侧的对象资源管理器,选择数据库,然后右键单击 > 创建 > 数据库… 继续操作。

image.png
image.png
image.png

在没有任何问题的情况下,可以确认在Object Explorer的数据库内已经添加了testdb。

image.png

数据库已经创建完成了!辛苦了。接下来我们开始创建表和列吧!

创建表格和列。

首先,我们需要创建一个用于存储已注册数据的forums表以及用于存储每个数据的列。
右键点击Object Explorer中的testdb,然后选择Query Tool。

image.png

请运行以下的SQL语句。

create TABLE forums (
  id serial primary key,
  title varchar(20),
  body varchar(100)
);
image.png

如果出现这样的表示,说明表格已经创建成功。

为了将画面反映出来, 选择”刷新…”. 这个选项也会在右键点击testdb时出现.

image.png

以下是添加的表格的显示结果。

image.png

我将简要总结我们在这个地方添加的每个栏目。

id : AUTO INCREMENTによる自動採番

title : 投稿の「タイトル」を保持するカラム。文字数上限は20文字。

body : 投稿の「本文」を保持するカラム。文字数上限は100文字。

我们来确认一下是否已经添加了新的列。

当你在Lists上点击右键,选择View/Edit Data > All Rows,你可以查看表格中的所有数据。

image.png
image.png

目前只定义了表格和列,所以现在处于类似于空白画面的状态。
在这个表格的每个列上,将会存储由Spring Boot端的表单输入的值。

这个表和列的创建工作已经完成了。

最后,我们要修改Spring Boot的application.properties文件。

spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.username=postgres
spring.datasource.password="インストール時に決めたパスワード"
spring.jpa.open-in-view=True

如果不进行这个设置,Spring Boot和postgreSQL将无法连接,因此请确保没有遗漏。

spring.datasource.password="インストール時に決めたパスワード"

请您将密码更改为您自己设定的密码。

执行

我们终于开始进行Spring Boot的实现。
关于Spring Boot的详细内容,我们将在以后的文章中总结,但为了初次接触的人,我们会适时地插入解释,如果有任何不清楚的地方,请在评论中告知,将不胜感激。

本次将说明关于使用同步通信进行数据登记的技巧。关于使用异步通信(Ajax × jQuery)进行数据登记的内容将在以后的文章中整理。

(什么是寄り道)MVC模型?

首先,Spring Boot处理的重要概念之一是MVC模型。对于那些曾经使用过Ruby on Rails等Web框架的人来说,这是一个熟悉的概念。

MVC模型将代码分为M(Model)、V(View)和C(Controller)三个部分,分别代表模型、视图和控制器。

Model : データベースとのやりとりやシステム内のデータ処理を担当

View : 画面表示を担当

Controller : ViewとModelの動作制御を担当(いわば仲介役)

通过采用MVC模型,文件可以根据角色独立存在,这可以提高可维护性和开发效率,这是一个优点。

◎建立模型

让我们从最初的系统核心模型开始创建。

这次要创建的模型是Forum.java。

package com.example.demo.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;

@Data
@Entity
@Table(name = "forums")
public class Forum {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id")
	private Integer id;
	@Column(name = "title")
	private String title;
	@Column(name = "body")
	private String body;
}

解释

如果你没有使用Java进行实现过,可能会对以下的表达感到困惑。

@Data
@Entity
@Table
@Id
@GeneratedValue
@Column

这被称为注释。注释直译为”注解”,通过在源代码中添加注释,可以修改程序的行为,还可以指示Spring Boot等框架进行处理。

例如,对于@Data注解而言,此注解会在编译时自动生成以下方法。

    • setter()

 

    • getter()

 

    • toString()

 

    • equals()

 

    hashCode()

只需一个选项:特别是不需要编写前两个getter和setter方法的优点是,

    • 開発者側も実装負担が減る

 

    ソースコードの可読性向上

由于这会产生连锁反应,可以说没有不使用注释的选择。

为了避免偏离本文的主题,我们将省略对每个注释进行详细解释。
以下网站上概括了注释的列表。非常方便…。

 

请看下面的注释和实现细节,希望对您的学习有所帮助。

package com.example.demo.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;

// getter(), setter()を自動生成するアノテーション
@Data
// JPAのエンティティであることを示すアノテーション
@Entity
// エンティティに対応するテーブル名を指定。 "forums"部分はPostgreSQLで作成したテーブル名
@Table(name = "forums")
public class Forum {

    // エンティティの主キーを指定。今回であれば "id" カラムになる
	@Id
    // オートインクリメント。主キー "id" の値を自動採番する
	@GeneratedValue(strategy = GenerationType.IDENTITY)

    // カラムに名前を付与
	@Column(name = "id")
	private Integer id;

	@Column(name = "title")
	private String title;

	@Column(name = "body")
	private String body;
}

这样,模型的实现就完成了!

◎创建控制器

接下来,我们将创建Controller。

首先,我们将创建一个ForumController。

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.example.demo.model.Forum;
import com.example.demo.service.ForumService;

@Controller
public class ForumController {

    // 特定のアノテーションを付与したクラスのインスタンスを使用可能にする(依存性注入・DI) 
	@Autowired
	ForumService service;

	// トップページ(フォームがある画面)
    // HTTPリクエストの"GET"を受け付けるメソッドに付与するアノテーション
	@GetMapping("/")
	public String top(Model model) {
		model.addAttribute("forum", new Forum());
		return "top";
	}

	// データベースへの登録
    // HTTPリクエストの"POST"を受け付けるメソッドに付与するアノテーション
	@PostMapping("/create")
	public String saveForum(@ModelAttribute Forum forum, Model model) {

        // serviceクラスのinsertメソッドを呼び出し、DBに入力値を登録
		service.insert(forum);
		return "result";
	}

}

说明

本次亮相的注解包括 @Autowired、@GetMapping、@PostMapping。

尤其是@Autowired这一点,它是使用DI(依赖注入)进行的。通过给特定注解(比如@Service和后面提到的@Repository)标记的类的实例,可以通过带有@Autowired注解的字段变量等来获取。

让我们来看一下用于显示首页的top方法。

	@GetMapping("/")
	public String top(Model model) {
		model.addAttribute("forum", new Forum());
		return "top";
	}

当通过@GetMapping注解指定的URL收到GET请求时,该方法会被执行。例如:访问localhost:8080/。

model.addAttribute(“forum”, new Forum());用于在视图中传递值。
addAttribute方法的参数设置方式是,第一个参数设置在视图中使用的变量名,第二个参数设置要传递给视图的值。

在这种情况下,变量forum中存储了一个Forum类的空实例,并将其设置为视图对象部分(在下文中介绍的View),从而可以存储表单的值。

然后在返回值中指定了top,这个返回值的名称将成为View文件的文件名。这是一个重要的点。

总结流的形象,

1. ルートパスにHTTPリクエスト(GET)が送られる
2. model.addAttributeでViewにフォームの空インスタンスを渡す
3. top.htmlを表示する

这样就可以在top.html中创建表单。

接下来我们来看一下必须进行数据库注册的方法saveForum。

	@PostMapping("/create")
	public String saveForum(@ModelAttribute Forum forum, Model model) {

		service.insert(forum);
		return "result";
	}

大部分与之前所提到的top方法没有什么不同。只介绍新出现的内容。

@ModelAttribute
saveForumメソッドの引数に@ModelAttributeのアノテーションが付与されています。
このアノテーションが付与されることにより、フォームで入力した値を受け取ることができるようになります。
引数のforumは、後述のtop.htmlのViewで作成したフォームのオブジェクト部分に入っているデータになります。

在以下的

标签中,th:object的值是forum。
关于View的解释稍后会详细说明,所以只需知道它接收了表单中输入的值即可,不会有问题!

<form th:action="@{/create}" th:object="${forum}" method="post">

service.insert(forum);
ここではServiceクラスのinsertメソッドを呼び出しています。前述のDI(依存性注入)によって呼び出すことができる仕組みです。
insert()の引数にフォームに入力された値が格納されているオブジェクトを設定することで、DBへ登録処理を行うことができます。
insert()メソッドの詳しい内容についても、後ほどServiceクラスの章で説明します。

当完成向数据库的注册处理后,我们设置将转到result.html页面。

控制器的说明就是这样了。真难啊…

◎创建视图

接下来我们会创建一个视图。

通过在Spring Boot中将视图文件放置在src/resources/templates目录下,可以实现页面的显示。

首先,我们需要创建一个顶层页面来展示表单界面。

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">

<head>
	<title>Index</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>

<body>
	<h2>【New Post】</h2>
	<form th:action="@{/create}" th:object="${forum}" method="post">

		<label>Title</label>
		<p><input type="text" th:field="*{title}" /></p>

		<label>Body</label>
		<p><textarea id="form" th:field="*{body}"></textarea></p>
		<p><input type="submit" value="送信" id="button" /></p>
	</form>
</body>

</html>

此外,我们还会设计一个用于显示发布内容的界面。

<!DOCTYPE HTML>
<html>

<head>
	<title>Result View</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>

<body>
	<div>
		<p>[[${forum.title}]]</p>
		<p>[[${forum.body}]]</p>
		<p><a href="http://localhost:8080/">一覧画面へ</a></p>
	</div>
</body>

</html>

解說 –> 说明

首先我们从首页开始看。

本次使用thymeleaf作为模板引擎。

<html xmlns:th="http://www.thymeleaf.org">

在这里,将thymeleaf的属性命名为th,并声明和使用命名空间。

借助thymeleaf,我们可以简洁地实现与表单相关的内容。

<form th:action="@{/create}" th:object="${forum}" method="post">
th:actionth:objectmethodフォームのアクションを設定(Controller側で使用)${}内のオブジェクトにフォーム入力値が格納HTTPメソッドを指定

此外,通过使用th:field来完成表单输入部分,可以将值存储在对象的字段中。

<p><input type="text" th:field="*{title}" /></p>
<p><textarea id="form" th:field="*{body}"></textarea></p>

在这里提到的”字段”是指在模型Forum.java中的字段。

// フィールド
@Column(name = "id")
private Integer id;

@Column(name = "title")
private String title;

@Column(name = "body")
private String body;

以上就是首页的实现。

接下来,我们要看的是结果显示屏。

<p>[[${forum.title}]]</p>
<p>[[${forum.body}]]</p>

我觉得你可能已经略有察觉,上面的部分展示了你在输入框中输入的内容。

以上是视图的实现。意外地很简单。

◎建立仓库

接下来我们将创建一个仓库。

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.example.demo.model.Forum;

@Repository
public interface ForumRepository extends JpaRepository<Forum, Integer> {
}

创建一个继承JpaRepository的接口,用于操作数据库。
通过继承JpaRepository,可以自动生成与数据操作相关的CRUD(创建、获取、更新、删除)方法。非常方便。

接下来创建一个Service。

◎服务制作

package com.example.demo.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.model.Forum;
import com.example.demo.repository.ForumRepository;

import jakarta.transaction.Transactional;

@Service
@Transactional
public class ForumService {

	@Autowired
	ForumRepository repository;

	// データベースよりフォーラム(掲示板)の一覧を取得
	public List<Forum> findAll() {
		return repository.findAll();
	}

	// データベースに値を登録
	public void insert(Forum forum) {
		repository.save(forum);
	}
}

解释

让我们通过这次新增的注释来看一看。

@Service 注解表示该类是一个服务类。
此外,通过添加 @Transactional 注解可以进行数据库的事务控制(在这种小规模应用中毫无必要性)。

接下来是关于数据库操作方法的部分。
在`repository.findAll()`中,我们使用通过`@Autowired`创建的ForumRepository实例来进行检索所有记录的操作。这可以用于在需要显示已注册数据的情况下。但在本次情景中我们不会使用它。

使用repository.save(forum)方法,将包含表单输入值的对象作为参数传递,并将其存储到数据库中。

服务的实现和解释就到这里。现在所有的实现都已经完成了。

最后的树形结构如下所示。

demo
│  .classpath
│  .gitignore
│  .project
│  build.gradle
│  gradlew
│  gradlew.bat
│  HELP.md
│  settings.gradle
│
├─.gradle
│  ├─7.6.1
│  │  │  gc.properties
│  │  │
│  │  ├─checksums
│  │  │      checksums.lock
│  │  │      md5-checksums.bin
│  │  │      sha1-checksums.bin
│  │  │
│  │  ├─dependencies-accessors
│  │  │      dependencies-accessors.lock
│  │  │      gc.properties
│  │  │
│  │  ├─executionHistory
│  │  │      executionHistory.lock
│  │  │
│  │  ├─fileChanges
│  │  │      last-build.bin
│  │  │
│  │  ├─fileHashes
│  │  │      fileHashes.lock
│  │  │
│  │  └─vcsMetadata
│  ├─buildOutputCleanup
│  │      buildOutputCleanup.lock
│  │      cache.properties
│  │
│  └─vcs-1
│          gc.properties
│
├─.settings
│      org.eclipse.buildship.core.prefs
│
├─bin
│  ├─main
│  │  │  application.properties
│  │  │
│  │  ├─com
│  │  │  └─example
│  │  │      └─demo
│  │  │          │  DemoApplication.class
│  │  │          │
│  │  │          ├─controller
│  │  │          │      ForumController.class
│  │  │          │
│  │  │          ├─model
│  │  │          │      Forum.class
│  │  │          │
│  │  │          ├─repository
│  │  │          │      ForumRepository.class
│  │  │          │
│  │  │          └─service
│  │  │                  ForumService.class
│  │  │
│  │  └─templates
│  │          result.html
│  │          top.html
│  │
│  └─test
│      └─com
│          └─example
│              └─demo
│                      DemoApplicationTests.class
│
├─gradle
│  └─wrapper
│          gradle-wrapper.jar
│          gradle-wrapper.properties
│
└─src
    ├─main
    │  ├─java
    │  │  └─com
    │  │      └─example
    │  │          └─demo
    │  │              │  DemoApplication.java
    │  │              │
    │  │              ├─controller
    │  │              │      ForumController.java
    │  │              │
    │  │              ├─model
    │  │              │      Forum.java
    │  │              │
    │  │              ├─repository
    │  │              │      ForumRepository.java
    │  │              │
    │  │              └─service
    │  │                      ForumService.java
    │  │
    │  └─resources
    │      │  application.properties
    │      │
    │      ├─static
    │      └─templates
    │              result.html
    │              top.html
    │
    └─test
        └─java
            └─com
                └─example
                    └─demo
                            DemoApplicationTests.java

我们最后来确认一下是否有动作上的问题!

确认操作

首先启动服务器。您可以通过引导仪表板执行服务器启动操作。

image.png

如果在控制台上出现以下这样的提示,说明启动已完成。

image.png

我将访问localhost:8080。我认为会显示如下页面。

image.png

在表单中输入值,并点击提交按钮。

image.png

如果出现以下的画面,就代表没问题!

image.png

我们来确认一下数据库中是否成功注册了数据。

image.png

问题看起来没有。

以上就完成了使用Spring Boot × PostgreSQL进行注册功能。辛苦了!

请提供更多相关信息.

 

结束了

这一次使用了Spring Boot和PostgreSQL,实现了最基本的数据注册功能,您觉得如何?

实际上,我第一次接触Spring Boot时,正如前面所述,它与Rails等Web框架非常相似,因此我相对容易理解。
但是最近我主要在使用Next.js、Go和Docker,所以可能暂时不需要再碰Spring Boot了呢。

大家一起来用Spring Boot吧!

bannerAds