ืืคืก ืคืจื™ืกืช ื–ืžืŸ ื”ืฉื‘ืชื” ื•ืžืกื“ื™ ื ืชื•ื ื™ื

ืืคืก ืคืจื™ืกืช ื–ืžืŸ ื”ืฉื‘ืชื” ื•ืžืกื“ื™ ื ืชื•ื ื™ื

ืžืืžืจ ื–ื” ืžืกื‘ื™ืจ ื‘ืคื™ืจื•ื˜ ื›ื™ืฆื“ ืœืคืชื•ืจ ื‘ืขื™ื•ืช ืชืื™ืžื•ืช ืฉืœ ืžืกื“ื™ ื ืชื•ื ื™ื ื‘ืคืจื™ืกื”. ืื ื• ืื’ื™ื“ ืœืš ืžื” ื™ื›ื•ืœ ืœืงืจื•ืช ืœื™ื™ืฉื•ืžื™ ื”ื™ื™ืฆื•ืจ ืฉืœืš ืื ืชื ืกื” ืœืคืจื•ืก ืœืœื ื”ื›ื ื” ืžื•ืงื“ืžืช. ืœืื—ืจ ืžื›ืŸ ื ืขื‘ื•ืจ ืืช ืฉืœื‘ื™ ืžื—ื–ื•ืจ ื”ื—ื™ื™ื ืฉืœ ื”ืืคืœื™ืงืฆื™ื” ืฉื ื“ืจืฉื™ื ืœืืคืก ื–ืžืŸ ื”ืฉื‘ืชื” (ืžืฉื•ืขืจ. ื ืชื™ื‘: ืขื•ื“ ื™ื•ืชืจ - ืืคืก ื–ืžืŸ ื”ืฉื‘ืชื”). ื”ืชื•ืฆืื” ืฉืœ ื”ืคืขื•ืœื•ืช ืฉืœื ื• ืชื”ื™ื” ืœื”ื—ื™ืœ ืืช ื”ืฉื™ื ื•ื™ ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ืฉืื™ื ื• ืชื•ืื ืœืื—ื•ืจ ื‘ืื•ืคืŸ ืชื•ืื ืœืื—ื•ืจ.

ืื ืืชื” ืจื•ืฆื” ืœื”ื‘ื™ืŸ ืืช ื“ื•ื’ืžืื•ืช ื”ืงื•ื“ ืžื”ืžืืžืจ, ืชื•ื›ืœ ืœืžืฆื•ื ืื•ืชืŸ ื‘ื›ืชื•ื‘ืช GitHub.

ืžื‘ื•ื

ืืคืก ืคืจื™ืกืช ื–ืžืŸ ื”ืฉื‘ืชื”

ืื™ื–ื” ืžื™ืกื˜ื™ ืืคืก ืคืจื™ืกืช ื–ืžืŸ ื”ืฉื‘ืชื”? ืืชื” ื™ื›ื•ืœ ืœื•ืžืจ ืฉื–ื” ื›ืืฉืจ ื”ืืคืœื™ืงืฆื™ื” ืฉืœืš ืคืจื•ืกื” ื‘ืฆื•ืจื” ื›ื–ื• ืฉืชื•ื›ืœ ืœื”ืฆื™ื’ ื‘ื”ืฆืœื—ื” ื’ืจืกื” ื—ื“ืฉื” ืฉืœ ื”ืืคืœื™ืงืฆื™ื” ืœื™ื™ืฆื•ืจ, ื‘ื–ืžืŸ ืฉื”ืžืฉืชืžืฉ ืœื ืฉื ืœื‘ ืœืื™-ื–ืžื™ื ื•ืชื”. ืžื ืงื•ื“ืช ืžื‘ื˜ ืฉืœ ืžืฉืชืžืฉ ื•ื—ื‘ืจื”, ื–ื”ื• ืชืจื—ื™ืฉ ื”ืคืจื™ืกื” ื”ื˜ื•ื‘ ื‘ื™ื•ืชืจ ื”ืืคืฉืจื™ ืžื›ื™ื•ื•ืŸ ืฉื”ื•ื ืžืืคืฉืจ ืœื”ืฆื™ื’ ืชื›ื•ื ื•ืช ื—ื“ืฉื•ืช ื•ืœืชืงืŸ ื‘ืื’ื™ื ืœืœื ื”ืคืจืขื”.

ืื™ืš ืœื”ืฉื™ื’ ื–ืืช? ื™ืฉื ืŸ ืžืกืคืจ ื“ืจื›ื™ื, ื”ื ื” ืื—ืช ืžื”ืŸ:

  • ืœืคืจื•ืก ื’ืจืกื” ืžืก' 1 ืฉืœ ื”ืฉื™ืจื•ืช ืฉืœืš
  • ืœื‘ืฆืข ื”ืขื‘ืจืช ืžืกื“ ื ืชื•ื ื™ื
  • ืคืจื•ืก ืืช ื’ืจืกื” ืžืก' 2 ืฉืœ ื”ืฉื™ืจื•ืช ืฉืœืš ื‘ืžืงื‘ื™ืœ ืœื’ืจืกื” ืžืก' 1
  • ื‘ืจื’ืข ืฉืืชื” ืจื•ืื” ืฉื’ืจืกื” ืžืก' 2 ืขื•ื‘ื“ืช ื›ืžื• ืฉืฆืจื™ืš, ื”ืกืจ ืืช ื’ืจืกื” ืžืก' 1
  • ื ืขืฉื”!

ืงืœ, ืœื? ืœืžืจื‘ื” ื”ืฆืขืจ, ื–ื” ืœื ื›ืœ ื›ืš ืคืฉื•ื˜, ื•ื ืกืชื›ืœ ืขืœ ื–ื” ื‘ืคื™ืจื•ื˜ ื‘ื”ืžืฉืš. ื›ืขืช ื ื‘ื“ื•ืง ืขื•ื“ ืชื”ืœื™ืš ืคืจื™ืกื” ื ืคื•ืฅ ืœืžื“ื™ - ืคืจื™ืกื” ื›ื—ื•ืœ ื™ืจื•ืง.

ื”ืื ืฉืžืขืช ืื™ ืคืขื ืขืœ ืคืจื™ืกื” ื›ื—ื•ืœ ื™ืจื•ืง? Cloud Foundry ืขื•ืฉื” ืืช ื–ื” ืงืœ ื‘ืžื™ื•ื—ื“. ืจืง ืชืกืชื›ืœ ืžืืžืจ ื–ื”, ืฉื ืื ื• ืžืชืืจื™ื ื–ืืช ื‘ื™ืชืจ ืคื™ืจื•ื˜. ืœืกื™ื›ื•ื ืงืฆืจ, ื”ืจืฉื• ืœื ื• ืœื”ื–ื›ื™ืจ ืœื›ื ื›ื™ืฆื“ ืœื‘ืฆืข ืคืจื™ืกื” ื›ื—ื•ืœื” ื™ืจื•ืงื”:

  • ื•ื“ื ืฉืฉื ื™ ืขื•ืชืงื™ื ืฉืœ ืงื•ื“ ื”ื™ื™ืฆื•ืจ ืฉืœืš ("ื›ื—ื•ืœ" ื•"ื™ืจื•ืง") ืขื•ื‘ื“ื™ื;
  • ืœื”ืคื ื•ืช ืืช ื›ืœ ื”ืชื ื•ืขื” ืœืกื‘ื™ื‘ื” ื”ื›ื—ื•ืœื”, ื›ืœื•ืžืจ. ื›ืš ืฉื›ืชื•ื‘ื•ืช ืืชืจื™ื ืœื™ื™ืฆื•ืจ ืžืฆื‘ื™ืขื•ืช ืœืฉื;
  • ืœืคืจื•ืก ื•ืœื‘ื“ื•ืง ืืช ื›ืœ ื”ืฉื™ื ื•ื™ื™ื ื‘ืืคืœื™ืงืฆื™ื” ื‘ืกื‘ื™ื‘ื” ื™ืจื•ืงื”;
  • ื”ื—ืœืฃ ื›ืชื•ื‘ื•ืช ืืชืจื™ื ืžืกื‘ื™ื‘ื” ื›ื—ื•ืœื” ืœื™ืจื•ืงื”

ืคืจื™ืกื” ื›ื—ื•ืœ ื™ืจื•ืง ื”ื™ื ื’ื™ืฉื” ื”ืžืืคืฉืจืช ืœืš ืœื”ืฆื™ื’ ื‘ืงืœื•ืช ืชื›ื•ื ื•ืช ื—ื“ืฉื•ืช ืžื‘ืœื™ ืœื“ืื•ื’ ืœืฉื‘ื™ืจืช ื”ื™ื™ืฆื•ืจ. ื–ื” ื ื•ื‘ืข ืžื”ืขื•ื‘ื“ื” ืฉื’ื ืื ืžืฉื”ื• ืงื•ืจื”, ืืชื” ื™ื›ื•ืœ ื‘ืงืœื•ืช ืœื—ื–ื•ืจ ืื—ื•ืจื” ืœืกื‘ื™ื‘ื” ื”ืงื•ื“ืžืช ืขืœ ื™ื“ื™ ืคืฉื•ื˜ "ื”ืงืฉืช ืžืชื’".

ืœืื—ืจ ืงืจื™ืืช ื›ืœ ื”ืืžื•ืจ ืœืขื™ืœ, ืืชื” ืขืฉื•ื™ ืœืฉืื•ืœ ืืช ื”ืฉืืœื”: ืžื” ื”ืงืฉืจ ืœืืคืก ื–ืžืŸ ื”ืฉื‘ืชื” ืœืคืจื™ืกื” ื›ื—ื•ืœื” ื™ืจื•ืงื”?

ื•ื‘ื›ืŸ, ื™ืฉ ืœื”ื ืœื ืžืขื˜ ื‘ืžืฉื•ืชืฃ, ืฉื›ืŸ ืฉืžื™ืจื” ืขืœ ืฉื ื™ ืขื•ืชืงื™ื ืฉืœ ืื•ืชื” ืกื‘ื™ื‘ื” ื“ื•ืจืฉืช ืžืืžืฅ ื›ืคื•ืœ ื›ื“ื™ ืœืฉืžื•ืจ ืขืœื™ื”ื. ื–ื• ื”ืกื™ื‘ื” ืฉื›ืžื” ืงื‘ื•ืฆื•ืช ื˜ื•ืขื ื•ืช ืžืจื˜ื™ืŸ ืคืื•ืœืจ, ื‘ืฆืข ื•ืจื™ืืฆื™ื” ืฉืœ ื’ื™ืฉื” ื–ื•:

ืืคืฉืจื•ืช ื ื•ืกืคืช ื”ื™ื ืœื”ืฉืชืžืฉ ื‘ืื•ืชื• ืžืกื“ ื ืชื•ื ื™ื, ื™ืฆื™ืจืช ืžืชื’ื™ื ื›ื—ื•ืœื™ื-ื™ืจื•ืงื™ื ืขื‘ื•ืจ ืฉื›ื‘ื•ืช ื”ืื™ื ื˜ืจื ื˜ ื•ื”ื“ื•ืžื™ื™ืŸ. ื‘ื’ื™ืฉื” ื–ื•, ืžืกื“ ื”ื ืชื•ื ื™ื ื™ื›ื•ืœ ืœื”ื•ื•ืช ืœืขืชื™ื ืงืจื•ื‘ื•ืช ื‘ืขื™ื”, ื‘ืžื™ื•ื—ื“ ื›ืืฉืจ ืืชื” ืฆืจื™ืš ืœืฉื ื•ืช ืืช ื”ืกื›ื™ืžื” ืฉืœื• ื›ื“ื™ ืœืชืžื•ืš ื‘ื’ืจืกื” ื—ื“ืฉื” ืฉืœ ื”ืชื•ื›ื ื”.

ื•ื›ืืŸ ืื ื• ืžื’ื™ืขื™ื ืœื‘ืขื™ื” ื”ืขื™ืงืจื™ืช ื‘ืžืืžืจ ื–ื”. ืžืกื“ ื ืชื•ื ื™ื. ื‘ื•ืื• ื ืกืชื›ืœ ืฉื•ื‘ ืขืœ ื”ื‘ื™ื˜ื•ื™ ื”ื–ื”.

ืœื‘ืฆืข ื”ืขื‘ืจืช ืžืกื“ ื ืชื•ื ื™ื.

ื›ืขืช ืขืœื™ื›ื ืœืฉืื•ืœ ืืช ืขืฆืžื›ื ืืช ื”ืฉืืœื” - ืžื” ืื ื”ืฉื™ื ื•ื™ ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ืื™ื ื• ืชื•ืื ืœืื—ื•ืจ? ื”ืื ื”ื’ืจืกื” ื”ืจืืฉื•ื ื” ืฉืœื™ ืฉืœ ื”ืืคืœื™ืงืฆื™ื” ืœื ืชื™ืฉื‘ืจ? ืœืžืขืฉื”, ื–ื” ื‘ื“ื™ื•ืง ืžื” ืฉื™ืงืจื”...

ืœื›ืŸ, ืœืžืจื•ืช ื”ื™ืชืจื•ื ื•ืช ื”ืขืฆื•ืžื™ื ืฉืœ ืืคืก ื–ืžืŸ ื”ืฉื‘ืชื” / ืคืจื™ืกื” ื›ื—ื•ืœื” ื™ืจื•ืงื”, ื—ื‘ืจื•ืช ื ื•ื˜ื•ืช ืœื‘ืฆืข ืืช ื”ืชื”ืœื™ืš ื”ื‘ื˜ื•ื— ื”ื‘ื ื™ื•ืชืจ ืœืคืจื™ืกืช ื”ื™ื™ืฉื•ืžื™ื ืฉืœื”ืŸ:

  • ืœื”ื›ื™ืŸ ื—ื‘ื™ืœื” ืขื ื’ืจืกื” ื—ื“ืฉื” ืฉืœ ื”ืืคืœื™ืงืฆื™ื”
  • ื›ื‘ื” ืืคืœื™ืงืฆื™ื” ืคื•ืขืœืช
  • ืœื”ืคืขื™ืœ ืกืงืจื™ืคื˜ื™ื ื›ื“ื™ ืœื”ืขื‘ื™ืจ ืืช ืžืกื“ ื”ื ืชื•ื ื™ื
  • ืœืคืจื•ืก ื•ืœื”ืคืขื™ืœ ื’ืจืกื” ื—ื“ืฉื” ืฉืœ ื”ืืคืœื™ืงืฆื™ื”

ื‘ืžืืžืจ ื–ื”, ื ืคืจื˜ ื›ื™ืฆื“ ืชื•ื›ืœ ืœืขื‘ื•ื“ ืขื ืžืกื“ ื”ื ืชื•ื ื™ื ื•ื”ืงื•ื“ ืฉืœืš ื›ื“ื™ ืœื ืฆืœ ืืช ื”ื™ืชืจื•ื ื•ืช ืฉืœ ืคืจื™ืกืช ื–ืžืŸ ื”ืฉื‘ืชื” ืืคืก.

ื‘ืขื™ื•ืช ื‘ืžืกื“ ื ืชื•ื ื™ื

ืื ื™ืฉ ืœืš ืืคืœื™ืงืฆื™ื” ื—ืกืจืช ืžื“ื™ื ื” ืฉืื™ื ื” ืžืื—ืกื ืช ื ืชื•ื ื™ื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื, ืชื•ื›ืœ ืœืงื‘ืœ ืืคืก ืคืจื™ืกื” ื‘ื–ืžืŸ ื”ืฉื‘ืชื” ืžื™ื“. ืœืžืจื‘ื” ื”ืฆืขืจ, ืจื•ื‘ ื”ืชื•ื›ื ื•ืช ืฆืจื™ื›ื•ืช ืœืื—ืกืŸ ื ืชื•ื ื™ื ื‘ืžืงื•ื ื›ืœืฉื”ื•. ื–ื• ื”ืกื™ื‘ื” ืฉืืชื” ืฆืจื™ืš ืœื—ืฉื•ื‘ ืคืขืžื™ื™ื ืœืคื ื™ ื‘ื™ืฆื•ืข ืฉื™ื ื•ื™ื™ื ื›ืœืฉื”ื ื‘ืžืขื’ืœ. ืœืคื ื™ ืฉื ื™ื›ื ืก ืœืคืจื˜ื™ื ื›ื™ืฆื“ ืœืฉื ื•ืช ืืช ื”ืกื›ื™ืžื” ื›ืš ืฉืชืชืืคืฉืจ ืคืจื™ืกื” ืœืœื ื–ืžืŸ ื”ืฉื‘ืชื”, ื‘ื•ืื• ื ืชืžืงื“ ืชื—ื™ืœื” ื‘ืกื›ื™ืžืช ื ื™ื”ื•ืœ ื”ื’ืจืกืื•ืช.

ืขืจื›ืช ื’ื™ืจืกืื•ืช

ื‘ืžืืžืจ ื–ื” ื ืฉืชืžืฉ ื“ืจืš ื˜ื™ืกื” ื›ื›ืœื™ ื‘ืงืจืช ื’ืจืกืื•ืช (ืžืฉื•ืขืจ. ืชืจื’ื•ื: ืื ื—ื ื• ืžื“ื‘ืจื™ื ืขืœ ื”ืขื‘ืจืช ืžืกื“ื™ ื ืชื•ื ื™ื). ื‘ืื•ืคืŸ ื˜ื‘ืขื™, ื ื›ืชื•ื‘ ื’ื ืืคืœื™ืงืฆื™ื™ืช Spring Boot ืฉื™ืฉ ืœื” ืชืžื™ื›ื” ืžื•ื‘ื ื™ืช ื‘-Flyway ื•ืชื‘ืฆืข ื”ืขื‘ืจืช ืกื›ื™ืžื” ืชื•ืš ื”ื’ื“ืจืช ื”ืงืฉืจ ื”ืืคืœื™ืงืฆื™ื”. ื‘ืขืช ืฉื™ืžื•ืฉ ื‘-Flyway, ืืชื” ื™ื›ื•ืœ ืœืื—ืกืŸ ืกืงืจื™ืคื˜ื™ื ืœื”ืขื‘ืจื” ื‘ืชื™ืงื™ื™ืช ื”ืคืจื•ื™ืงื˜ื™ื ืฉืœืš (ื›ื‘ืจื™ืจืช ืžื—ื“ืœ ื‘ classpath:db/migration). ื›ืืŸ ืืชื” ื™ื›ื•ืœ ืœืจืื•ืช ื“ื•ื’ืžื” ืœืงื‘ืฆื™ ื”ื’ื™ืจื” ื›ืืœื”

โ””โ”€โ”€ db
 โ””โ”€โ”€ migration
     โ”œโ”€โ”€ V1__init.sql
     โ”œโ”€โ”€ V2__Add_surname.sql
     โ”œโ”€โ”€ V3__Final_migration.sql
     โ””โ”€โ”€ V4__Remove_lastname.sql

ื‘ื“ื•ื’ืžื” ื–ื• ืื ื• ืจื•ืื™ื 4 ืกืงืจื™ืคื˜ื™ื ืœืžื™ื’ืจืฆื™ื”, ืฉืื ืœื ื‘ื•ืฆืขื• ืงื•ื“ื ืœื›ืŸ, ื™ื‘ื•ืฆืขื• ื‘ื–ื” ืื—ืจ ื–ื” ืขื ื”ืคืขืœืช ื”ืืคืœื™ืงืฆื™ื”. ื‘ื•ืื• ื ืกืชื›ืœ ืขืœ ืื—ื“ ื”ืงื‘ืฆื™ื (V1__init.sql) ืœื“ื•ื’ืžื.

CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);

insert into PERSON (first_name, last_name) values ('Dave', 'Syer');

ื”ื›ืœ ืžื•ื‘ืŸ ืžืืœื™ื• ืœื—ืœื•ื˜ื™ืŸ: ืืชื” ื™ื›ื•ืœ ืœื”ืฉืชืžืฉ ื‘-SQL ื›ื“ื™ ืœื”ื’ื“ื™ืจ ื›ื™ืฆื“ ื™ืฉ ืœืฉื ื•ืช ืืช ืžืกื“ ื”ื ืชื•ื ื™ื ืฉืœืš. ืœืžื™ื“ืข ื ื•ืกืฃ ืขืœ Spring Boot ื•-Flyway, ื‘ื“ื•ืง Spring Boot Docs.

ืขืœ ื™ื“ื™ ืฉื™ืžื•ืฉ ื‘ื›ืœื™ ื‘ืงืจืช ืžืงื•ืจ ืขื Spring Boot, ืืชื” ืžืงื‘ืœ 2 ื™ืชืจื•ื ื•ืช ื’ื“ื•ืœื™ื:

  • ืืชื” ืžืคืจื™ื“ ื‘ื™ืŸ ืฉื™ื ื•ื™ื™ื ื‘ื‘ืกื™ืก ื”ื ืชื•ื ื™ื ืœื‘ื™ืŸ ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื“
  • ื”ืขื‘ืจืช ืžืกื“ื™ ื ืชื•ื ื™ื ืžืชืจื—ืฉืช ื™ื—ื“ ืขื ื”ืฉืงืช ื”ืืคืœื™ืงืฆื™ื” ืฉืœืš, ื›ืœื•ืžืจ. ืชื”ืœื™ืš ื”ืคืจื™ืกื” ืฉืœืš ืžืคื•ืฉื˜

ืคืชืจื•ืŸ ื‘ืขื™ื•ืช ื‘ื‘ืกื™ืก ื”ื ืชื•ื ื™ื

ื‘ื—ืœืง ื”ื‘ื ืฉืœ ื”ืžืืžืจ, ื ืชืžืงื“ ื‘ื”ืกืชื›ืœื•ืช ืขืœ ืฉืชื™ ื’ื™ืฉื•ืช ืœืฉื™ื ื•ื™ื™ื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื.

  • ืื™ ื”ืชืืžื” ืœืื—ื•ืจ
  • ืชืื™ืžื•ืช ืœืื—ื•ืจ

ื”ืจืืฉื•ืŸ ื™ื™ื—ืฉื‘ ื›ืื–ื”ืจื” ืฉืื™ืŸ ืœื‘ืฆืข ืคืจื™ืกืช ื–ืžืŸ ื”ืฉื‘ืชื” ืืคืก ืœืœื ื”ื›ื ื” ืžื•ืงื“ืžืช... ื”ืฉื ื™ ืžืฆื™ืข ืคืชืจื•ืŸ ื›ื™ืฆื“ ื ื™ืชืŸ ืœื‘ืฆืข ืคืจื™ืกื” ืœืœื ื”ืฉื‘ืชื” ื•ื‘ืžืงื‘ื™ืœ ืœืฉืžื•ืจ ืขืœ ืชืื™ืžื•ืช ืœืื—ื•ืจ.

ื”ืคืจื•ื™ืงื˜ ืฉืœื ื• ืขืœื™ื• ื ืขื‘ื•ื“ ื™ื”ื™ื” ื™ื™ืฉื•ื ืคืฉื•ื˜ Spring Boot Flyway ืฉื™ืฉ ืœื• Person ั first_name ะธ last_name ื‘ืžืกื“ ื”ื ืชื•ื ื™ื (ืžืฉื•ืขืจ. ืชึดืจื’ื•ึผื: Person ื”ื•ื ืฉื•ืœื—ืŸ ื• ื•irst_name ะธ last_name - ืืœื• ื”ืฉื“ื•ืช ืฉื‘ื•). ืื ื—ื ื• ืจื•ืฆื™ื ืœืฉื ื•ืช ืืช ื”ืฉื last_name ะฒ surname.

ื”ื ื—ื•ืช

ืœืคื ื™ ืฉื ื™ื›ื ืก ืœืคืจื˜ื™ื, ื™ืฉ ื›ืžื” ื”ื ื—ื•ืช ืฉืขืœื™ื ื• ืœืขืฉื•ืช ืœื’ื‘ื™ ื”ื™ื™ืฉื•ืžื™ื ืฉืœื ื•. ื”ืชื•ืฆืื” ื”ืขื™ืงืจื™ืช ืฉืื ื• ืจื•ืฆื™ื ืœื”ืฉื™ื’ ืชื”ื™ื” ืชื”ืœื™ืš ืคืฉื•ื˜ ืœืžื“ื™.

ื”ืคืชืง. ืขืกืงื™ PRO-TIP. ืคื™ืฉื•ื˜ ืชื”ืœื™ื›ื™ื ื™ื›ื•ืœ ืœื—ืกื•ืš ืœืš ื”ืจื‘ื” ื›ืกืฃ ืขืœ ืชืžื™ื›ื” (ื›ื›ืœ ืฉื™ืฉ ืœืš ื™ื•ืชืจ ืื ืฉื™ื ืฉืขื•ื‘ื“ื™ื ื‘ื—ื‘ืจื” ืฉืœืš, ื›ืš ืชื•ื›ืœ ืœื—ืกื•ืš ื™ื•ืชืจ ื›ืกืฃ)!

ืื™ืŸ ืฆื•ืจืš ืœื”ื—ื–ื™ืจ ืืช ืžืกื“ ื”ื ืชื•ื ื™ื ืœืื—ื•ืจ

ื–ื” ืžืคืฉื˜ ืืช ืชื”ืœื™ืš ื”ืคืจื™ืกื” (ื—ืœืง ืžื”ื—ื–ืจื•ืช ืžืกื“ ื ืชื•ื ื™ื ื”ืŸ ื›ืžืขื˜ ื‘ืœืชื™ ืืคืฉืจื™ื•ืช, ื›ื’ื•ืŸ ื‘ื™ื˜ื•ืœ ืžื—ื™ืงื”). ืื ื• ืžืขื“ื™ืคื™ื ืœื”ื—ื–ื™ืจ ืจืง ืืคืœื™ืงืฆื™ื•ืช. ื‘ื“ืจืš ื–ื•, ื’ื ืื ื™ืฉ ืœืš ืžืกื“ื™ ื ืชื•ื ื™ื ืฉื•ื ื™ื (ืœื“ื•ื’ืžื”, SQL ื•-NoSQL), ืฆื™ื ื•ืจ ื”ืคืจื™ืกื” ืฉืœืš ื™ื™ืจืื” ื–ื”ื”.

ื–ื” ื—ื™ื™ื‘ ืœื”ื™ื•ืช ืชืžื™ื“ ืืคืฉืจื™ ืœื”ื—ื–ื™ืจ ืืช ื”ืืคืœื™ืงืฆื™ื” ืœืื—ื•ืจ ื’ืจืกื” ืื—ืช ืื—ื•ืจื” (ืœื ื™ื•ืชืจ)

ื”ื—ื–ืจื” ืœืื—ื•ืจ ืฆืจื™ื›ื” ืœื”ื™ืขืฉื•ืช ืจืง ื›ืืฉืจ ื™ืฉ ืฆื•ืจืš. ืื ื™ืฉ ื‘ืื’ ื‘ื’ืจืกื” ื”ื ื•ื›ื—ื™ืช ืฉืœื ื ื™ืชืŸ ืœืชืงืŸ ื‘ืงืœื•ืช, ืื ื—ื ื• ืืžื•ืจื™ื ืœื”ื™ื•ืช ืžืกื•ื’ืœื™ื ืœื—ื–ื•ืจ ืœื’ืจืกื” ื”ืื—ืจื•ื ื” ืฉืขื•ื‘ื“ืช. ืื ื• ืžื ื™ื—ื™ื ืฉื’ืจืกืช ื”ืขื‘ื•ื“ื” ื”ืื—ืจื•ื ื” ื”ื–ื• ื”ื™ื ื”ืงื•ื“ืžืช. ืฉืžื™ืจื” ืขืœ ืชืื™ืžื•ืช ืงื•ื“ ื•ืžืกื“ ื ืชื•ื ื™ื ืขื‘ื•ืจ ื™ื•ืชืจ ืžืฉื’ืจื” ืื—ืช ืชื”ื™ื” ืงืฉื” ื•ื™ืงืจื” ื‘ืžื™ื•ื—ื“.

ื”ืคืชืง. ืœืงืจื™ืื•ืช ืจื‘ื” ื™ื•ืชืจ, ื‘ืžืืžืจ ื–ื” ื ืฉื ื” ืืช ื”ื’ืจืกื” ื”ืขื™ืงืจื™ืช ืฉืœ ื”ืืคืœื™ืงืฆื™ื”.

ืฉืœื‘ 1: ืžืฆื‘ ื”ืชื—ืœืชื™

ื’ืจืกืช ื”ืืคืœื™ืงืฆื™ื”: 1.0.0
ื’ืจืกืช DB: v1

ื”ืขืจื”

ื–ื” ื™ื”ื™ื” ื”ืžืฆื‘ ื”ืจืืฉื•ื ื™ ืฉืœ ื”ื‘ืงืฉื”.

ืฉื™ื ื•ื™ื™ื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื

DB ืžื›ื™ืœ last_name.

CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);

insert into PERSON (first_name, last_name) values ('Dave', 'Syer');

ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื“

ื”ืืคืœื™ืงืฆื™ื” ืžืื—ืกื ืช ื ืชื•ื ื™ ืื“ื ื‘ last_name:

/*
 * Copyright 2012-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package sample.flyway;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Person {
    @Id
    @GeneratedValue
    private Long id;
    private String firstName;
    private String lastName;

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String lastname) {
        this.lastName = lastname;
    }

    @Override
    public String toString() {
        return "Person [firstName=" + this.firstName + ", lastName=" + this.lastName
                + "]";
    }
}

ืฉื™ื ื•ื™ ืฉื ื”ืขืžื•ื“ื” ืœื ืชื•ืื ืœืื—ื•ืจ

ื‘ื•ืื• ื ืกืชื›ืœ ืขืœ ื“ื•ื’ืžื” ื›ื™ืฆื“ ืœืฉื ื•ืช ืฉื ืขืžื•ื“ื”:

ืชืฉื•ืžืช ื”ืœื‘. ื”ื“ื•ื’ืžื” ื”ื‘ืื” ืชืฉื‘ื•ืจ ื“ื‘ืจื™ื ื‘ื›ื•ื•ื ื”. ืื ื• ืžืจืื™ื ื–ืืช ื›ื“ื™ ืœื”ื“ื’ื™ื ืืช ื‘ืขื™ื™ืช ืชืื™ืžื•ืช ืžืกื“ื™ ื”ื ืชื•ื ื™ื.

ื’ืจืกืช ื”ืืคืœื™ืงืฆื™ื”: 2.0.0.BAD

ื’ืจืกืช DB: v2bad

ื”ืขืจื”

ื”ืฉื™ื ื•ื™ื™ื ื”ื ื•ื›ื—ื™ื™ื ืื™ื ื ืžืืคืฉืจื™ื ืœื ื• ืœื”ืคืขื™ืœ ืฉื ื™ ืžื•ืคืขื™ื (ื™ืฉืŸ ื•ื—ื“ืฉ) ื‘ื• ื–ืžื ื™ืช. ืœืคื™ื›ืš, ืืคืก ืคืจื™ืกืช ื–ืžืŸ ื”ืฉื‘ืชื” ืชื”ื™ื” ืงืฉื” ืœื”ืฉื’ื” (ืื ืœื•ืงื—ื™ื ื‘ื—ืฉื‘ื•ืŸ ื”ื ื—ื•ืช, ื–ื” ืœืžืขืฉื” ื‘ืœืชื™ ืืคืฉืจื™).

ื‘ื“ื™ืงืช A/B

ื”ืžืฆื‘ ื”ื ื•ื›ื—ื™ ื”ื•ื ืฉื™ืฉ ืœื ื• ื’ืจืกืช ืืคืœื™ืงืฆื™ื” 1.0.0, ืคืจื•ืก ื‘ื™ื™ืฆื•ืจ, ื•ืžืกื“ ื ืชื•ื ื™ื v1. ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœืคืจื•ืก ืžื•ืคืข ืฉื ื™ ืฉืœ ื”ืืคืœื™ืงืฆื™ื”, ื’ืจืกื” 2.0.0.BAD, ื•ืขื“ื›ืŸ ืืช ืžืกื“ ื”ื ืชื•ื ื™ื ืœ v2bad.

ืฉืœื‘ื™ื:

  1. ื ืคืจืก ืžื•ืคืข ื—ื“ืฉ ืฉืœ ืืคืœื™ืงืฆื™ื™ืช ื”ื’ืจืกื” 2.0.0.BADืืฉืจ ืžืขื“ื›ื ืช ืืช ืžืกื“ ื”ื ืชื•ื ื™ื ืœ v2bad
  2. ื‘ืžืกื“ ื”ื ืชื•ื ื™ื v2bad ืขืžื•ื“ื” last_name ื›ื‘ืจ ืœื ืงื™ื™ื - ื”ื•ื ืฉื•ื ื” ืœ surname
  3. ืขื“ื›ื•ืŸ ืžืกื“ ื”ื ืชื•ื ื™ื ื•ื”ื™ื™ืฉื•ื ื”ืฆืœื™ื— ื•ื—ืœืง ืžื”ืžื•ืคืขื™ื ืคื•ืขืœื™ื 1.0.0, ืื—ืจื™ื - ื‘ 2.0.0.BAD. ื”ื›ืœ ืžื—ื•ื‘ืจ ืœืžืกื“ ื”ื ืชื•ื ื™ื v2bad
  4. ื›ืœ ื”ืžื•ืคืขื™ื ืฉืœ ื”ื’ืจืกื” 1.0.0 ื™ืชื—ื™ืœื• ืœื–ืจื•ืง ืฉื’ื™ืื•ืช ื›ื™ ื”ื ื™ื ืกื• ืœื”ื›ื ื™ืก ื ืชื•ื ื™ื ืœืขืžื•ื“ื” last_nameืฉืœื ืงื™ื™ื ื™ื•ืชืจ
  5. ื›ืœ ื”ืžื•ืคืขื™ื ืฉืœ ื”ื’ืจืกื” 2.0.0.BAD ื™ืขื‘ื•ื“ ืœืœื ื‘ืขื™ื•ืช

ื›ืคื™ ืฉืืชื” ื™ื›ื•ืœ ืœืจืื•ืช, ืื ื ื‘ืฆืข ืฉื™ื ื•ื™ื™ื ืœื ืชื•ืืžื™ื ืœืื—ื•ืจ ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ื•ื‘ื™ื™ืฉื•ื, ื‘ื“ื™ืงืช A/B ื”ื™ื ื‘ืœืชื™ ืืคืฉืจื™ืช.

ื”ื—ื–ืจืช ืืคืœื™ืงืฆื™ื” ืœืื—ื•ืจ

ื‘ื•ืื• ื ื ื™ื— ืฉืื—ืจื™ ืฉื ื™ืกื™ื ื• ืœื‘ืฆืข ืคืจื™ืกืช A/B (ืžืฉื•ืขืจ. ืœื›ืœ.: ื”ืžื—ื‘ืจ ื›ื ืจืื” ื”ืชื›ื•ื•ืŸ ืœื‘ื“ื™ืงืช A/B ื›ืืŸ) ื”ื—ืœื˜ื ื• ืฉืขืœื™ื ื• ืœื”ื—ื–ื™ืจ ืืช ื”ืืคืœื™ืงืฆื™ื” ืœืื—ื•ืจ ืœื’ืจืกื” 1.0.0. ื ื ื™ื— ืฉืื ื—ื ื• ืœื ืจื•ืฆื™ื ืœื”ื—ื–ื™ืจ ืืช ืžืกื“ ื”ื ืชื•ื ื™ื ืœืื—ื•ืจ.

ืฉืœื‘ื™ื:

  1. ืื ื• ืขื•ืฆืจื™ื ืืช ืžื•ืคืข ืืคืœื™ืงืฆื™ื™ืช ื”ื’ืจืกื” 2.0.0.BAD
  2. ืžืกื“ ื”ื ืชื•ื ื™ื ืขื“ื™ื™ืŸ v2bad
  3. ืžืื– ื”ื’ืจืกื” 1.0.0 ืœื ืžื‘ื™ืŸ ืžื” ื–ื” surname, ื ืจืื” ืฉื’ื™ืื•ืช
  4. ื”ื’ื™ื”ื ื•ื ื”ืฉืชื—ืจืจ, ืื ื—ื ื• ืœื ื™ื›ื•ืœื™ื ืœื—ื–ื•ืจ ื™ื•ืชืจ

ื›ืคื™ ืฉืืชื” ื™ื›ื•ืœ ืœืจืื•ืช, ืื ื ื‘ืฆืข ืฉื™ื ื•ื™ื™ื ืœื ืชื•ืืžื™ื ืœืื—ื•ืจ ื‘ืžืกื“ ื”ื ืชื•ื ื™ื ื•ื‘ื™ื™ืฉื•ื, ืœื ื ื•ื›ืœ ืœื—ื–ื•ืจ ืœื’ืจืกื” ื”ืงื•ื“ืžืช.

ื™ื•ืžื ื™ ื‘ื™ืฆื•ืข ืกืงืจื™ืคื˜

Backward incompatible scenario:

01) Run 1.0.0
02) Wait for the app (1.0.0) to boot
03) Generate a person by calling POST localhost:9991/person to version 1.0.0
04) Run 2.0.0.BAD
05) Wait for the app (2.0.0.BAD) to boot
06) Generate a person by calling POST localhost:9991/person to version 1.0.0 <-- this should fail
07) Generate a person by calling POST localhost:9992/person to version 2.0.0.BAD <-- this should pass

Starting app in version 1.0.0
Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:

{"firstName":"b73f639f-e176-4463-bf26-1135aace2f57","lastName":"b73f639f-e176-4463-bf26-1135aace2f57"}

Starting app in version 2.0.0.BAD
Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:

curl: (22) The requested URL returned error: 500 Internal Server Error

Generate a person in version 2.0.0.BAD
Sending a post to 127.0.0.1:9995/person. This is the response:

{"firstName":"e156be2e-06b6-4730-9c43-6e14cfcda125","surname":"e156be2e-06b6-4730-9c43-6e14cfcda125"}

ืฉื™ื ื•ื™ื™ื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื

ืกืงืจื™ืคื˜ ื”ื’ื™ืจื” ืฉืžืฉื ื” ืฉื last_name ะฒ surname

ืžืงื•ืจ ืชืกืจื™ื˜ Flyway:

CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);

insert into PERSON (first_name, last_name) values ('Dave', 'Syer');

ืกืงืจื™ืคื˜ ืฉืžืฉื ื” ืฉื last_name.

-- This change is backward incompatible - you can't do A/B testing
ALTER TABLE PERSON CHANGE last_name surname VARCHAR;

ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื“

ืฉื™ื ื™ื ื• ืืช ืฉื ื”ืฉื“ื” lastName ืขืœ surname.

ืฉื™ื ื•ื™ ืฉื ืฉืœ ืขืžื•ื“ื” ื‘ืื•ืคืŸ ืชื•ืื ืœืื—ื•ืจ

ื–ื”ื• ื”ืžืฆื‘ ื”ื ืคื•ืฅ ื‘ื™ื•ืชืจ ืฉืื ื• ืขืœื•ืœื™ื ืœื”ื™ืชืงืœ ื‘ื•. ืื ื—ื ื• ืฆืจื™ื›ื™ื ืœืขืฉื•ืช ืฉื™ื ื•ื™ื™ื ืœื ืชื•ืืžื™ื ืœืื—ื•ืจ. ื›ื‘ืจ ื”ื•ื›ื—ื ื• ืฉืœืคืจื™ืกื” ื‘ื–ืžืŸ ื”ืฉื‘ืชื” ืืคืก, ืื ื—ื ื• ืœื ืฆืจื™ื›ื™ื ืคืฉื•ื˜ ืœื”ื—ื™ืœ ื”ืขื‘ืจืช ืžืกื“ ื ืชื•ื ื™ื ืœืœื ืฉืœื‘ื™ื ื ื•ืกืคื™ื. ื‘ื—ืœืง ื–ื” ืฉืœ ื”ืžืืžืจ, ื ื‘ืฆืข 3 ืคืจื™ืกื•ืช ืฉืœ ื”ืืคืœื™ืงืฆื™ื” ื™ื—ื“ ืขื ื”ืขื‘ืจื•ืช ืžืกื“ ื ืชื•ื ื™ื ื›ื“ื™ ืœื”ืฉื™ื’ ืืช ื”ืชื•ืฆืื” ื”ืจืฆื•ื™ื” ืชื•ืš ืฉืžื™ืจื” ืขืœ ืชืื™ืžื•ืช ืœืื—ื•ืจ.

ื”ืคืชืง. ื ื–ื›ื™ืจ ืฉื™ืฉ ืœื ื• ืžืกื“ ื ืชื•ื ื™ื ืฉืœ ื’ืจืกืื•ืช v1. ื”ื•ื ืžื›ื™ืœ ืขืžื•ื“ื•ืช first_name ะธ last_name. ืื ื—ื ื• ื—ื™ื™ื‘ื™ื ืœืฉื ื•ืช last_name ืขืœ surname. ื™ืฉ ืœื ื• ื’ื ื’ืจืกืช ืืคืœื™ืงืฆื™ื” 1.0.0, ืฉืขื“ื™ื™ืŸ ืœื ื ืขืฉื” ื‘ื• ืฉื™ืžื•ืฉ surname.

ืฉืœื‘ 2: ื”ื•ืกืฃ ืฉื ืžืฉืคื—ื”

ื’ืจืกืช ื”ืืคืœื™ืงืฆื™ื”: 2.0.0
ื’ืจืกืช DB: v2

ื”ืขืจื”

ืขืœ ื™ื“ื™ ื”ื•ืกืคืช ืขืžื•ื“ื” ื—ื“ืฉื” ื•ื”ืขืชืงืช ืชื•ื›ื ื”, ืื ื• ื™ื•ืฆืจื™ื ืฉื™ื ื•ื™ื™ื ื‘ืžืกื“ ื ืชื•ื ื™ื ืชื•ืืžื™ื ืœืื—ื•ืจ. ื™ื—ื“ ืขื ื–ืืช, ืื ื ื—ื–ื™ืจ ืืช ื”-JAR ืœืื—ื•ืจ ืื• ืฉ-JAR ื™ืฉืŸ ืคื•ืขืœ, ื”ื•ื ืœื ื™ืฉื‘ืจ ื‘ืžื”ืœืš ื”ื‘ื™ืฆื•ืข.

ืื ื—ื ื• ืžืฉื™ืงื™ื ื’ืจืกื” ื—ื“ืฉื”

ืฉืœื‘ื™ื:

  1. ืœื‘ืฆืข ื”ืขื‘ืจืช ืžืกื“ ื ืชื•ื ื™ื ื›ื“ื™ ืœื™ืฆื•ืจ ืขืžื•ื“ื” ื—ื“ืฉื” surname. ืขื›ืฉื™ื• ื’ืจืกืช ื”-DB ืฉืœืš v2
  2. ื”ืขืชืง ื ืชื•ื ื™ื ืž last_name ะฒ surname. ืฉื™ื ืœื‘ืฉืื ื™ืฉ ืœืš ื”ืจื‘ื” ืžื”ื ืชื•ื ื™ื ื”ืืœื”, ืขืœื™ืš ืœืฉืงื•ืœ ื”ืขื‘ืจืช ืืฆื•ื•ื”!
  3. ื›ืชื•ื‘ ืืช ื”ืงื•ื“ ื‘ืžืงื•ื ืฉื‘ื• ื”ื ืžืฉืžืฉื™ื ืฉื ื™ื”ื ะธ ื—ื“ืฉื• - ัั‚ะฐั€ั‹ะน ื˜ื•ืจ. ืขื›ืฉื™ื• ื’ืจืกืช ื”ืืคืœื™ืงืฆื™ื” ืฉืœืš 2.0.0
  4. ืงืจื ืืช ื”ืขืจืš ืžื”ืขืžื•ื“ื” surname, ืื ื–ื” ืœื null, ืื• ืž-last_nameืื surname ืœื ืžื•ื’ื“ืจ. ืืชื” ื™ื›ื•ืœ ืœืžื—ื•ืง getLastName() ืžื”ืงื•ื“, ืžื›ื™ื•ื•ืŸ ืฉื”ื•ื ื™ืคืœื•ื˜ null ื‘ืขืช ื‘ื™ื˜ื•ืœ ื”ื™ื™ืฉื•ื ืฉืœืš ืž 3.0.0 ะดะพ 2.0.0.

ืื ืืชื” ืžืฉืชืžืฉ ื‘-Spring Boot Flyway, ืฉื ื™ ื”ืฉืœื‘ื™ื ื”ืืœื” ื™ื‘ื•ืฆืขื• ื‘ืžื”ืœืš ืืชื—ื•ืœ ื”ื’ืจืกื” 2.0.0 ื™ื™ืฉื•ืžื™ื. ืื ืืชื” ืžืคืขื™ืœ ืืช ื›ืœื™ ื ื™ื”ื•ืœ ื”ื’ืจืกื” ืฉืœ ืžืกื“ ื”ื ืชื•ื ื™ื ื‘ืื•ืคืŸ ื™ื“ื ื™, ืชืฆื˜ืจืš ืœืขืฉื•ืช ืฉื ื™ ื“ื‘ืจื™ื ืฉื•ื ื™ื ื›ื“ื™ ืœืขืฉื•ืช ื–ืืช (ืชื—ื™ืœื” ืขื“ื›ืŸ ืืช ื’ืจืกืช ื”-db ื™ื“ื ื™ืช ื•ืœืื—ืจ ืžื›ืŸ ืœืคืจื•ืก ืืช ื”ื™ื™ืฉื•ื ื”ื—ื“ืฉ).

ื–ื” ื—ืฉื•ื‘. ื–ื›ื•ืจ ืฉื”ืขืžื•ื“ื” ื”ื—ื“ืฉื” ืฉื ื•ืฆืจื” ืœื ืฆืจื™ืš ืœื”ื™ื•ืช ืœื ืจื™ืง. ืื ืชื‘ืฆืข ื”ื—ื–ืจื” ืœืื—ื•ืจ, ื”ืืคืœื™ืงืฆื™ื” ื”ื™ืฉื ื” ืœื ื™ื•ื“ืขืช ืขืœ ื”ืขืžื•ื“ื” ื”ื—ื“ืฉื” ื•ืœื ืชืชืงื™ืŸ ืื•ืชื” ื‘ืžื”ืœืš Insert. ืื‘ืœ ืื ืชื•ืกื™ืฃ ืืช ื”ืื™ืœื•ืฅ ื”ื–ื” ื•ื”-db ืฉืœืš ื™ื”ื™ื” v2, ื–ื” ื™ื“ืจื•ืฉ ื”ื’ื“ืจืช ื”ืขืจืš ืฉืœ ื”ืขืžื•ื“ื” ื”ื—ื“ืฉื”. ืžื” ืฉื™ื•ื‘ื™ืœ ืœื”ืคืจื•ืช ื”ื’ื‘ืœื•ืช.

ื–ื” ื—ืฉื•ื‘. ื›ื“ืื™ ืœื”ืกื™ืจ ืืช ื”ืฉื™ื˜ื” getLastName(), ื›ื™ ื‘ื’ืจืกื” 3.0.0 ืื™ืŸ ืžื•ืฉื’ ืฉืœ ืขืžื•ื“ื” ื‘ืงื•ื“ last_name. ื”ืžืฉืžืขื•ืช ื”ื™ื ืฉ-null ื™ื•ื’ื“ืจ ืฉื. ืืชื” ื™ื›ื•ืœ ืœืขื–ื•ื‘ ืืช ื”ืฉื™ื˜ื” ื•ืœื”ื•ืกื™ืฃ ืฆ'ืงื™ื ืขื‘ื•ืจ null, ืื‘ืœ ืคืชืจื•ืŸ ื”ืจื‘ื” ื™ื•ืชืจ ื˜ื•ื‘ ื™ื”ื™ื” ืœื•ื•ื“ื ืืช ื–ื” ื‘ื”ื™ื’ื™ื•ืŸ getSurname() ื‘ื—ืจืช ืืช ื”ืขืจืš ื”ื ื›ื•ืŸ ืฉืื™ื ื• ืืคืก.

ื‘ื“ื™ืงืช A/B

ื”ืžืฆื‘ ื”ื ื•ื›ื—ื™ ื”ื•ื ืฉื™ืฉ ืœื ื• ื’ืจืกืช ืืคืœื™ืงืฆื™ื” 1.0.0, ืคืจื•ืก ืขืœ ื”ื™ื™ืฆื•ืจ, ื•ืžืกื“ ื”ื ืชื•ื ื™ื ื‘ v1. ืขืœื™ื ื• ืœืคืจื•ืก ืžื•ืคืข ืฉื ื™ ืฉืœ ืืคืœื™ืงืฆื™ื™ืช ื”ื’ืจืกื” 2.0.0ืืฉืจ ื™ืขื“ื›ืŸ ืืช ืžืกื“ ื”ื ืชื•ื ื™ื ืœ v2.

ืฉืœื‘ื™ื:

  1. ื ืคืจืก ืžื•ืคืข ื—ื“ืฉ ืฉืœ ืืคืœื™ืงืฆื™ื™ืช ื”ื’ืจืกื” 2.0.0ืืฉืจ ืžืขื“ื›ื ืช ืืช ืžืกื“ ื”ื ืชื•ื ื™ื ืœ v2
  2. ื‘ื™ื ืชื™ื™ื, ื—ืœืง ืžื”ื‘ืงืฉื•ืช ืขื•ื‘ื“ื• ืขืœ ื™ื“ื™ ืžื•ืคืขื™ ื’ืจืกื” 1.0.0
  3. ื”ืขื“ื›ื•ืŸ ื”ืฆืœื™ื— ื•ื™ืฉ ืœืš ืžื•ืคืขื™ื ืžืจื•ื‘ื™ื ืฉืœ ื™ื™ืฉื•ื ื”ื’ืจืกื” 1.0.0 ื•ื’ืจืกืื•ืช ืื—ืจื•ืช 2.0.0. ื›ื•ืœื ืžืชืงืฉืจื™ื ืขื ืžืกื“ ื”ื ืชื•ื ื™ื ื‘ v2
  4. ื’ืจืกื” 1.0.0 ืื™ื ื• ืžืฉืชืžืฉ ื‘ืขืžื•ื“ืช ืฉื ื”ืžืฉืคื—ื” ื‘ืžืกื“ ื”ื ืชื•ื ื™ื, ืืœื ื‘ื’ืจืกื” 2.0.0 ืฉื™ืžื•ืฉื™ื. ื”ื ืื™ื ื ืžืคืจื™ืขื™ื ื–ื” ืœื–ื”, ื•ืœื ืืžื•ืจื•ืช ืœื”ื™ื•ืช ืฉื’ื™ืื•ืช.
  5. ื’ืจืกื” 2.0.0 ืžืื—ืกืŸ ื ืชื•ื ื™ื ื‘ืขืžื•ื“ื” ื”ื™ืฉื ื” ื•ื”ื—ื“ืฉื”, ื•ืžื‘ื˜ื™ื— ืชืื™ืžื•ืช ืœืื—ื•ืจ

ื–ื” ื—ืฉื•ื‘. ืื ื™ืฉ ืœืš ืฉืื™ืœืชื•ืช ืฉืกื•ืคืจื•ืช ืคืจื™ื˜ื™ื ืขืœ ืกืžืš ืขืจื›ื™ื ืžื”ืขืžื•ื“ื” ื”ื™ืฉื ื”/ื—ื“ืฉื”, ืขืœื™ืš ืœื–ื›ื•ืจ ืฉื›ืขืช ื™ืฉ ืœืš ืขืจื›ื™ื ื›ืคื•ืœื™ื (ืกื‘ื™ืจ ืœื”ื ื™ื— ืฉื”ื ืขื“ื™ื™ืŸ ืขื•ื‘ืจื™ื). ืœื“ื•ื’ืžื”, ืื ื‘ืจืฆื•ื ืš ืœืกืคื•ืจ ืืช ืžืกืคืจ ื”ืžืฉืชืžืฉื™ื ืฉืฉื ืžืฉืคื—ืชื (ืื™ืš ืฉืชืงืจื ื”ืขืžื•ื“ื”) ื”ืชื—ื™ืœ ื‘ืื•ืช A, ื•ืื– ืขื“ ืœื”ืฉืœืžืช ื”ืขื‘ืจืช ื”ื ืชื•ื ื™ื (old โ†’ new ืขืžื•ื“ื”) ื™ื™ืชื›ืŸ ืฉื™ืฉ ืœืš ื ืชื•ื ื™ื ืœื ืขืงื‘ื™ื™ื ืื ืชื‘ืฆืข ืฉืื™ืœืชื” ื‘ืขืžื•ื“ื” ื—ื“ืฉื”.

ื”ื—ื–ืจืช ืืคืœื™ืงืฆื™ื” ืœืื—ื•ืจ

ืขื›ืฉื™ื• ื™ืฉ ืœื ื• ื’ืจืกืช ืืคืœื™ืงืฆื™ื” 2.0.0 ื•ืžืกื“ ื ืชื•ื ื™ื ื‘ v2.

ืฉืœื‘ื™ื:

  1. ื”ื—ื–ืจ ืืช ื”ืืคืœื™ืงืฆื™ื” ืฉืœืš ืœื’ืจืกื” 1.0.0.
  2. ื’ืจืกื” 1.0.0 ืื™ื ื• ืžืฉืชืžืฉ ื‘ืขืžื•ื“ื” ื‘ืžืกื“ ื”ื ืชื•ื ื™ื surname, ื›ืš ืฉื”ื—ื–ืจื” ืœืื—ื•ืจ ืืžื•ืจื” ืœื”ืฆืœื™ื—

ืฉื™ื ื•ื™ื™ื ื‘-DB

ืžืกื“ ื”ื ืชื•ื ื™ื ืžื›ื™ืœ ืขืžื•ื“ื” ื‘ืฉื last_name.

ืชืกืจื™ื˜ ืžืงื•ืจ ืฉืœ ืžืกืœื•ืœ ืคืœื™ื™ื”:

CREATE TABLE PERSON (
id BIGINT GENERATED BY DEFAULT AS IDENTITY,
first_name varchar(255) not null,
last_name varchar(255) not null
);

insert into PERSON (first_name, last_name) values ('Dave', 'Syer');

ื”ื•ืกืฃ ืกืงืจื™ืคื˜ surname.

ืชืฉื•ืžืช ื”ืœื‘. ื–ื›ื•ืจ ืฉืื™ื ืš ื™ื›ื•ืœ ืœื”ื•ืกื™ืฃ ืฉื•ื ืื™ืœื•ืฆื™ NOT NULL ืœืขืžื•ื“ื” ืฉืืชื” ืžื•ืกื™ืฃ. ืื ืชื—ื–ื™ืจ ืืช ื”-JAR ืœืื—ื•ืจ, ืœื’ืจืกื” ื”ื™ืฉื ื” ืœื ื™ื”ื™ื” ืžื•ืฉื’ ืœื’ื‘ื™ ื”ืขืžื•ื“ื” ืฉื ื•ืกืคื” ื•ื”ื™ื ืชื’ื“ื™ืจ ืื•ืชื” ื‘ืื•ืคืŸ ืื•ื˜ื•ืžื˜ื™ ืœ-NULL. ืื ื™ืฉ ืžื’ื‘ืœื” ื›ื–ื•, ื”ืืคืœื™ืงืฆื™ื” ื”ื™ืฉื ื” ืคืฉื•ื˜ ืชื™ืฉื‘ืจ.

-- NOTE: This field can't have the NOT NULL constraint cause if you rollback, the old version won't know about this field
-- and will always set it to NULL
ALTER TABLE PERSON ADD surname varchar(255);

-- WE'RE ASSUMING THAT IT'S A FAST MIGRATION - OTHERWISE WE WOULD HAVE TO MIGRATE IN BATCHES
UPDATE PERSON SET PERSON.surname = PERSON.last_name

ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื“

ืื ื• ืžืื—ืกื ื™ื ื ืชื•ื ื™ื ื› last_name, ื• ื‘ surname. ื‘ืžืงื‘ื™ืœ ืื ื• ืงื•ืจืื™ื ืžืชื•ืš last_name, ืžื›ื™ื•ื•ืŸ ืฉืขืžื•ื“ื” ื–ื• ื”ื™ื ื”ืจืœื•ื•ื ื˜ื™ืช ื‘ื™ื•ืชืจ. ื‘ืžื”ืœืš ืชื”ืœื™ืš ื”ืคืจื™ืกื”, ื™ื™ืชื›ืŸ ืฉื—ืœืง ืžื”ื‘ืงืฉื•ืช ืขื•ื‘ื“ื• ืขืœ ื™ื“ื™ ืžื•ืคืข ื™ื™ืฉื•ื ืฉืขื“ื™ื™ืŸ ืœื ืขื•ื“ื›ืŸ.

/*
 * Copyright 2012-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package sample.flyway;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Person {
    @Id
    @GeneratedValue
    private Long id;
    private String firstName;
    private String lastName;
    private String surname;

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    /**
     * Reading from the new column if it's set. If not the from the old one.
     *
     * When migrating from version 1.0.0 -> 2.0.0 this can lead to a possibility that some data in
     * the surname column is not up to date (during the migration process lastName could have been updated).
     * In this case one can run yet another migration script after all applications have been deployed in the
     * new version to ensure that the surname field is updated.
     *
     * However it makes sense since when looking at the migration from 2.0.0 -> 3.0.0. In 3.0.0 we no longer
     * have a notion of lastName at all - so we don't update that column. If we rollback from 3.0.0 -> 2.0.0 if we
     * would be reading from lastName, then we would have very old data (since not a single datum was inserted
     * to lastName in version 3.0.0).
     */
    public String getSurname() {
        return this.surname != null ? this.surname : this.lastName;
    }

    /**
     * Storing both FIRST_NAME and SURNAME entries
     */
    public void setSurname(String surname) {
        this.lastName = surname;
        this.surname = surname;
    }

    @Override
    public String toString() {
        return "Person [firstName=" + this.firstName + ", lastName=" + this.lastName + ", surname=" + this.surname
                + "]";
    }
}

ืฉืœื‘ 3: ื”ืกืจืช last_name ืžื”ืงื•ื“

ื’ืจืกืช ื”ืืคืœื™ืงืฆื™ื”: 3.0.0

ื’ืจืกืช DB:v3

ื”ืขืจื”

ื”ืขืจื” per.: ื›ื›ืœ ื”ื ืจืื”, ื‘ืžืืžืจ ื”ืžืงื•ืจื™ ื”ืžื—ื‘ืจ ื”ืขืชื™ืง ื‘ื˜ืขื•ืช ืืช ื”ื˜ืงืกื˜ ืฉืœ ื‘ืœื•ืง ื–ื” ืžืฉืœื‘ 2. ื‘ืฉืœื‘ ื–ื”, ื™ืฉ ืœื‘ืฆืข ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื“ ื”ืืคืœื™ืงืฆื™ื” ืฉืžื˜ืจืชื ืœื”ืกื™ืจ ืืช ื”ืคื•ื ืงืฆื™ื•ื ืœื™ื•ืช ื”ืžืฉืชืžืฉืช ื‘ืขืžื•ื“ื” last_name.

ืขืœ ื™ื“ื™ ื”ื•ืกืคืช ืขืžื•ื“ื” ื—ื“ืฉื” ื•ื”ืขืชืงืช ืชื•ื›ื ื”, ื™ืฆืจื ื• ืฉื™ื ื•ื™ื™ื ื‘ืžืกื“ ื ืชื•ื ื™ื ืชื•ืืžื™ื ืœืื—ื•ืจ. ื›ืžื• ื›ืŸ, ืื ื ื—ื–ื™ืจ ืืช ื”-JAR ืœืื—ื•ืจ ืื• ืฉ-JAR ื™ืฉืŸ ืคื•ืขืœ, ื”ื•ื ืœื ื™ื™ืฉื‘ืจ ื‘ืžื”ืœืš ื”ื‘ื™ืฆื•ืข.

ื”ื—ื–ืจืช ืืคืœื™ืงืฆื™ื” ืœืื—ื•ืจ

ื›ืจื’ืข ื™ืฉ ืœื ื• ื’ืจืกืช ืืคืœื™ืงืฆื™ื” 3.0.0 ื•ืžืกื“ ื ืชื•ื ื™ื v3. ื’ึดืจึฐืกึธื” 3.0.0 ืœื ืฉื•ืžืจ ื ืชื•ื ื™ื ืœ last_name. ื–ื” ืื•ืžืจ ืฉื‘ surname ื”ืžื™ื“ืข ื”ืžืขื•ื“ื›ืŸ ื‘ื™ื•ืชืจ ื ืฉืžืจ.

ืฉืœื‘ื™ื:

  1. ื”ื—ื–ืจ ืืช ื”ืืคืœื™ืงืฆื™ื” ืฉืœืš ืœื’ืจืกื” 2.0.0.
  2. ื’ืจืกื” 2.0.0 ืžืฉืชืžืฉ ื• last_name ะธ surname.
  3. ื’ืจืกื” 2.0.0 ื™ื™ืงื— surname, ืื ื”ื•ื ืœื ืืคืก, ืื—ืจืช -last_name

ืฉื™ื ื•ื™ื™ื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื

ืื™ืŸ ืฉื™ื ื•ื™ื™ื ืžื‘ื ื™ื™ื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื. ื”ืกืงืจื™ืคื˜ ื”ื‘ื ืžื‘ื•ืฆืข ื›ื“ื™ ืœื‘ืฆืข ืืช ื”ื”ืขื‘ืจื” ื”ืกื•ืคื™ืช ืฉืœ ื”ื ืชื•ื ื™ื ื”ื™ืฉื ื™ื:

-- WE'RE ASSUMING THAT IT'S A FAST MIGRATION - OTHERWISE WE WOULD HAVE TO MIGRATE IN BATCHES
-- ALSO WE'RE NOT CHECKING IF WE'RE NOT OVERRIDING EXISTING ENTRIES. WE WOULD HAVE TO COMPARE
-- ENTRY VERSIONS TO ENSURE THAT IF THERE IS ALREADY AN ENTRY WITH A HIGHER VERSION NUMBER
-- WE WILL NOT OVERRIDE IT.
UPDATE PERSON SET PERSON.surname = PERSON.last_name;

-- DROPPING THE NOT NULL CONSTRAINT; OTHERWISE YOU WILL TRY TO INSERT NULL VALUE OF THE LAST_NAME
-- WITH A NOT_NULL CONSTRAINT.
ALTER TABLE PERSON MODIFY COLUMN last_name varchar(255) NULL DEFAULT NULL;

ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื“

ื”ืขืจื” per.: ื’ื ื”ืชื™ืื•ืจ ืฉืœ ื‘ืœื•ืง ื–ื” ื”ื•ืขืชืง ื‘ื˜ืขื•ืช ืขืœ ื™ื“ื™ ื”ืžื—ื‘ืจ ืžืฉืœื‘ 2. ื‘ื”ืชืื ืœื”ื™ื’ื™ื•ืŸ ืฉืœ ื”ืžืืžืจ, ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื“ ื‘ืฉืœื‘ ื–ื” ืฆืจื™ื›ื™ื ืœื”ื™ื•ืช ืžื›ื•ื•ื ื™ื ืœื”ืกื™ืจ ืžืžื ื• ืืœืžื ื˜ื™ื ืฉืขื•ื‘ื“ื™ื ืขื ื”ืขืžื•ื“ื” last_name.

ืื ื• ืžืื—ืกื ื™ื ื ืชื•ื ื™ื ื› last_name, ื• ื‘ surname. ื‘ื ื•ืกืฃ, ืื ื• ืงื•ืจืื™ื ืžื”ื˜ื•ืจ last_name, ืžื›ื™ื•ื•ืŸ ืฉื”ื•ื ื”ืจืœื•ื•ื ื˜ื™ ื‘ื™ื•ืชืจ. ื‘ืžื”ืœืš ืชื”ืœื™ืš ื”ืคืจื™ืกื”, ื™ื™ืชื›ืŸ ืฉื‘ืงืฉื•ืช ืžืกื•ื™ืžื•ืช ื™ืขื•ื‘ื“ื• ืขืœ ื™ื“ื™ ืžื•ืคืข ืฉืขื“ื™ื™ืŸ ืœื ืฉื•ื“ืจื’.

/*
 * Copyright 2012-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package sample.flyway;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Person {
    @Id
    @GeneratedValue
    private Long id;
    private String firstName;
    private String surname;

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getSurname() {
        return this.surname;
    }

    public void setSurname(String lastname) {
        this.surname = lastname;
    }

    @Override
    public String toString() {
        return "Person [firstName=" + this.firstName + ", surname=" + this.surname
                + "]";
    }
}

ืฉืœื‘ 4: ื”ืกืจืช last_name ืžืžืกื“ ื”ื ืชื•ื ื™ื

ื’ืจืกืช ื”ืืคืœื™ืงืฆื™ื”: 4.0.0

ื’ืจืกืช DB: v4

ื”ืขืจื”

ื‘ืฉืœ ื”ืขื•ื‘ื“ื” ืฉืงื•ื“ ื”ื’ืจืกื” 3.0.0 ืœื ื”ืฉืชืžืฉ ื‘ืขืžื•ื“ื” last_name, ืฉื•ื ื“ื‘ืจ ืจืข ืœื ื™ืงืจื” ื‘ืžื”ืœืš ื”ื‘ื™ืฆื•ืข ืื ื ื—ื–ื•ืจ ืืœื™ื• 3.0.0 ืœืื—ืจ ื”ืกืจืช ืขืžื•ื“ื” ืžืžืกื“ ื”ื ืชื•ื ื™ื.

ื™ื•ืžื ื™ ื‘ื™ืฆื•ืข ืกืงืจื™ืคื˜

We will do it in the following way:

01) Run 1.0.0
02) Wait for the app (1.0.0) to boot
03) Generate a person by calling POST localhost:9991/person to version 1.0.0
04) Run 2.0.0
05) Wait for the app (2.0.0) to boot
06) Generate a person by calling POST localhost:9991/person to version 1.0.0
07) Generate a person by calling POST localhost:9992/person to version 2.0.0
08) Kill app (1.0.0)
09) Run 3.0.0
10) Wait for the app (3.0.0) to boot
11) Generate a person by calling POST localhost:9992/person to version 2.0.0
12) Generate a person by calling POST localhost:9993/person to version 3.0.0
13) Kill app (3.0.0)
14) Run 4.0.0
15) Wait for the app (4.0.0) to boot
16) Generate a person by calling POST localhost:9993/person to version 3.0.0
17) Generate a person by calling POST localhost:9994/person to version 4.0.0

Starting app in version 1.0.0
Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:

{"firstName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2","lastName":"52b6e125-4a5c-429b-a47a-ef18bbc639d2"}

Starting app in version 2.0.0

Generate a person in version 1.0.0
Sending a post to 127.0.0.1:9991/person. This is the response:

{"firstName":"e41ee756-4fa7-4737-b832-e28827a00deb","lastName":"e41ee756-4fa7-4737-b832-e28827a00deb"}

Generate a person in version 2.0.0
Sending a post to 127.0.0.1:9992/person. This is the response:

{"firstName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","lastName":"0c1240f5-649a-4bc5-8aa9-cff855f3927f","surname":"0c1240f5-649a-4bc5-8aa9-cff855f3927f"}

Killing app 1.0.0

Starting app in version 3.0.0

Generate a person in version 2.0.0
Sending a post to 127.0.0.1:9992/person. This is the response:
{"firstName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","lastName":"74d84a9e-5f44-43b8-907c-148c6d26a71b","surname":"74d84a9e-5f44-43b8-907c-148c6d26a71b"}

Generate a person in version 3.0.0
Sending a post to 127.0.0.1:9993/person. This is the response:
{"firstName":"c6564dbe-9ab5-40ae-9077-8ae6668d5862","surname":"c6564dbe-9ab5-40ae-9077-8ae6668d5862"}

Killing app 2.0.0

Starting app in version 4.0.0

Generate a person in version 3.0.0
Sending a post to 127.0.0.1:9993/person. This is the response:

{"firstName":"cbe942fc-832e-45e9-a838-0fae25c10a51","surname":"cbe942fc-832e-45e9-a838-0fae25c10a51"}

Generate a person in version 4.0.0
Sending a post to 127.0.0.1:9994/person. This is the response:

{"firstName":"ff6857ce-9c41-413a-863e-358e2719bf88","surname":"ff6857ce-9c41-413a-863e-358e2719bf88"}

ืฉื™ื ื•ื™ื™ื ื‘-DB

ืœื’ื‘ื™ v3 ืื ื—ื ื• ืคืฉื•ื˜ ืžืกื™ืจื™ื ืืช ื”ืขืžื•ื“ื” last_name ื•ืœื”ื•ืกื™ืฃ ื”ื’ื‘ืœื•ืช ื—ืกืจื•ืช.

-- REMOVE THE COLUMN
ALTER TABLE PERSON DROP last_name;

-- ADD CONSTRAINTS
UPDATE PERSON SET surname='' WHERE surname IS NULL;
ALTER TABLE PERSON ALTER COLUMN surname VARCHAR NOT NULL;

ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื“

ืื™ืŸ ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื“.

ืคืœื˜

ื”ื—ืœืžื ื• ื‘ื”ืฆืœื—ื” ืฉื™ื ื•ื™ ืฉื ืขืžื•ื“ื” ืฉืื™ื ื• ืชื•ืื ืœืื—ื•ืจ ืขืœ ื™ื“ื™ ื‘ื™ืฆื•ืข ืžืกืคืจ ืคืจื™ืกื•ืช ืชื•ืืžื•ืช ืœืื—ื•ืจ. ืœื”ืœืŸ ืกื™ื›ื•ื ื”ืคืขื•ืœื•ืช ืฉื‘ื•ืฆืขื•:

  1. ืคืจื™ืกืช ื’ืจืกืช ื”ืืคืœื™ืงืฆื™ื” 1.0.0 ั v1 ืกื›ื™ืžืช ืžืกื“ ื ืชื•ื ื™ื (ืฉื ืขืžื•ื“ื” = last_name)
  2. ืคืจื™ืกืช ื’ืจืกืช ื”ืืคืœื™ืงืฆื™ื” 2.0.0, ืืฉืจ ืžืื—ืกืŸ ื ืชื•ื ื™ื ื‘ last_name ะธ surname. ื”ืืคืœื™ืงืฆื™ื” ืงื•ืจืืช ืž last_name. ืžืกื“ ื”ื ืชื•ื ื™ื ื ืžืฆื ื‘ื’ืจืกื” v2ื”ืžื›ื™ืœ ืขืžื•ื“ื•ืช ื›ืžื• last_nameื• - surname. surname ื”ื•ื ืขื•ืชืง ืฉืœ last_name. (ื”ืขืจื”: ืืกื•ืจ ืœืขืžื•ื“ื” ื–ื• ืœื›ืœื•ืœ ืื™ืœื•ืฅ ืœื null)
  3. ืคืจื™ืกืช ื’ืจืกืช ื”ืืคืœื™ืงืฆื™ื” 3.0.0, ืืฉืจ ืžืื—ืกืŸ ืจืง ื ืชื•ื ื™ื ื‘ surname ื•ืงื•ืจื ืžืฉื ืžืฉืคื—ื”. ื‘ืืฉืจ ืœืžืกื“ ื”ื ืชื•ื ื™ื, ื”ื”ื’ื™ืจื” ื”ืื—ืจื•ื ื” ืžืชืจื—ืฉืช last_name ะฒ surname. ื’ื ืžื’ื‘ืœื” ืœื ืจื™ืง ื”ื•ืกืจ ืž last_name. ืžืกื“ ื”ื ืชื•ื ื™ื ื ืžืฆื ื›ืขืช ื‘ื’ืจืกื” v3
  4. ืคืจื™ืกืช ื’ืจืกืช ื”ืืคืœื™ืงืฆื™ื” 4.0.0 - ืœื ื‘ื•ืฆืขื• ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื“. ืคืจื™ืกืช ืžืกื“ื™ ื ืชื•ื ื™ื v4, ืืฉืจ ืžืกื™ืจ last_name. ื›ืืŸ ืืชื” ื™ื›ื•ืœ ืœื”ื•ืกื™ืฃ ืื™ืœื•ืฆื™ื ื—ืกืจื™ื ืœืžืกื“ ื”ื ืชื•ื ื™ื.

ืขืœ ื™ื“ื™ ื‘ื™ืฆื•ืข ื’ื™ืฉื” ื–ื•, ืืชื” ืชืžื™ื“ ื™ื›ื•ืœ ืœื”ื—ื–ื™ืจ ื’ืจืกื” ืื—ืช ืœืื—ื•ืจ ืžื‘ืœื™ ืœืฉื‘ื•ืจ ืืช ืชืื™ืžื•ืช ืžืกื“ื™ ื”ื ืชื•ื ื™ื/ืืคืœื™ืงืฆื™ื•ืช.

ืงื•ื“

ื›ืœ ื”ืงื•ื“ ื”ืžืฉืžืฉ ื‘ืžืืžืจ ื–ื” ื–ืžื™ืŸ ื‘ื›ืชื•ื‘ืช GitHub. ืœื”ืœืŸ ืชื™ืื•ืจ ื ื•ืกืฃ.

ืคืจื•ื™ื™ืงื˜ื™ื

ืœืื—ืจ ืฉื™ื‘ื•ื˜ ื”ืžืื’ืจ, ืชืจืื” ืืช ืžื‘ื ื” ื”ืชื™ืงื™ื•ืช ื”ื‘ื.

โ”œโ”€โ”€ boot-flyway-v1              - 1.0.0 version of the app with v1 of the schema
โ”œโ”€โ”€ boot-flyway-v2              - 2.0.0 version of the app with v2 of the schema (backward-compatible - app can be rolled back)
โ”œโ”€โ”€ boot-flyway-v2-bad          - 2.0.0.BAD version of the app with v2bad of the schema (backward-incompatible - app cannot be rolled back)
โ”œโ”€โ”€ boot-flyway-v3              - 3.0.0 version of the app with v3 of the schema (app can be rolled back)
โ””โ”€โ”€ boot-flyway-v4              - 4.0.0 version of the app with v4 of the schema (app can be rolled back)

ืกืงืจื™ืคื˜ื™ื

ืืชื” ื™ื›ื•ืœ ืœื”ืคืขื™ืœ ืืช ื”ืกืงืจื™ืคื˜ื™ื ื”ืžืชื•ืืจื™ื ื‘ืกืงืจื™ืคื˜ื™ื ืœืžื˜ื”, ืฉื™ื“ื’ื™ืžื• ืฉื™ื ื•ื™ื™ื ืชื•ืืžื™ื ืœืื—ื•ืจ ื•ื‘ืœืชื™ ืชื•ืืžื™ื ื‘ืžืกื“ ื”ื ืชื•ื ื™ื.

ืœืจืื•ืช ื”ืžืงืจื” ืขื ืฉื™ื ื•ื™ื™ื ืชื•ืืžื™ื ืœืื—ื•ืจ, ื”ืจืฅ:

./scripts/scenario_backward_compatible.sh

ื•ืœืจืื•ืช ืžืงืจื” ืขื ืฉื™ื ื•ื™ื™ื ืœื ืชื•ืืžื™ื ืœืื—ื•ืจ, ื”ืจืฅ:

./scripts/scenario_backward_incompatible.sh

ืžืกืœื•ืœ ื“ื’ื™ืžื” ืฉืœ ืžื’ืฃ ืื‘ื™ื‘

ื›ืœ ื”ื“ื•ื’ืžืื•ืช ืœืงื•ื—ื•ืช ืž Spring Boot Sample Flyway.

ืืชื” ื™ื›ื•ืœ ืœื”ืขื™ืฃ ืžื‘ื˜ http://localhost:8080/flyway, ื™ืฉ ืจืฉื™ืžื” ืฉืœ ืกืงืจื™ืคื˜ื™ื.

ื“ื•ื’ืžื” ื–ื• ื›ื•ืœืœืช ื’ื ืืช ืงื•ื ืกื•ืœืช H2 (ื‘ื›ืชื•ื‘ืช http://localhost:8080/h2-console) ื›ื“ื™ ืฉืชื•ื›ืœ ืœื”ืฆื™ื’ ืืช ืกื˜ื˜ื•ืก ืžืกื“ ื”ื ืชื•ื ื™ื (ื›ืชื•ื‘ืช ื‘ืจื™ืจืช ื”ืžื—ื“ืœ ืฉืœ jdbc ื”ื™ื jdbc:h2:mem:testdb).

ื‘ื ื•ืกืฃ

ืงืจื ื’ื ืžืืžืจื™ื ืื—ืจื™ื ื‘ื‘ืœื•ื’ ืฉืœื ื•:

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”