使用Spring Boot创建Web应用程序的DB访问部分

首先

我想用Spring Boot + Thymeleaf来集成开发Web应用程序。

以下是上一篇「使用Spring Boot创建Web应用程序〜Hello World篇〜」的延续。

我希望在本次开发中实现对数据库的访问(初始化、注册、查询)功能。本篇文章的目标是显示能够从数据库获取/注册值的以下屏幕。

スクリーンショット 2020-06-21 14.49.12.png

这次的材料

    • Spring Boot

 

    • Flayway

 

    • Mybatis

 

    h2database

完成的源代码可以在这里访问。

总结

这是本次使用材料的概要。

飞英

这是一个数据库迁移框架。简单来说,它是一个自动创建和升级数据库表格的工具。

优点

    • 環境構築時に手動で SQL を流さなくても良い

 

    • 現在の DB のバージョンを気にせずに起動すれば自動的に最新になる

 

    → アプリを起動したけど SQL エラーが発生した.原因を調査したら DB のテーブルが古かったということがなくなる

Mybatis -> Mybatis是一个Java持久层框架。

这是一个将SQL和Java对象进行关联的持久化框架。简单来说,它可以将XML中编写的SQL和Java代码进行对应,并自动进行类型转换。通过它,你可以不再使用Java的字符串连接来编写SQL。

H2数据库

运行在Java平台上的ACID关系数据库。
虽然可以使用Oracle或者PostgreSQL,但为了测试方便且不需要复杂的环境设置,我们选择了这个轻量级的数据库。
由于是内存数据库,所以很轻便,但是如果不进行持久化操作,在程序结束时所有数据都将会消失。

安装

为了将这次使用的三个添加到依赖关系中,我们将在 build.gradle 的 dependencies 中添加以下内容。

dependencies {
    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'
    annotationProcessor 'org.projectlombok:lombok'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
    implementation 'org.flywaydb:flyway-core' // 追加
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3' // 追加
    runtimeOnly 'com.h2database:h2' // 追加
}

只需这样,安装就完成了。

数据库的初始设置

首先要创建数据库的定义文件。
默认情况下,它被设置在src/main/resources/db/migration目录下,所以在创建SQL文件时,我们需要创建不存在的文件夹。
文件名的格式如下:
V{版本号}__{描述}.sql
※ 分隔符是两个下划线。

文件名的例子

    • V1.0__init.sql

 

    V1.0.1__insert_test_data.sql

版本会按照数字的大小顺序进行执行。本次将以V1.0__init.sql的形式插入表的定义和初始数据。

CREATE TABLE neko_table (
    id INT,
    name VARCHAR(30),
    age INT
);

insert into neko_table (id, name, age) values (1, 'たま', 3);
insert into neko_table (id, name, age) values (2, 'みけ', 1);
insert into neko_table (id, name, age) values (3, 'くろ', 4);

只需这样,应用程序在启动时会查找当前数据库版本,如果是空数据库则创建,如果不是最新版本则更新到最新定义。

从数据库中获取信息

从数据库中获取值和进行注册使用的是MyBatis。

领域

因为与DB列名称一致创建变得更容易,所以我们将创建一个以DB列命名为同名的实体。

package com.example.demo.domain;
import lombok.Data;
@Data // Lombokでgetterやsetterを自動生成
public class Neko {
    private int id;
    private String name;
    private int age;
}

你可以使用Lombok自动生成getter/setter从而减少代码量。

绘制地图的人

界面

定义了数据库访问的接口。

package com.example.demo.mapper;
import java.util.ArrayList;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import com.example.demo.domain.Neko;
@Repository // springのDIの対象となる
@Mapper // MybatisでxmlのSQLが対応づけられる
public interface NekoMapper {
    public ArrayList<Neko> getNekoList();
    public boolean insertNeko(Neko neko);
}

我会准备一个方法来简单地获取全部内容,并准备两个额外的方法。
通过@Repository注解将其注册到Spring的依赖注入中,
@Mapper注解将其与在xml中定义的SQL语句的接口进行对应。
该方法在执行时的SQL语句将在XML中定义。
虽然也可以使用@Sql注解进行说明, 但由于注解本身无法实现某些功能,并且当注解变得多行时,可读性会降低,因此选择在XML文件中进行定义。

配置

将数据库连接设置添加到 application.properties 文件中。

# FlywayのDB定義
spring.flyway.url=jdbc:h2:mem:NekoDB
spring.flyway.user=user
spring.flyway.password=password

# MybatisのDB定義
spring.datasource.url=jdbc:h2:mem:NekoDB
spring.datasource.username=user
spring.datasource.password=password

在Flyway和Mybatis中都需要进行配置。
数据库的URL将是jdbc:h2:mem:<DB名>。
用户和密码可以是任意的。

为了简化在 XML 中编写更多的 SQL,我们将以下内容添加到 application.properties 文件中。

# Mybatisのタイプエイリアス
mybatis.type-aliases-package=com.example.demo.domain,com.example.demo.mapper
# DB上のカラム「NEKO_TYPE」をJavaの「nekoType」に自動変換する
mybatis.configuration.map-underscore-to-camel-case=true

通过指定类型别名可以省去写入FQCN的麻烦。在数据库中,经常使用蛇形命名法,而在Java中,则经常使用驼峰命名法,因此启用自动转换设置。*在本次代码中不需要。

SQL (Structured Query Language)

接下来是SQL的定义。
需要使用与Mapper相同的文件名进行创建,所以将其保存在以下层次结构中。
/src/main/resources/com/example/demo/mapper/NekoMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- mapperのFQCNを指定 -->
<mapper namespace="com.example.demo.mapper.NekoMapper">
    <!-- select文はselectタグを利用する.idはインターフェースのメソッド名とする.resultTypeで結果を格納するJavaのオブジェクトを指定 -->
    <select id="getNekoList" resultType="Neko">
        SELECT * FROM neko_table
    </select>
    <!-- insert文はinsertタグを利用する.idはインターフェースのメソッド名とする.-->
    <!-- parameterTypeで引数のJavaのオブジェクトを指定.#{name}と指定すると,オブジェクトのgetName()から値を取得する. -->
    <insert id="insertNeko" parameterType="Neko">
        INSERT INTO neko_table (id, name, age) VALUES (#{id}, #{name}, #{age})
    </insert>
</mapper>

由于在配置中指定了类型别名,所以只需在resultType中写入类名而不是FQCN即可。

服务

package com.example.demo.service;
import java.util.ArrayList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.demo.domain.Neko;
import com.example.demo.mapper.NekoMapper;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class NekoService {

    @Autowired
    private final NekoMapper mapper;

    /**
     * ねこの一覧を取得する
     *
     * @return 一覧
     */
    public ArrayList<Neko> getNekoList() {
        return mapper.getNekoList();
    }

    /**
     * ねこを登録する
     *
     * @param neko
     * @return
     */
    public boolean insertNeko(Neko neko) {
        return mapper.insertNeko(neko);
    }
}

这次不像之前那样创建数组并返回,而是为了从数据库中获取信息,我们要执行映射器。
※由于没有进行错误检查等工作,所以几乎没有起到任何作用。

控制器

从上次到现在没有任何变更。

观看

没有从上次开始有任何变动。

确认行动

スクリーンショット 2020-06-21 14.24.53.png

我认为表格的内容是由Flyway投入的初始数据。

将数据注册到数据库中。

我在数据引用方面已经做了大约一半的准备,但我也想实现数据插入(insert)。

观看

定义用于数据注册的表单。

<form th:action="@{neko}" th:method="POST">
  <div>登録フォーム</div>
  <input type="text" name="id" placeholder="ID" />
  <input type="text" name="name" placeholder="名前" />
  <input type="text" name="age" placeholder="年齢" />
  <input type="submit" value="登録" />
</form>

请将POST请求也设定为与GET请求相同的“neko”。

控制器

为了使得PSOT能够正常工作,我们在NekoController.java中添加以下方法。

    @PostMapping("neko") // nekoへのPOSTを制御する
    public String insertNeko(@ModelAttribute Neko form, Model model) { // formとしてNekoをそのまま使う(手抜き)
        service.insertNeko(form); // DBにinsert
        model.addAttribute("nekoList", service.getNekoList()); // serviceから一覧を再取得
        return "neko"; // neko.htmlをクライアントに返す
    }

对于Form来说,应该创建一个新的对象,但是我懒散地直接使用了现成的Neko对象。
我会将传入的Form直接使用service的insertneko方法注册到数据库中。

确认动作

スクリーンショット 2020-06-21 14.48.45.png
スクリーンショット 2020-06-21 14.49.12.png

总结

我使用SpringBoot + Flyway + Mybatis实现了对数据库的访问。下一步,我计划实现表单验证功能。

广告
将在 10 秒后关闭
bannerAds