αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž–αŸαž›αž˜αž·αž“αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš αž“αž·αž„αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™

αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž–αŸαž›αž˜αž·αž“αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš αž“αž·αž„αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™

αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αž–αž“αŸ’αž™αž›αŸ‹αž›αž˜αŸ’αž’αž·αžαž’αŸ†αž–αžΈαžšαž”αŸ€αž”αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž”αž‰αŸ’αž αžΆαž—αžΆαž–αž†αž”αž‚αŸ’αž“αžΆαž“αŸƒαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž“αŸ…αž€αŸ’αž“αž»αž„αž€αžΆαžšαžŠαžΆαž€αŸ‹αž±αŸ’αž™αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αŸ” αž™αžΎαž„αž“αžΉαž„αž”αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αž–αžΈαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž’αžΆαž…αž€αžΎαžαž‘αžΎαž„αž…αŸ†αž–αŸ„αŸ‡αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž•αž›αž·αžαž€αž˜αŸ’αž˜αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€ αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž–αŸ’αž™αžΆαž™αžΆαž˜αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž€αžΆαžšαžšαŸ€αž”αž…αŸ†αž‡αžΆαž˜αž»αž“αŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹β€‹αž˜αž€β€‹αž™αžΎαž„β€‹αž“αžΉαž„β€‹αž†αŸ’αž›αž„β€‹αž€αžΆαžαŸ‹β€‹αžŠαŸ†αžŽαžΆαž€αŸ‹β€‹αž€αžΆαž›β€‹αžŠαŸ†αžŽαžΎαžšβ€‹αž‡αžΈαžœαž·αžβ€‹αžšαž”αžŸαŸ‹β€‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈβ€‹αžŠαŸ‚αž›β€‹αžαž˜αŸ’αžšαžΌαžœβ€‹αž±αŸ’αž™β€‹αž˜αžΆαž“β€‹αž–αŸαž›β€‹αžœαŸαž›αžΆβ€‹αž˜αž·αž“β€‹αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš (αž”αŸ’αžšαž αŸ‚αž› αž•αŸ’αž›αžΌαžœαŸ– αž”αž“αŸ’αžαŸ‚αž˜αž‘αŸ€αž - αžŸαžΌαž“αŸ’αž™αž–αŸαž›αžœαŸαž›αžΆαžšαž„αž…αžΆαŸ†) αž›αž‘αŸ’αž’αž•αž›αž“αŸƒαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαžšαž”αžŸαŸ‹αž™αžΎαž„αž“αžΉαž„αž’αž“αž»αžœαžαŸ’αžαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαŸ‚αž›αž˜αž·αž“αž†αž”αž‚αŸ’αž“αžΆαžαž™αž€αŸ’αžšαŸ„αž™αž€αŸ’αž“αž»αž„αž›αž€αŸ’αžαžŽαŸˆαžŠαŸ‚αž›αž†αž”αž‚αŸ’αž“αžΆαžαž™αž€αŸ’αžšαŸ„αž™αŸ”

αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž…αž„αŸ‹αž™αž›αŸ‹αž–αžΈαž§αž‘αžΆαž αžšαžŽαŸαž€αžΌαžŠαž–αžΈαž’αžαŸ’αžαž”αž‘ αž’αŸ’αž“αž€αž’αžΆαž…αžŸαŸ’αžœαŸ‚αž„αžšαž€αž–αž½αž€αžœαžΆαž“αŸ… GitHub.

αžŸαŸαž…αž€αŸ’αžαžΈαžŽαŸ‚αž“αžΆαŸ†

αž€αžΆαžšβ€‹αžŠαžΆαž€αŸ‹β€‹αž–αž„αŸ’αžšαžΆαž™β€‹αž–αŸαž›β€‹αžœαŸαž›αžΆβ€‹αž˜αž·αž“β€‹αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš

αž’αŸ’αžœαžΈαžŠαŸ‚αž›αž‡αžΆαž’αžΆαžαŸŒαž€αŸ†αž”αžΆαŸ†αž„ αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž–αŸαž›αž‘αŸ†αž“αŸαžšαžŸαžΌαž“αŸ’αž™? αž’αŸ’αž“αž€αž’αžΆαž…αž“αž·αž™αžΆαž™αž”αžΆαž“αžαžΆαž“αŸαŸ‡αž‚αžΊαž‡αžΆαž–αŸαž›αžŠαŸ‚αž›αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαžΆαž€αŸ‹αž±αŸ’αž™αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αžαžΆαž˜αžšαž”αŸ€αž”αžŠαŸ‚αž›αž’αŸ’αž“αž€αž’αžΆαž…αžŽαŸ‚αž“αžΆαŸ†αž€αŸ†αžŽαŸ‚αžαŸ’αž˜αžΈαž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαŸ„αž™αž‡αŸ„αž‚αž‡αŸαž™αž€αŸ’αž“αž»αž„αž€αžΆαžšαž•αž›αž·αž αžαžŽαŸˆαž–αŸαž›αžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž˜αž·αž“αž€αžαŸ‹αžŸαŸ†αž‚αžΆαž›αŸ‹αž—αžΆαž–αž˜αž·αž“αž’αžΆαž…αž”αŸ’αžšαžΎαž”αžΆαž“αžšαž”αžŸαŸ‹αžœαžΆαŸ” αžαžΆαž˜αž‘αžŸαŸ’αžŸαž“αŸˆαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎ αž“αž·αž„αž€αŸ’αžšαž»αž˜αž αŸŠαž»αž“ αž“αŸαŸ‡αž‚αžΊαž‡αžΆαžŸαŸαžŽαžΆαžšαžΈαž™αŸ‰αžΌαž“αŸƒαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžŠαŸαž›αŸ’αž’αž”αŸ†αž•αž»αžαžŠαŸ‚αž›αž’αžΆαž…αž’αŸ’αžœαžΎαž‘αŸ…αž”αžΆαž“ αž–αŸ’αžšαŸ„αŸ‡αžœαžΆαž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž›αž€αŸ’αžαžŽαŸˆαž–αž·αžŸαŸαžŸαžαŸ’αž˜αžΈαŸ—αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŽαŸ‚αž“αžΆαŸ† αž“αž·αž„αž€αŸ†αž αž»αžŸαžαŸ’αžšαžΌαžœαž”αžΆαž“αž‡αž½αžŸαž‡αž»αž›αžŠαŸ„αž™αž˜αž·αž“αž˜αžΆαž“αž€αžΆαžšαžšαŸ†αžαžΆαž“αŸ”

αžαžΎαž’αŸ’αžœαžΎαžŠαžΌαž…αž˜αŸ’αžαŸαž…αžŠαžΎαž˜αŸ’αž”αžΈαžŸαž˜αŸ’αžšαŸαž…αž”αžΆαž“αž“αŸαŸ‡? αž˜αžΆαž“αžœαž·αž’αžΈαž‡αžΆαž…αŸ’αžšαžΎαž“ αž“αŸαŸ‡αž‚αžΊαž‡αžΆαžœαž·αž’αžΈαž˜αž½αž™αž€αŸ’αž“αž»αž„αž…αŸ†αžŽαŸ„αž˜αžœαž·αž’αžΈαž‘αžΆαŸ†αž„αž“αŸαŸ‡αŸ–

  • αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž€αŸ†αžŽαŸ‚αž›αŸαž 1 αž“αŸƒαžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”
  • αž’αŸ’αžœαžΎαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™
  • αž”αŸ’αžšαžΎαž€αŸ†αžŽαŸ‚ #2 αž“αŸƒαžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αžŸαŸ’αžšαž”αž‡αžΆαž˜αž½αž™αž€αŸ†αžŽαŸ‚ #1
  • αžŠαžšαžΆαž”αžŽαžΆαž’αŸ’αž“αž€αžƒαžΎαž‰αžαžΆαž€αŸ†αžŽαŸ‚αž›αŸαž 2 αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαžΌαž…αžŠαŸ‚αž›αžœαžΆαž‚αž½αžšαžαŸ‚ αžŸαžΌαž˜αž›αž»αž”αž€αŸ†αžŽαŸ‚αž›αŸαž 1 αž…αŸαž‰
  • αžšαž½αž…αžšαžΆαž›αŸ‹!

αž„αžΆαž™αžŸαŸ’αžšαž½αž›αž‘αŸ? αž‡αžΆαž’αž€αž»αžŸαž› αžœαžΆαž˜αž·αž“αžŸαžΆαž˜αž‰αŸ’αž‰αž“αŸ„αŸ‡αž‘αŸ αž αžΎαž™αž™αžΎαž„αž“αžΉαž„αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžœαžΆαž±αŸ’αž™αž›αž˜αŸ’αž’αž·αžαž“αŸ…αž–αŸαž›αž€αŸ’αžšαŸ„αž™αŸ” αž₯αž‘αžΌαžœαž“αŸαŸ‡ αžŸαžΌαž˜αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž’αž˜αŸ’αž˜αžαžΆαž˜αž½αž™αž•αŸ’αžŸαŸαž„αž‘αŸ€αž - αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž–αžŽαŸŒαž”αŸƒαžαž„αžαŸ€αžœαŸ”

αžαžΎαž’αŸ’αž“αž€αž’αŸ’αž›αžΆαž”αŸ‹ heard αž’αŸ†αž–αžΈ αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž–αžŽαŸŒαžαŸ€αžœαž”αŸƒαžαž„? Cloud Foundry αž’αŸ’αžœαžΎαž±αŸ’αž™αžœαžΆαž„αžΆαž™αžŸαŸ’αžšαž½αž›αž”αŸ†αž•αž»αžαŸ” αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž˜αžΎαž› αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αžŠαŸ‚αž›αž‡αžΆαž€αž“αŸ’αž›αŸ‚αž„αžŠαŸ‚αž›αž™αžΎαž„αž–αž·αž–αžŽαŸŒαž“αžΆαž›αž˜αŸ’αž’αž·αžαž”αž“αŸ’αžαŸ‚αž˜αž‘αŸ€αžαŸ” αžŠαžΎαž˜αŸ’αž”αžΈαžŸαž„αŸ’αžαŸαž”αžŠαŸ„αž™αžŸαž„αŸ’αžαŸαž” αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž™αžΎαž„αžšαŸ†αž›αžΉαž€αž’αŸ’αž“αž€αž–αžΈαžšαž”αŸ€αž”αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž–αžŽαŸŒαžαŸ€αžœαž”αŸƒαžαž„αŸ–

  • αžαŸ’αžšαžΌαžœαž”αŸ’αžšαžΆαž€αžŠαžαžΆαž…αŸ’αž”αžΆαž”αŸ‹αž…αž˜αŸ’αž›αž„αž–αžΈαžšαž“αŸƒαž€αžΌαžŠαž•αž›αž·αžαž€αž˜αŸ’αž˜αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€ ("αžαŸ€αžœ" αž“αž·αž„ "αž”αŸƒαžαž„") αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαŸ”
  • αžŠαžΉαž€αž“αžΆαŸ†αž…αžšαžΆαž…αžšαžŽαŸαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž‘αŸ…αž€αžΆαž“αŸ‹αž”αžšαž·αžŸαŸ’αžαžΆαž“αž–αžŽαŸŒαžαŸ€αžœ, i.e. αžŠαžΌαž…αŸ’αž“αŸαŸ‡ URLs αž•αž›αž·αžαž€αž˜αŸ’αž˜αž…αž„αŸ’αž’αž»αž›αž‘αŸ…αž‘αžΈαž“αŸ„αŸ‡;
  • αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ αž“αž·αž„αžŸαžΆαž€αž›αŸ’αž”αž„αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αž”αžšαž·αžŸαŸ’αžαžΆαž“αž”αŸƒαžαž„αŸ”
  • αž”αŸ’αžαžΌαžš url αž–αžΈαž–αžŽαŸŒαžαŸ€αžœαž‘αŸ…αž”αžšαž·αžŸαŸ’αžαžΆαž“αž”αŸƒαžαž„

αž€αžΆαžšβ€‹αžŠαžΆαž€αŸ‹β€‹αž–αž„αŸ’αžšαžΆαž™β€‹αž–αžŽαŸŒβ€‹αž”αŸƒαžαž„β€‹αžαŸ€αžœβ€‹αž‚αžΊβ€‹αž‡αžΆβ€‹αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžαŸ’αžšβ€‹αžŠαŸ‚αž›β€‹αž’αž“αž»αž‰αŸ’αž‰αžΆαžβ€‹αž±αŸ’αž™β€‹αž’αŸ’αž“αž€β€‹αž„αžΆαž™αžŸαŸ’αžšαž½αž›β€‹αžŽαŸ‚αž“αžΆαŸ†β€‹αž˜αž»αžαž„αžΆαžšβ€‹αžαŸ’αž˜αžΈαŸ—β€‹αžŠαŸ„αž™β€‹αž˜αž·αž“β€‹αž”αžΆαž…αŸ‹β€‹αž”αžΆαžšαž˜αŸ’αž—β€‹αž–αžΈβ€‹αž€αžΆαžšβ€‹αž”αŸ†αž”αŸ‚αž€β€‹αž•αž›αž·αžαž€αž˜αŸ’αž˜αŸ” αž“αŸαŸ‡αž‚αžΊαžŠαŸ„αž™αžŸαžΆαžšαžαŸ‚αž€αžΆαžšαž–αž·αžαžŠαŸ‚αž›αžαžΆ αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαž˜αžΆαž“αž’αŸ’αžœαžΈαž˜αž½αž™αž€αžΎαžαž‘αžΎαž„αž€αŸαžŠαŸ„αž™ αž’αŸ’αž“αž€αž’αžΆαž…αžœαž·αž›αžαŸ’αžšαž›αž”αŸ‹αž‘αŸ…αž”αžšαž·αž™αžΆαž€αžΆαžŸαž–αžΈαž˜αž»αž“αž”αžΆαž“αž™αŸ‰αžΆαž„αž„αžΆαž™αžŸαŸ’αžšαž½αž›αžŠαŸ„αž™αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚ β€œαž…αž»αž…αž”αž·αž‘αž”αžΎαž€β€αŸ”

αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž”αžΆαž“αž’αžΆαž“αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αžαžΆαž„αž›αžΎ αž’αŸ’αž“αž€αž’αžΆαž…αž“αžΉαž„αžŸαž½αžšαžŸαŸ†αžŽαž½αžšαžαžΆ αžαžΎαž–αŸαž›αž‘αŸ†αž“αŸαžšαž‚αŸ’αž˜αžΆαž“αž‡αžΆαž”αŸ‹αž‘αžΆαž€αŸ‹αž‘αž„αž“αžΉαž„αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž–αžŽαŸŒαžαŸ€αžœαž”αŸƒαžαž„?

αž‡αžΆαž€αžΆαžšαž”αŸ’αžšαžŸαžΎαžšαžŽαžΆαžŸαŸ‹ αž–αž½αž€αž‚αŸαž˜αžΆαž“αž…αŸ’αžšαžΎαž“αžŠαžΌαž…αž‚αŸ’αž“αžΆ αž…αžΆαž”αŸ‹αžαžΆαŸ†αž„αž–αžΈαž€αžΆαžšαžšαž€αŸ’αžŸαžΆαž”αžΆαž“αž“αžΌαžœαž…αŸ’αž”αžΆαž”αŸ‹αž…αž˜αŸ’αž›αž„αž–αžΈαžšαž“αŸƒαž”αžšαž·αžŸαŸ’αžαžΆαž“αžŠαžΌαž…αž‚αŸ’αž“αžΆαž‘αžΆαž˜αž‘αžΆαžšαž±αŸ’αž™αž˜αžΆαž“αž€αžΆαžšαžαž·αžαžαŸ†αž”αŸ’αžšαžΉαž„αž”αŸ’αžšαŸ‚αž„αž‘αŸ’αžœαŸαžŠαž„αž€αŸ’αž“αž»αž„αž€αžΆαžšαžαŸ‚αžšαž€αŸ’αžŸαžΆαž–αž½αž€αž‚αŸαŸ” αž“αŸαŸ‡β€‹αž‡αžΆβ€‹αž˜αžΌαž›αž αŸαžαž»β€‹αžŠαŸ‚αž›β€‹αž€αŸ’αžšαž»αž˜β€‹αžαŸ’αž›αŸ‡β€‹αž’αŸ‡αž’αžΆαž„ Martin FowlerαžŸαžΌαž˜αž’αž“αž»αžœαžαŸ’αžαžαžΆαž˜αž”αŸ†αžšαŸ‚αž”αŸ†αžšαž½αž›αž“αŸƒαžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αžαž“αŸαŸ‡αŸ–

αž‡αž˜αŸ’αžšαžΎαžŸαž˜αž½αž™αž‘αŸ€αžαž‚αžΊαž”αŸ’αžšαžΎαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαžΌαž…αž‚αŸ’αž“αžΆ αž”αž„αŸ’αž€αžΎαžαž€αž»αž„αžαžΆαž€αŸ‹αž–αžŽαŸŒαžαŸ€αžœαž”αŸƒαžαž„αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŸαŸ’αžšαž‘αžΆαž”αŸ‹αž‚αŸαž αž‘αŸ†αž–αŸαžš αž“αž·αž„αžŠαŸ‚αž“αŸ” αž“αŸ…αž€αŸ’αž“αž»αž„αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αžαž“αŸαŸ‡ αž‡αžΆαž‰αžΉαž€αž‰αžΆαž”αŸ‹αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž’αžΆαž…αž˜αžΆαž“αž”αž‰αŸ’αž αžΆ αž‡αžΆαž–αž·αžŸαŸαžŸαž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž‚αŸ’αžšαŸ„αž„αž€αžΆαžšαžŽαŸαžšαž”αžŸαŸ‹αžœαžΆαžŠαžΎαž˜αŸ’αž”αžΈαž‚αžΆαŸ†αž‘αŸ’αžšαž€αŸ†αžŽαŸ‚αžαŸ’αž˜αžΈαž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαŸ”

αž αžΎαž™αž“αŸ…αž‘αžΈαž“αŸαŸ‡αž™αžΎαž„αž˜αž€αžŠαž›αŸ‹αž”αž‰αŸ’αž αžΆαž…αž˜αŸ’αž”αž„αž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αŸ” αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™. αžŸαžΌαž˜αž€αŸ’αžšαž‘αŸαž€αž˜αžΎαž›αžƒαŸ’αž›αžΆαž“αŸαŸ‡αž˜αž½αž™αž‘αŸ€αžαŸ”

αž’αŸ’αžœαžΎαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αŸ”

αž₯αž‘αžΌαžœαž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαžŸαž½αžšαžαŸ’αž›αž½αž“αž―αž„αž“αžΌαžœαžŸαŸ†αžŽαž½αžš - αž…αž»αŸ‡αž”αžΎαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž˜αž·αž“αžαŸ’αžšαžΌαžœαž‚αŸ’αž“αžΆαžœαž·αž‰? αžαžΎβ€‹αž€αŸ†αžŽαŸ‚β€‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈβ€‹αžŠαŸ†αž”αžΌαž„β€‹αžšαž”αžŸαŸ‹β€‹αžαŸ’αž‰αž»αŸ†β€‹αž“αžΉαž„β€‹αž˜αž·αž“β€‹αžαžΌαž…β€‹αž¬? αžαžΆαž˜αž–αž·αžαž‘αŸ… αž“αŸαŸ‡αž–αž·αžαž‡αžΆαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž“αžΉαž„αž€αžΎαžαž‘αžΎαž„...

αžŠαžΌαž…αŸ’αž“αŸαŸ‡ αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαž˜αžΆαž“αž’αžαŸ’αžαž”αŸ’αžšαž™αŸ„αž‡αž“αŸαžŠαŸαž’αŸ†αž“αŸƒαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžŸαžΌαž“αŸ’αž™/αžαŸ€αžœαž”αŸƒαžαž„αž€αŸαžŠαŸ„αž™ αž€αŸαž€αŸ’αžšαž»αž˜αž αŸŠαž»αž“αž˜αžΆαž“αž‘αŸ†αž“αŸ„αžšαž“αžΉαž„αž’αž“αž»αžœαžαŸ’αžαžαžΆαž˜αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸ‚αž›αž˜αžΆαž“αžŸαž»αžœαžαŸ’αžαž·αž—αžΆαž–αž‡αžΆαž„αž˜αž»αž“αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸαŸ–

  • αžšαŸ€αž”αž…αŸ†αž€αž‰αŸ’αž…αž”αŸ‹αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αŸ†αžŽαŸ‚αžαŸ’αž˜αžΈαž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈ
  • αž”αž·αž‘αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŠαŸ‚αž›αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžš
  • αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαŸ’αž‚αŸ’αžšαžΈαž”αžŠαžΎαž˜αŸ’αž”αžΈαž•αŸ’αž‘αŸαžšαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™
  • αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ αž“αž·αž„αž”αžΎαž€αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αŸ†αžŽαŸ‚αžαŸ’αž˜αžΈαž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈ

αž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡ αž™αžΎαž„αž“αžΉαž„αžšαŸ€αž”αžšαžΆαž”αŸ‹αž›αž˜αŸ’αž’αž·αžαž’αŸ†αž–αžΈαžšαž”αŸ€αž”αžŠαŸ‚αž›αž’αŸ’αž“αž€αž’αžΆαž…αž’αŸ’αžœαžΎαž€αžΆαžšαž‡αžΆαž˜αž½αž™αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™ αž“αž·αž„αž€αžΌαžŠαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€ αžŠαžΎαž˜αŸ’αž”αžΈαž‘αžΆαž‰αž™αž€αž’αžαŸ’αžαž”αŸ’αžšαž™αŸ„αž‡αž“αŸαž–αžΈαž€αžΆαžšαžŠαžΆαž€αŸ‹αž±αŸ’αž™αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‚αŸ’αž˜αžΆαž“αž–αŸαž›αž‘αŸ†αž“αŸαžšαŸ”

αž”αž‰αŸ’αž αžΆαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™

αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž˜αžΆαž“αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‚αŸ’αž˜αžΆαž“αžšαžŠαŸ’αž‹αžŠαŸ‚αž›αž˜αž·αž“αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŽαžΆαž˜αž½αž™αž“αŸ…αž€αŸ’αž“αž»αž„αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™ αž’αŸ’αž“αž€αž’αžΆαž…αž‘αž‘αž½αž›αž”αžΆαž“αžŸαžΌαž“αŸ’αž™αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž–αŸαž›αž‘αŸ†αž“αŸαžšαž—αŸ’αž›αžΆαž˜αŸ—αŸ” αž‡αžΆαž’αž€αž»αžŸαž› αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž—αžΆαž‚αž…αŸ’αžšαžΎαž“αžαŸ’αžšαžΌαžœαž€αžΆαžšαžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž‘αž·αž“αŸ’αž“αž“αŸαž™αž“αŸ…αž€αž“αŸ’αž›αŸ‚αž„αžŽαžΆαž˜αž½αž™αŸ” αž“αŸαŸ‡αž‡αžΆαž˜αžΌαž›αž αŸαžαž»αžŠαŸ‚αž›αž’αŸ’αž“αž€αž‚αž½αžšαžαŸ‚αž‚αž·αžαž–αžΈαžšαžŠαž„αž˜αž»αž“αž–αŸαž›αž’αŸ’αžœαžΎαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαžŽαžΆαž˜αž½αž™αž…αŸ†αž–αŸ„αŸ‡αžŸαŸ€αž‚αŸ’αžœαžΈαŸ” αž˜αž»αž“αž“αžΉαž„αž™αžΎαž„αžŸαŸ’αžœαŸ‚αž„αž™αž›αŸ‹αž›αž˜αŸ’αž’αž·αžαž’αŸ†αž–αžΈαžšαž”αŸ€αž”αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž‚αŸ’αžšαŸ„αž„αž€αžΆαžšαžŽαŸ αžŠαžΎαž˜αŸ’αž”αžΈαž€αž»αŸ†αž±αŸ’αž™αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž–αŸαž›αž‘αŸ†αž“αŸαžšαž’αžΆαž…αž’αŸ’αžœαžΎαž‘αŸ…αž”αžΆαž“ αžŸαžΌαž˜αž™αžΎαž„αž•αŸ’αžαŸ„αžαž›αžΎαž‚αŸ’αžšαŸ„αž„αž€αžΆαžšαžŽαŸαž€αŸ†αžŽαŸ‚αž‡αžΆαž˜αž»αž“αžŸαž·αž“αŸ”

αž‚αŸ’αžšαŸ„αž„αž€αžΆαžšαžŽαŸαž€αŸ†αžŽαŸ‚

αž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αž™αžΎαž„αž“αžΉαž„αž”αŸ’αžšαžΎ αž•αŸ’αž›αžΌαžœαž αŸ„αŸ‡αž αžΎαžš αž‡αžΆαž§αž”αž€αžšαžŽαŸαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž€αŸ†αžŽαŸ‚ (αž”αŸ’αžšαž αŸ‚αž› αž€αžΆαžšαž”αž€αž”αŸ’αžšαŸ‚αŸ– αž™αžΎαž„αž€αŸ†αž–αž»αž„αž“αž·αž™αžΆαž™αž’αŸ†αž–αžΈαž€αžΆαžšαž’αŸ’αžœαžΎαž…αŸ†αžŽαžΆαž€αžŸαŸ’αžšαž»αž€αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™) αž‡αžΆαž’αž˜αŸ’αž˜αžαžΆ αž™αžΎαž„αž€αŸαž“αžΉαž„αžŸαžšαžŸαŸαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈ 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.

αžŠαŸ„αž™αž”αŸ’αžšαžΎαž§αž”αž€αžšαžŽαŸαž‚αŸ’αžšαž”αŸ‹αž‚αŸ’αžšαž„αž”αŸ’αžšαž—αž–αž‡αžΆαž˜αž½αž™ Spring Boot αž’αŸ’αž“αž€αž‘αž‘αž½αž›αž”αžΆαž“αž’αžαŸ’αžαž”αŸ’αžšαž™αŸ„αž‡αž“αŸαž’αŸ† 2αŸ–

  • αž’αŸ’αž“αž€αž”αŸ†αž”αŸ‚αž€αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž–αžΈαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž€αžΌαžŠ
  • αž€αžΆαžšαž’αŸ’αžœαžΎαž…αŸ†αžŽαžΆαž€αžŸαŸ’αžšαž»αž€αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž€αžΎαžαž‘αžΎαž„αžšαž½αž˜αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαžŠαžΆαž€αŸ‹αž±αŸ’αž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€ αž–αŸ„αž›αž‚αžΊαž§αŸ” αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αŸ’αžœαžΎαž±αŸ’αž™αžŸαžΆαž˜αž‰αŸ’αž‰

αž€αžΆαžšαžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž”αž‰αŸ’αž αžΆαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™

αž“αŸ…αž€αŸ’αž“αž»αž„αž•αŸ’αž“αŸ‚αž€αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž“αŸƒαž’αžαŸ’αžαž”αž‘ αž™αžΎαž„αž“αžΉαž„αž•αŸ’αžαŸ„αžαž›αžΎαž€αžΆαžšαž˜αžΎαž›αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αžαž–αžΈαžšαž…αŸ†αž–αŸ„αŸ‡αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αŸ”

  • αž—αžΆαž–αž˜αž·αž“αž†αž”αž‚αŸ’αž“αžΆαžαžΆαž„αž€αŸ’αžšαŸ„αž™
  • αž—αžΆαž–αž†αž”αž‚αŸ’αž“αžΆαžαžΆαž„αž€αŸ’αžšαŸ„αž™

αž‘αžΈαž˜αž½αž™αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αžΆαžαŸ‹αž‘αž»αž€αžαžΆαž‡αžΆαž€αžΆαžšαž–αŸ’αžšαž˜αžΆαž“αž˜αž½αž™αžŠαŸ‚αž›αž’αŸ’αž“αž€αž˜αž·αž“αž‚αž½αžšαž’αž“αž»αžœαžαŸ’αžαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž‚αŸ’αž˜αžΆαž“αž–αŸαž›αžœαŸαž›αžΆαžšαž„αž…αžΆαŸ†αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž€αžΆαžšαžšαŸ€αž”αž…αŸ†αž‡αžΆαž˜αž»αž“... αž‘αžΈαž–αžΈαžšαž•αŸ’αžαž›αŸ‹αž“αžΌαžœαžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž’αŸ†αž–αžΈαžšαž”αŸ€αž”αžŠαŸ‚αž›αž’αŸ’αž“αž€αž’αžΆαž…αž’αž“αž»αžœαžαŸ’αžαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž–αŸαž›αžœαŸαž›αžΆαžšαž„αž…αžΆαŸ† αž αžΎαž™αž€αŸ’αž“αž»αž„αž–αŸαž›αžαŸ‚αž˜αž½αž™αžšαž€αŸ’αžŸαžΆαž—αžΆαž–αž†αž”αž‚αŸ’αž“αžΆαžαž™αž€αŸ’αžšαŸ„αž™αŸ”

αž‚αž˜αŸ’αžšαŸ„αž„αžšαž”αžŸαŸ‹αž™αžΎαž„αžŠαŸ‚αž›αž™αžΎαž„αž“αžΉαž„αž’αŸ’αžœαžΎαž€αžΆαžšαž“αžΉαž„αž€αŸ’αž›αžΆαž™αž‡αžΆαž€αž˜αŸ’αž˜αžœαž·αž’αžΈ Spring Boot Flyway αžŠαŸαžŸαžΆαž˜αž‰αŸ’αž‰αž˜αž½αž™αžŠαŸ‚αž›αž˜αžΆαž“ Person с first_name ΠΈ last_name αž“αŸ…αž€αŸ’αž“αž»αž„αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™ (αž”αŸ’αžšαž αŸ‚αž› αž€αžΆαžšαž”αž€αž”αŸ’αžšαŸ‚αŸ– Person αž‚αžΊαž‡αžΆαžαžΆαžšαžΆαž„ αž“αž·αž„ first_name ΠΈ last_name - αž‘αžΆαŸ†αž„αž“αŸαŸ‡αž‚αžΊαž‡αžΆαžœαžΆαž›αž“αŸ…αž€αŸ’αž“αž»αž„αžœαžΆαŸ”) αž™αžΎαž„αž…αž„αŸ‹αž”αŸ’αžαžΌαžšαžˆαŸ’αž˜αŸ„αŸ‡ last_name Π² surname.

αž€αžΆαžšαžŸαž“αŸ’αž˜αžαŸ‹

αž˜αž»αž“αž–αŸαž›αž™αžΎαž„αž…αžΌαž›αž‘αŸ…αž€αŸ’αž“αž»αž„αž–αŸαžαŸŒαž˜αžΆαž“αž›αž˜αŸ’αž’αž·αž αž˜αžΆαž“αž€αžΆαžšαžŸαž“αŸ’αž˜αžαŸ‹αž˜αž½αž™αž…αŸ†αž“αž½αž“αžŠαŸ‚αž›αž™αžΎαž„αžαŸ’αžšαžΌαžœαž’αŸ’αžœαžΎαž’αŸ†αž–αžΈαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž™αžΎαž„αŸ” αž›αž‘αŸ’αž’αž•αž›αžŸαŸ†αžαžΆαž“αŸ‹αžŠαŸ‚αž›αž™αžΎαž„αž…αž„αŸ‹αžŸαž˜αŸ’αžšαŸαž…αž”αžΆαž“αž“αžΉαž„αž‡αžΆαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαŸαžŸαžΆαž˜αž‰αŸ’αž‰αž˜αž½αž™αŸ”

αž€αŸ†αžŽαžαŸ‹αžŸαŸ†αž‚αžΆαž›αŸ‹αŸ” αž’αžΆαž‡αžΈαžœαž€αž˜αŸ’αž˜ PRO-TIP αŸ” αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαžΆαž˜αž‰αŸ’αž‰αž’αžΆαž…αž‡αž½αž™αž’αŸ’αž“αž€αžŸαž“αŸ’αžŸαŸ†αž”αŸ’αžšαžΆαž€αŸ‹αž”αžΆαž“αž…αŸ’αžšαžΎαž“αž›αžΎαž€αžΆαžšαž‚αžΆαŸ†αž‘αŸ’αžš (αž˜αž“αž»αžŸαŸ’αžŸαž€αžΆαž“αŸ‹αžαŸ‚αž…αŸ’αžšαžΎαž“αžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αžΆαž“αž’αŸ’αžœαžΎαž€αžΆαžšαž±αŸ’αž™αž€αŸ’αžšαž»αž˜αž αŸŠαž»αž“αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€ αž”αŸ’αžšαžΆαž€αŸ‹αž€αžΆαž“αŸ‹αžαŸ‚αž…αŸ’αžšαžΎαž“αž’αŸ’αž“αž€αž’αžΆαž…αžŸαž“αŸ’αžŸαŸ†αž”αžΆαž“)!

αž˜αž·αž“αž…αžΆαŸ†αž”αžΆαž…αŸ‹αžαŸ’αžšαž‘αž”αŸ‹αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž‘αŸαŸ”

αžœαžΆαž‡αž½αž™αžŸαž˜αŸ’αžšαž½αž›αžŠαž›αŸ‹αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ (αž€αžΆαžšαžœαž·αž›αžαŸ’αžšαž‘αž”αŸ‹αž˜αž€αžœαž·αž‰αž“αŸƒαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž˜αž½αž™αž…αŸ†αž“αž½αž“αž‚αžΊαžŸαŸ’αž‘αžΎαžšαžαŸ‚αž˜αž·αž“αž’αžΆαž…αž‘αŸ…αžšαž½αž…αž‘αŸ αžŠαžΌαž…αž‡αžΆαž€αžΆαžšαž›αž»αž”αž‘αžΎαž„αžœαž·αž‰)αŸ” αž™αžΎαž„αž…αž„αŸ‹αžαŸ’αžšαž‘αž”αŸ‹αžαŸ‚αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ” αžœαž·αž’αžΈαž“αŸαŸ‡ αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαž’αŸ’αž“αž€αž˜αžΆαž“αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž•αŸ’αžŸαŸαž„αž‚αŸ’αž“αžΆ (αž§αž‘αžΆαž αžšαžŽαŸ SQL αž“αž·αž„ NoSQL) αž”αŸ†αž–αž„αŸ‹αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž“αžΉαž„αž˜αžΎαž›αž‘αŸ…αžŠαžΌαž…αž‚αŸ’αž“αžΆαŸ”

αžœαžΆαžαŸ’αžšαžΌαžœαžαŸ‚αž’αžΆαž…αž’αŸ’αžœαžΎαž‘αŸ…αž”αžΆαž“αžŠαžΎαž˜αŸ’αž”αžΈαžšαž˜αŸ€αž›αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžαŸ’αžšαž‘αž”αŸ‹αž˜αž€αžœαž·αž‰αž€αŸ†αžŽαŸ‚αž˜αž½αž™αžαŸ’αžšαž‘αž”αŸ‹αž˜αž€αžœαž·αž‰ (αž˜αž·αž“αž˜αžΆαž“αž‘αŸ€αžαž‘αŸ)

Rollback αž‚αž½αžšβ€‹αžαŸ‚β€‹αžαŸ’αžšαžΌαžœβ€‹αž”αžΆαž“β€‹αž’αŸ’αžœαžΎβ€‹αž“αŸ…β€‹αž–αŸαž›β€‹αž…αžΆαŸ†αž”αžΆαž…αŸ‹αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž˜αžΆαž“αž€αŸ†αž αž»αžŸαž“αŸ…αž€αŸ’αž“αž»αž„αž€αŸ†αžŽαŸ‚αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αžŠαŸ‚αž›αž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‡αž½αžŸαž‡αž»αž›αž™αŸ‰αžΆαž„αž„αžΆαž™αžŸαŸ’αžšαž½αž›αž“αŸ„αŸ‡ αž™αžΎαž„αž‚αž½αžšαžαŸ‚αž’αžΆαž…αžαŸ’αžšαž‘αž”αŸ‹αž‘αŸ…αž€αŸ†αžŽαŸ‚αžŠαŸ‚αž›αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž…αž»αž„αž€αŸ’αžšαŸ„αž™αž”αŸ†αž•αž»αžαŸ” αž™αžΎαž„αžŸαž“αŸ’αž˜αžαŸ‹αžαžΆαž€αŸ†αžŽαŸ‚αž…αž»αž„αž€αŸ’αžšαŸ„αž™αž”αŸ†αž•αž»αžαž“αŸαŸ‡αž‚αžΊαž‡αžΆαž€αŸ†αžŽαŸ‚αž˜αž»αž“αŸ” αž€αžΆαžšαžšαž€αŸ’αžŸαžΆαž—αžΆαž–αžαŸ’αžšαžΌαžœαž‚αŸ’αž“αžΆαž“αŸƒαž€αžΌαžŠ αž“αž·αž„αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž…αŸαž‰αž•αŸ’αžŸαžΆαž™αž…αŸ’αžšαžΎαž“αž‡αžΆαž„αž˜αž½αž™αž“αžΉαž„αž–αž·αž”αžΆαž€ αž“αž·αž„αžαŸ’αž›αŸƒαžŽαžΆαžŸαŸ‹αŸ”

αž€αŸ†αžŽαžαŸ‹αžŸαŸ†αž‚αžΆαž›αŸ‹. αžŠαžΎαž˜αŸ’αž”αžΈαž±αŸ’αž™αž€αžΆαž“αŸ‹αžαŸ‚αž„αžΆαž™αžŸαŸ’αžšαž½αž›αž’αžΆαž“ αž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡ αž™αžΎαž„αž“αžΉαž„αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž€αŸ†αžŽαŸ‚αžŸαŸ†αžαžΆαž“αŸ‹αŸ—αž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαŸ”

αž‡αŸ†αž αžΆαž“αž‘αžΈ 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 αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ (αž”αŸ’αžšαž αŸ‚αž› per.: αž’αŸ’αž“αž€αž“αž·αž–αž“αŸ’αž’αž”αŸ’αžšαž αŸ‚αž›αž‡αžΆαž˜αžΆαž“αž“αŸαž™αžαžΆαž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αž 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 αžŠαŸ„αž™αžŠαŸƒ αž αžΎαž™αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžŠαžΆαž€αŸ‹αž±αŸ’αž™αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžαŸ’αž˜αžΈ)αŸ”

αžœαžΆαžŸαŸ†αžαžΆαž“αŸ‹αžŽαžΆαžŸαŸ‹αŸ” αž…αž„αž…αžΆαŸ†αžαžΆαž‡αž½αžšαžˆαžšαžŠαŸ‚αž›αž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαžαŸ’αž˜αžΈαŸ” αž˜αž·αž“β€‹αž‚αž½αžš αžŠαžΎαž˜αŸ’αž”αžΈαž±αŸ’αž™αž˜αžΆαž“αŸ” αž˜αž·αž“αž˜αŸ‚αž“αž‘αŸ. αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž’αŸ’αžœαžΎ rollback αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž…αžΆαžŸαŸ‹αž˜αž·αž“αžŠαžΉαž„αž’αŸ†αž–αžΈαž‡αž½αžšαžˆαžšαžαŸ’αž˜αžΈ αž αžΎαž™αž“αžΉαž„αž˜αž·αž“αžŠαŸ†αž‘αžΎαž„αžœαžΆαž’αŸ†αž‘αž»αž„αž–αŸαž› 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 column) αž’αŸ’αž“αž€αž’αžΆαž…αž˜αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž˜αž·αž“αžŸαŸŠαžΈαžŸαž„αŸ’αžœαžΆαž€αŸ‹αž‚αŸ’αž“αžΆ αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αžŸαž½αžšαž‡αž½αžšαžˆαžšαžαŸ’αž˜αžΈαŸ”

αž€αžΆαžšβ€‹αžαŸ’αžšαž‘αž”αŸ‹β€‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈβ€‹

αž₯αž‘αžΌαžœαž“αŸαŸ‡αž™αžΎαž„αž˜αžΆαž“αž€αŸ†αžŽαŸ‚αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ 2.0.0 αž“αž·αž„αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž“αŸ…αž€αŸ’αž“αž»αž„ v2.

αž‡αŸ†αž αžΆαž“αŸ–

  1. αžαŸ’αžšαž‘αž”αŸ‹αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž‘αŸ…αž‡αžΆαž€αŸ†αžŽαŸ‚ 1.0.0.
  2. αž€αŸ†αžŽαŸ‚ 1.0.0 αž˜αž·αž“αž”αŸ’αžšαžΎαž‡αž½αžšαžˆαžšαž€αŸ’αž“αž»αž„αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž‘αŸαŸ” surnameαžŠαžΌαž…αŸ’αž“αŸαŸ‡ rollback αž‚αž½αžšαžαŸ‚αž‘αž‘αž½αž›αž”αžΆαž“αž‡αŸ„αž‚αž‡αŸαž™

αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžš DB

αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž˜αžΆαž“αž‡αž½αžšαžˆαžšαžŠαŸ‚αž›αž˜αžΆαž“αžˆαŸ’αž˜αŸ„αŸ‡ last_name.

αž”αŸ’αžšαž—αž–αžŸαŸ’αž‚αŸ’αžšαžΈαž” 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');

αž”αž“αŸ’αžαŸ‚αž˜αžŸαŸ’αž‚αŸ’αžšαžΈαž” surname.

αž€αžΆαžšαž™αž€αž…αž·αžαŸ’αžαž‘αž»αž€αžŠαžΆαž€αŸ‹αŸ” αžŸαžΌαž˜αž…αž„αž…αžΆαŸ†αžαžΆαž’αŸ’αž“αž€αž˜αž·αž“αž’αžΆαž…αž”αž“αŸ’αžαŸ‚αž˜αž§αž”αžŸαž‚αŸ’αž‚αžŠαŸ‚αž›αž˜αž·αž“αž˜αŸ‚αž“αž‡αžΆ 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: αž€αžΆαžšαžŠαž€αžˆαŸ’αž˜αŸ„αŸ‡αž…αž»αž„αž€αŸ’αžšαŸ„αž™αž…αŸαž‰αž–αžΈαž›αŸαžαž€αžΌαžŠ

αž€αŸ†αžŽαŸ‚αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαŸ– 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: αž€αžΆαžšαžŠαž€αžˆαŸ’αž˜αŸ„αŸ‡αž…αž»αž„αž€αŸ’αžšαŸ„αž™αž…αŸαž‰αž–αžΈαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™

αž€αŸ†αžŽαŸ‚αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαŸ– 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. (αž…αŸ†αžŽαžΆαŸ†αŸ– αž‡αž½αžšβ€‹αžˆαžšβ€‹αž“αŸαŸ‡β€‹αž˜αž·αž“β€‹αžαŸ’αžšαžΌαžœβ€‹αž˜αžΆαž“β€‹αž€αž˜αŸ’αžšαž·αžβ€‹αž˜αž·αž“β€‹αž‘αž»αž€β€‹αž‡αžΆβ€‹αž˜αŸ„αžƒαŸˆβ€‹αž‘αŸ)
  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

αž§αž‘αžΆαž αžšαžŽαŸαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αžαŸ’αžšαžΌαžœαž”αžΆαž“αž™αž€αž…αŸαž‰αž–αžΈ Spring Boot Sample Flyway.

αž’αŸ’αž“αž€αž’αžΆαž…αž˜αžΎαž› http://localhost:8080/flywayαž˜αžΆαž“αž”αž‰αŸ’αž‡αžΈαžŸαŸ’αž‚αŸ’αžšαžΈαž”αŸ”

αž§αž‘αžΆαž αžšαžŽαŸαž“αŸαŸ‡αž€αŸαžšαž½αž˜αž”αž‰αŸ’αž…αžΌαž›αž€αž»αž„αžŸαžΌαž› H2 (αž“αŸ… http://localhost:8080/h2-console) αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž’αŸ’αž“αž€αž’αžΆαž…αž˜αžΎαž›αžŸαŸ’αžαžΆαž“αž—αžΆαž–αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™ (αž›αŸ†αž“αžΆαŸ†αžŠαžΎαž˜ jdbc URL αž‚αžΊ jdbc:h2:mem:testdb).

αž›αžΎαžŸαž–αžΈαž“αŸαŸ‡αž‘αŸ€αž

αžŸαžΌαž˜αž’αžΆαž“αž’αžαŸ’αžαž”αž‘αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαž“αŸ…αž›αžΎαž”αŸ’αž›αž€αŸ‹αžšαž”αžŸαŸ‹αž™αžΎαž„αž•αž„αžŠαŸ‚αžšαŸ–

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹