宅男在线永久免费观看网直播,亚洲欧洲日产国码无码久久99,野花社区在线观看视频,亚洲人交乣女bbw,一本一本久久a久久精品综合不卡

全部
常見問題
產(chǎn)品動(dòng)態(tài)
精選推薦

Spring Boot 2.x基礎(chǔ)教程:使用Flyway管理數(shù)據(jù)庫版本

管理 管理 編輯 刪除

Flyway簡(jiǎn)介

Flyway是一個(gè)簡(jiǎn)單開源數(shù)據(jù)庫版本控制器(約定大于配置),主要提供migrate、clean、info、validate、baseline、repair等命令。它支持SQL(PL/SQL、T-SQL)方式和Java方式,支持命令行客戶端等,還提供一系列的插件支持(Maven、Gradle、SBT、ANT等)。

官方網(wǎng)站:https://flywaydb.org/

本文對(duì)于Flyway的自身功能不做過多的介紹,讀者可以通過閱讀官方文檔或利用搜索引擎獲得更多資料。下面我們具體說說在Spring Boot應(yīng)用中的應(yīng)用,如何使用Flyway來創(chuàng)建數(shù)據(jù)庫以及結(jié)構(gòu)不一致的檢查。

#動(dòng)手試試

下面我們先預(yù)設(shè)一個(gè)開發(fā)目標(biāo):

  1. 假設(shè)我們需要開發(fā)一個(gè)用戶管理系統(tǒng),那么我們勢(shì)必要設(shè)計(jì)一張用戶表,并實(shí)現(xiàn)對(duì)用戶表的增刪改查操作。
  2. 在任務(wù)1的功能完成之后,我們又有一個(gè)新需求,需要對(duì)用戶表增加了一個(gè)字段,看看如何實(shí)現(xiàn)對(duì)數(shù)據(jù)庫表結(jié)構(gòu)的更改。

目標(biāo) 1 的實(shí)現(xiàn)

第一步:創(chuàng)建一個(gè)基礎(chǔ)的Spring Boot項(xiàng)目,并在pom.xml中加入Flyway、MySQL連接和數(shù)據(jù)訪問相關(guān)的必要依賴(這里選用spring-boot-starter-jdbc作為例子)

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <dependency>
        <groupId>org.flywaydb</groupId>
        <artifactId>flyway-core</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

第二步:按Flyway的規(guī)范創(chuàng)建版本化的SQL腳本。

  • 在工程的src/main/resources目錄下創(chuàng)建db目錄,在db目錄下再創(chuàng)建migration目錄
  • migration目錄下創(chuàng)建版本化的SQL腳本V1__Base_version.sql
DROP TABLE IF EXISTS user ;
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `name` varchar(20) NOT NULL COMMENT '姓名',
  `age` int(5) DEFAULT NULL COMMENT '年齡',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
注意:如果你不想將SQL腳本放到其他目錄,可以用spring.flyway.locations參數(shù)來配置。這里不同于1.x版本的配置項(xiàng)flyway.locations

第三步:根據(jù)User表的結(jié)構(gòu),編寫對(duì)應(yīng)的實(shí)體定義

@Data
@NoArgsConstructor
public class User {

    private Long id;
    private String name;
    private Integer age;

}

第四步:編寫用戶操作接口和實(shí)現(xiàn)

public interface UserService {

    /**
     * 新增一個(gè)用戶
     *
     * @param name
     * @param age
     */
    int create(String name, Integer age);

    /**
     * 根據(jù)name查詢用戶
     *
     * @param name
     * @return
     */
    List<User> getByName(String name);

    /**
     * 根據(jù)name刪除用戶
     *
     * @param name
     */
    int deleteByName(String name);

    /**
     * 獲取用戶總量
     */
    int getAllUsers();

    /**
     * 刪除所有用戶
     */
    int deleteAllUsers();

}

@Service
public class UserServiceImpl implements UserService {

    private JdbcTemplate jdbcTemplate;

    UserServiceImpl(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public int create(String name, Integer age) {
        return jdbcTemplate.update("insert into USER(NAME, AGE) values(?, ?)", name, age);
    }

    @Override
    public List<User> getByName(String name) {
        List<User> users = jdbcTemplate.query("select * from USER where NAME = ?", (resultSet, i) -> {
            User user = new User();
            user.setId(resultSet.getLong("ID"));
            user.setName(resultSet.getString("NAME"));
            user.setAge(resultSet.getInt("AGE"));
            return user;
        }, name);
        return users;
    }

    @Override
    public int deleteByName(String name) {
        return jdbcTemplate.update("delete from USER where NAME = ?", name);
    }

    @Override
    public int getAllUsers() {
        return jdbcTemplate.queryForObject("select count(1) from USER", Integer.class);
    }

    @Override
    public int deleteAllUsers() {
        return jdbcTemplate.update("delete from USER");
    }

}
這里主要介紹Flyway的應(yīng)用,所以采用這種比較簡(jiǎn)單的編寫方式,實(shí)際項(xiàng)目應(yīng)用中,還是推薦MyBatis的具體操作實(shí)現(xiàn)。

第五步:編寫測(cè)試用例

@Slf4j
@SpringBootTest
public class Chapter311ApplicationTests {

    @Autowired
    private UserService userSerivce;

    @Test
    public void test() throws Exception {
        userSerivce.deleteAllUsers();

        // 插入5個(gè)用戶
        userSerivce.create("Tom", 10);
        userSerivce.create("Mike", 11);
        userSerivce.create("Didispace", 30);
        userSerivce.create("Oscar", 21);
        userSerivce.create("Linda", 17);

        // 查詢名為Oscar的用戶,判斷年齡是否匹配
        List<User> userList = userSerivce.getByName("Oscar");
        Assertions.assertEquals(21, userList.get(0).getAge().intValue());

        // 查數(shù)據(jù)庫,應(yīng)該有5個(gè)用戶
        Assertions.assertEquals(5, userSerivce.getAllUsers());

        // 刪除兩個(gè)用戶
        userSerivce.deleteByName("Tom");
        userSerivce.deleteByName("Mike");

        // 查數(shù)據(jù)庫,應(yīng)該有5個(gè)用戶
        Assertions.assertEquals(3, userSerivce.getAllUsers());
    }

}
注意由于Spring Boot 2.4應(yīng)用的junit版本與之前Spring Boot 1.x版本中的不同,因此單元測(cè)試的編寫略有區(qū)別,有興趣的讀者可以分別查看之前介紹文章和這篇文章中的單元測(cè)試的區(qū)別,這里就不細(xì)說了。

第六步:運(yùn)行上面編寫的單元測(cè)試,驗(yàn)證一下效果。

不出意外,單元測(cè)試運(yùn)行ok的話

連上數(shù)據(jù)庫看看。此時(shí)應(yīng)該多出了這兩張表:

  • user表就是我們維護(hù)在SQL腳本中要?jiǎng)?chuàng)建的表
  • flyway_schema_history表是flyway的管理表,用來記錄在這個(gè)數(shù)據(jù)庫上跑過的腳本,以及每個(gè)腳本的檢查依據(jù)。這樣每次應(yīng)用啟動(dòng)的時(shí)候,就可以知道哪個(gè)腳本需要運(yùn)行,或者哪個(gè)腳本發(fā)生了變動(dòng),運(yùn)行基礎(chǔ)可能不對(duì),造成數(shù)據(jù)結(jié)構(gòu)的混亂而阻止運(yùn)行。

目標(biāo) 2 的實(shí)現(xiàn)

有了上面的基礎(chǔ)之后,我們來說說后續(xù)要做表結(jié)構(gòu)的表變動(dòng)該怎么操作,這也是之前讀者出現(xiàn)問題最多的情況,所以在2.x版本教程中特地講一講。

首先,大家在開始使用Flyway之后,對(duì)于數(shù)據(jù)庫表接口的變更就要關(guān)閉這幾個(gè)途徑:

  1. 直接通過工具登錄數(shù)據(jù)去修改表結(jié)構(gòu)
  2. 已經(jīng)發(fā)布的sql腳本不允許修改

正確的表結(jié)構(gòu)調(diào)整途徑:在flyway腳本配置路徑下編寫新的腳本,啟動(dòng)程序來執(zhí)行變更。這樣可以獲得幾個(gè)很大的好處:

  1. 腳本受Git版本管理控制,可以方便的找到過去的歷史
  2. 腳本在程序啟動(dòng)的時(shí)候先加載,再提供接口服務(wù),一起完成部署步驟
  3. 所有表結(jié)構(gòu)的歷史變遷,在管理目錄中根據(jù)版本號(hào)就能很好的追溯

下面根據(jù)一個(gè)實(shí)際需求來具體操作下。假設(shè)我們現(xiàn)在想對(duì)User表增加一個(gè)字段:address,用來存儲(chǔ)用戶的通訊地址,那么我們就需要這樣操作實(shí)現(xiàn)。

第一步:創(chuàng)建腳本文件V1_1__alter_table_user.sql,并寫入增加address列的語句

ALTER TABLE `user` ADD COLUMN `address` VARCHAR(20) DEFAULT NULL;
對(duì)于腳本文件名的基本規(guī)則是:版本號(hào)__描述.sql。當(dāng)然如果你有更細(xì)致的要求,那么可以做更細(xì)致的文件名規(guī)劃,具體細(xì)節(jié)讀者可以查閱文末參考資料中的官方文檔獲取。

第二步:再次執(zhí)行單元測(cè)試,在控制臺(tái)中可以看到如下日志:

2021-01-11 16:58:12.025  INFO 37330 --- [           main] o.f.c.i.database.base.DatabaseType       : Database: jdbc:mysql://localhost:3306/test (MySQL 8.0)
2021-01-11 16:58:12.063  INFO 37330 --- [           main] o.f.core.internal.command.DbValidate     : Successfully validated 2 migrations (execution time 00:00.020s)
2021-01-11 16:58:12.075  INFO 37330 --- [           main] o.f.core.internal.command.DbMigrate      : Current version of schema `test`: 1
2021-01-11 16:58:12.082  INFO 37330 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema `test` to version "1.1 - alter table user"
2021-01-11 16:58:12.113  INFO 37330 --- [           main] o.f.core.internal.command.DbMigrate      : Successfully applied 1 migration to schema `test` (execution time 00:00.045s)

再查看一下數(shù)據(jù)中國(guó)的內(nèi)容:

User表中已經(jīng)有了Address列

Flyway管理表中已經(jīng)有新腳本的加載記錄

如果你還沒有體會(huì)到引入Flyway對(duì)給我們的表結(jié)構(gòu)帶來的好處的話,不妨也留言分享下你們的管理方式吧!

本系列教程《Spring Boot 2.x基礎(chǔ)教程》點(diǎn)擊直達(dá)!。學(xué)習(xí)過程中如遇困難,建議加入Spring技術(shù)交流群open in new window,參與交流與討論,更好的學(xué)習(xí)與進(jìn)步!

#代碼示例

本文的相關(guān)例子可以查看下面?zhèn)}庫中的chapter3-11目錄:


請(qǐng)登錄后查看

CRMEB 最后編輯于2025-02-25 15:01:09

快捷回復(fù)
回復(fù)
回復(fù)
回復(fù)({{post_count}}) {{!is_user ? '我的回復(fù)' :'全部回復(fù)'}}
排序 默認(rèn)正序 回復(fù)倒序 點(diǎn)贊倒序

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level }}

作者 管理員 企業(yè)

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推薦': '推薦'}}
{{item.is_suggest == 1? '取消推薦': '推薦'}}
沙發(fā) 板凳 地板 {{item.floor}}#
{{item.user_info.title || '暫無簡(jiǎn)介'}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
打賞
已打賞¥{{item.reward_price}}
{{item.like_count}}
{{item.showReply ? '取消回復(fù)' : '回復(fù)'}}
刪除
回復(fù)
回復(fù)

{{itemc.user_info.nickname}}

{{itemc.user_name}}

回復(fù) {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}
打賞
已打賞¥{{itemc.reward_price}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回復(fù)' : '回復(fù)'}}
刪除
回復(fù)
回復(fù)
查看更多
打賞
已打賞¥{{reward_price}}
1134
{{like_count}}
{{collect_count}}
添加回復(fù) ({{post_count}})

相關(guān)推薦

快速安全登錄

使用微信掃碼登錄
{{item.label}} 加精
{{item.label}} {{item.label}} 板塊推薦 常見問題 產(chǎn)品動(dòng)態(tài) 精選推薦 首頁頭條 首頁動(dòng)態(tài) 首頁推薦
取 消 確 定
回復(fù)
回復(fù)
問題:
問題自動(dòng)獲取的帖子內(nèi)容,不準(zhǔn)確時(shí)需要手動(dòng)修改. [獲取答案]
答案:
提交
bug 需求 取 消 確 定
打賞金額
當(dāng)前余額:¥{{rewardUserInfo.reward_price}}
{{item.price}}元
請(qǐng)輸入 0.1-{{reward_max_price}} 范圍內(nèi)的數(shù)值
打賞成功
¥{{price}}
完成 確認(rèn)打賞

微信登錄/注冊(cè)

切換手機(jī)號(hào)登錄

{{ bind_phone ? '綁定手機(jī)' : '手機(jī)登錄'}}

{{codeText}}
切換微信登錄/注冊(cè)
暫不綁定
CRMEB客服

CRMEB咨詢熱線 咨詢熱線

400-8888-794

微信掃碼咨詢

CRMEB開源商城下載 源碼下載 CRMEB幫助文檔 幫助文檔
返回頂部 返回頂部
CRMEB客服