\n \u003Cinclude relativeToChangelogFile=\"true\" file=\"install/all/procedures.xml\"/>\n ...\n \u003Cinclude relativeToChangelogFile=\"true\" file=\"changes/all/table_add_column_xyz.xml\"/>\n \u003Cinclude relativeToChangelogFile=\"true\" file=\"changes/${projectname.branch}/adjust_procedure_asd.xml\"/>\n ...\n\u003C/databaseChangeLog>\n",[99,445,446,451,456,461,466,471,476,481,486,491,495],{"__ignoreMap":97},[102,447,448],{"class":104,"line":105},[102,449,450],{},"\u003C?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",[102,452,453],{"class":104,"line":111},[102,454,455],{},"\u003CdatabaseChangeLog xmlns=\"http://www.liquibase.org/xml/ns/dbchangelog\"\n",[102,457,458],{"class":104,"line":117},[102,459,460],{}," xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n",[102,462,463],{"class":104,"line":123},[102,464,465],{}," xsi:schemaLocation=\"http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd\">\n",[102,467,468],{"class":104,"line":129},[102,469,470],{}," \u003Cinclude relativeToChangelogFile=\"true\" file=\"install/all/tables.xml\"/>\n",[102,472,473],{"class":104,"line":135},[102,474,475],{}," \u003Cinclude relativeToChangelogFile=\"true\" file=\"install/all/procedures.xml\"/>\n",[102,477,478],{"class":104,"line":141},[102,479,480],{}," ...\n",[102,482,483],{"class":104,"line":147},[102,484,485],{}," \u003Cinclude relativeToChangelogFile=\"true\" file=\"changes/all/table_add_column_xyz.xml\"/>\n",[102,487,488],{"class":104,"line":153},[102,489,490],{}," \u003Cinclude relativeToChangelogFile=\"true\" file=\"changes/${projectname.branch}/adjust_procedure_asd.xml\"/>\n",[102,492,493],{"class":104,"line":159},[102,494,480],{},[102,496,497],{"class":104,"line":165},[102,498,499],{},"\u003C/databaseChangeLog>\n",[18,501,502,503,510],{},"As you can see, we have used the ",[504,505,506],"strong",{},[507,508,509],"em",{},"${projectname.branch}"," placeholder in the path of a changelog. The file that is\nreferenced there, has to be added for each of the branches, because this changelog is also used for every branch. This\ncan be somewhat inconvenient in some times, when you only have to add a change to one of the branches, but that should\nnot happen that often. It’s more likely (at least for our case) that you have to adjust the same thing for all branches,\nbut a little differnt, or fill some table with different data.",[18,512,513],{},"Also, the right execution order of the scripts is secured this way. Furthermore, we don’t have to create and update one\nchangelog for every branch, where it can easily happen, that one file is left out and it goes through unnoticed. In our\nsetup, if you forget to add a file that’s declared in the changelog, that’s another case, because you will know it as\nsoon as you execute the script for the specific branch. So we considered this to be the best method to address multiple\nbranches.",[18,515,516,517,520,521,524],{},"You can also use the placeholder in other places, like the ",[507,518,519],{},"loadUpdateData"," tag, where you can specify a .csv file from\nwhich liquibase will load data. There, You’ll only need to add the changelog to the ‘",[507,522,523],{},"all","‘ folder and the .csv files in\neach branch folder. Furthermore, we are",[81,526,528],{"id":527},"maven-profiles","maven profiles",[18,530,531],{},"To configure and execute liquibase, we use different maven profiles. We need to specify the url, username and password\nfor each server, so we have one profile for each of them. The properties that are the same based on the environment (\ntest, stage, prod), are defined in a config file included from the pom (as already seen above), so we also need to add a\nproperty for the environment in each profile. Like this we can create a liquibase profile for each application of an\nenvironment of a branch (yup, there are quite some profiles because of this, but it is simply needed – you don’t have to\nkeep them in your settings.xml all the time, though, so it isn’t that much of a pain, once they are created 😛 ). By\nsetting the username and password locally in the maven settings.xml, we also keep sure that no passwords are commited in\nour version control.",[18,533,534],{},"example profile:",[92,536,538],{"className":94,"code":537,"language":96,"meta":97,"style":97},"\n \u003Cprofile>\n \u003Cid>xyz-test\u003C/id>\n \u003Cproperties>\n \u003Cprojectname.branch>xyz\u003C/projectname.branch>\n \u003Cprojectname.environment>test\u003C/projectname.environment>\n \u003Cprojectname.dbName>dbname\u003C/projectname.dbName>\n \u003Cprojectname.liquibase.url>jdbc:oracle:thin:@192.168.224.234:1521:DBID\u003C/projectname.liquibase.url>\n \u003Cprojectname.liquibase.username>username\u003C/projectname.liquibase.username>\n \u003Cprojectname.liquibase.password>password\u003C/projectname.liquibase.password>\n \u003Cprojectname.liquibase.schemaName>schema\u003C/projectname.liquibase.schemaName>\n \u003Cprojectname.liquibase.changeLogFile>target/classes/path/to/changelog/db.changelog.xml\u003C/projectname.liquibase.changeLogFile>\n \u003C/properties>\n \u003C/profile>\n",[99,539,540,546,551,556,561,566,571,576,581,586,591,596,601,606],{"__ignoreMap":97},[102,541,542],{"class":104,"line":105},[102,543,545],{"emptyLinePlaceholder":544},true,"\n",[102,547,548],{"class":104,"line":111},[102,549,550],{}," \u003Cprofile>\n",[102,552,553],{"class":104,"line":117},[102,554,555],{}," \u003Cid>xyz-test\u003C/id>\n",[102,557,558],{"class":104,"line":123},[102,559,560],{}," \u003Cproperties>\n",[102,562,563],{"class":104,"line":129},[102,564,565],{}," \u003Cprojectname.branch>xyz\u003C/projectname.branch>\n",[102,567,568],{"class":104,"line":135},[102,569,570],{}," \u003Cprojectname.environment>test\u003C/projectname.environment>\n",[102,572,573],{"class":104,"line":141},[102,574,575],{}," \u003Cprojectname.dbName>dbname\u003C/projectname.dbName>\n",[102,577,578],{"class":104,"line":147},[102,579,580],{}," \u003Cprojectname.liquibase.url>jdbc:oracle:thin:@192.168.224.234:1521:DBID\u003C/projectname.liquibase.url>\n",[102,582,583],{"class":104,"line":153},[102,584,585],{}," \u003Cprojectname.liquibase.username>username\u003C/projectname.liquibase.username>\n",[102,587,588],{"class":104,"line":159},[102,589,590],{}," \u003Cprojectname.liquibase.password>password\u003C/projectname.liquibase.password>\n",[102,592,593],{"class":104,"line":165},[102,594,595],{}," \u003Cprojectname.liquibase.schemaName>schema\u003C/projectname.liquibase.schemaName>\n",[102,597,598],{"class":104,"line":171},[102,599,600],{}," \u003Cprojectname.liquibase.changeLogFile>target/classes/path/to/changelog/db.changelog.xml\u003C/projectname.liquibase.changeLogFile>\n",[102,602,603],{"class":104,"line":177},[102,604,605],{}," \u003C/properties>\n",[102,607,608],{"class":104,"line":183},[102,609,610],{}," \u003C/profile>\n",[18,612,613],{},"With this config, it uses the property file target/classes/liquibase-test.properties (keep in mind, the file initially\nlies in the folder src/main/resources, but because we build the project before we execute liquibase, it is then located\nunder target/classes/ , with its parameters replaced by our properties).",[18,615,616],{},"liquibase-test.properties:",[92,618,620],{"className":334,"code":619,"language":336,"meta":97,"style":97},"changeLogFile=${projectname.liquibase.changeLogFile}\ndriver=oracle.jdbc.OracleDriver\nurl=${projectname.liquibase.url}\nusername=${projectname.liquibase.username}\npassword=${projectname.liquibase.password}\ndefaultSchemaName=${projectname.liquibase.schemaName}\nverbose=true\ndropFirst=false\n",[99,621,622,627,632,637,642,647,652,657],{"__ignoreMap":97},[102,623,624],{"class":104,"line":105},[102,625,626],{},"changeLogFile=${projectname.liquibase.changeLogFile}\n",[102,628,629],{"class":104,"line":111},[102,630,631],{},"driver=oracle.jdbc.OracleDriver\n",[102,633,634],{"class":104,"line":117},[102,635,636],{},"url=${projectname.liquibase.url}\n",[102,638,639],{"class":104,"line":123},[102,640,641],{},"username=${projectname.liquibase.username}\n",[102,643,644],{"class":104,"line":129},[102,645,646],{},"password=${projectname.liquibase.password}\n",[102,648,649],{"class":104,"line":135},[102,650,651],{},"defaultSchemaName=${projectname.liquibase.schemaName}\n",[102,653,654],{"class":104,"line":141},[102,655,656],{},"verbose=true\n",[102,658,659],{"class":104,"line":147},[102,660,661],{},"dropFirst=false\n",[18,663,664],{},"Here we map our properties from the profiles to the actual liquibase property names and also set a few other liquibase\nconfigs.",[18,666,667],{},"For scripts you need to execute in another schema as the one the db user has set as the default schema, we also set the\ndefaultSchemaName property of liquibase (mainly the case, if we execute scripts as the SYSDBA user).",[30,669,671],{"id":670},"execution-conclusion","Execution & Conclusion",[18,673,674],{},"Because of the use of maven, we can execute all of the changes from our local machines very easy:",[92,676,678],{"className":334,"code":677,"language":336,"meta":97,"style":97},"mvn clean install -Pxyz-test\n",[99,679,680],{"__ignoreMap":97},[102,681,682],{"class":104,"line":105},[102,683,677],{},[18,685,686],{},"If you connect against a remote server, you are even warned with a dialogue that contains the database name, url and\nusername, it wants to execute the scripts on, before the scripts are actually executed. So you can check them again and\nabort the migration if you used the wrong profile.",[18,688,689],{},"With this setup we can now add scripts for only one branch, multiple branches, or all branches, without having to worry\nto forget to add one change to a branch and leaving the error unnoticed. Even if we forget to put some file in the\nfolder of one branch, our changelog file is global for all branches! So if we try to execute it the next time, liquibase\nnotices the missing file and informs us about this (and aborts the execution). And because we don’t have different\nfolders for the environments, but only the branches, this gets noticed on the test machines.",[18,691,692],{},"Please let us know what you think of our approach and if you know an even better one!",[694,695,696],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":97,"searchDepth":111,"depth":111,"links":698},[699,700,706],{"id":32,"depth":111,"text":33},{"id":78,"depth":111,"text":79,"children":701},[702,703,704,705],{"id":83,"depth":117,"text":84},{"id":327,"depth":117,"text":328},{"id":436,"depth":117,"text":437},{"id":527,"depth":117,"text":528},{"id":670,"depth":111,"text":671},[708],"developer-blog","2013-04-12T11:19:55","In this post, we want to show you our Liquibase setup in a larger scale project that we’ve\\nbeen developing for some time now.","md","https://synyx.de/blog/liquibase-our-setup-in-a-larger-scale-project/",{},"/blog/liquibase-our-setup-in-a-larger-scale-project",{"title":7,"description":716},"In this post, we want to show you our Liquibase setup in a larger scale project that we’ve\nbeen developing for some time now.","blog/liquibase-our-setup-in-a-larger-scale-project",[719,720,721,722],"database","database-change-management","database-migration","liquibase","In this post, we want to show you our Liquibase setup in a larger scale project that we’ve been developing for some time now. Gather Requirements First off, a bit…","Edhd0rsE8wWORJZowAN7nLiXbUivWvpaqbjev0vh3MQ",[726,729,732,735,738,741,744,747,750,753,756,759,762,765,768,771,774,777,780,783,786,789,791,794,797,800,803,805,808,811,814,817,820,823,826,829,832,835,838,841,844,847,850,853,856,859,862,865,868,871,874,877,880,883,886,889,892,895,898,901,904,907,910,912,915,918,921,924,927,930,933,936,939,942,945,948,951,954,957,960,963,966,969,972,975,978,981,984,987,990,993,996,999,1002,1005,1008,1011,1014,1017,1019,1022,1025,1028,1031,1033,1036,1039,1042,1045,1048,1051,1054,1057,1060,1063,1066,1069,1072,1075,1078,1081,1084,1087,1090,1093,1096,1099,1102,1105,1108,1110,1113,1116,1119,1122,1125,1128,1131,1134,1137,1140,1143],{"slug":727,"name":728},"abel","Jennifer Abel",{"slug":730,"name":731},"allmendinger","Otto Allmendinger",{"slug":733,"name":734},"antony","Ben Antony",{"slug":736,"name":737},"arrasz","Joachim Arrasz",{"slug":739,"name":740},"bauer","David Bauer",{"slug":742,"name":743},"bechtold","Janine Bechtold",{"slug":745,"name":746},"boersig","Jasmin Börsig",{"slug":748,"name":749},"buch","Fabian Buch",{"slug":751,"name":752},"buchloh","Aljona Buchloh",{"slug":754,"name":755},"burgard","Julia Burgard",{"slug":757,"name":758},"caspar-schwedes","Caspar Schwedes",{"slug":760,"name":761},"christina-schmitt","Christina Schmitt",{"slug":763,"name":764},"clausen","Michael Clausen",{"slug":766,"name":767},"contargo_poetzsch","Thomas Pötzsch",{"slug":769,"name":770},"damrath","Sebastian Damrath",{"slug":772,"name":773},"daniel","Markus Daniel",{"slug":775,"name":776},"dasch","Julia Dasch",{"slug":778,"name":779},"denman","Joffrey Denman",{"slug":781,"name":782},"dfuchs","Daniel Fuchs",{"slug":784,"name":785},"dobler","Max Dobler",{"slug":787,"name":788},"dobriakov","Vladimir Dobriakov",{"slug":790,"name":790},"dreiqbik",{"slug":792,"name":793},"dschaefer","Denise Schäfer",{"slug":795,"name":796},"dschneider","Dominik Schneider",{"slug":798,"name":799},"duerlich","Isabell Duerlich",{"slug":801,"name":802},"dutkowski","Bernd Dutkowski",{"slug":804,"name":804},"eifler",{"slug":806,"name":807},"essig","Tim Essig",{"slug":809,"name":810},"ferstl","Maximilian Ferstl",{"slug":812,"name":813},"fey","Prisca Fey",{"slug":815,"name":816},"frank","Leonard Frank",{"slug":818,"name":819},"franke","Arnold Franke",{"slug":821,"name":822},"frischer","Nicolette Rudmann",{"slug":824,"name":825},"fuchs","Petra Fuchs",{"slug":827,"name":828},"gari","Sarah Gari",{"slug":830,"name":831},"gast","Gast",{"slug":833,"name":834},"graf","Johannes Graf",{"slug":836,"name":837},"grammlich","Daniela Grammlich",{"slug":839,"name":840},"guthardt","Sabrina Guthardt",{"slug":842,"name":843},"haeussler","Johannes Häussler",{"slug":845,"name":846},"hammann","Daniel Hammann",{"slug":848,"name":849},"heetel","Julian Heetel",{"slug":851,"name":852},"heft","Florian Heft",{"slug":854,"name":855},"heib","Sebastian Heib",{"slug":857,"name":858},"heisler","Ida Heisler",{"slug":860,"name":861},"helm","Patrick Helm",{"slug":863,"name":864},"herbold","Michael Herbold",{"slug":866,"name":867},"hofmann","Peter Hofmann",{"slug":869,"name":870},"hopf","Florian Hopf",{"slug":872,"name":873},"jaud","Alina Jaud",{"slug":875,"name":876},"jayasinghe","Robin De Silva Jayasinghe",{"slug":878,"name":879},"jbuch","Jonathan Buch",{"slug":881,"name":882},"junghanss","Gitta Junghanß",{"slug":884,"name":885},"kadyietska","Khrystyna Kadyietska",{"slug":887,"name":888},"kannegiesser","Marc Kannegiesser",{"slug":890,"name":891},"karoly","Robert Károly",{"slug":893,"name":894},"karrasz","Katja Arrasz-Schepanski",{"slug":896,"name":897},"kaufmann","Florian Kaufmann",{"slug":899,"name":900},"kesler","Mike Kesler",{"slug":902,"name":903},"kirchgaessner","Bettina Kirchgäßner",{"slug":905,"name":906},"klem","Yannic Klem",{"slug":908,"name":909},"klenk","Timo Klenk",{"slug":9,"name":911},"Tobias Knell",{"slug":913,"name":914},"knoll","Anna-Lena Knoll",{"slug":916,"name":917},"knorre","Matthias Knorre",{"slug":919,"name":920},"koenig","Melanie König",{"slug":922,"name":923},"kraft","Thomas Kraft",{"slug":925,"name":926},"krupicka","Florian Krupicka",{"slug":928,"name":929},"kuehn","Christian Kühn",{"slug":931,"name":932},"lange","Christian Lange",{"slug":934,"name":935},"larrasz","Luca Arrasz",{"slug":937,"name":938},"leist","Sascha Leist",{"slug":940,"name":941},"lihs","Michael Lihs",{"slug":943,"name":944},"linsin","David Linsin",{"slug":946,"name":947},"maniyar","Christian Maniyar",{"slug":949,"name":950},"martin","Björnie",{"slug":952,"name":953},"martin-koch","Martin Koch",{"slug":955,"name":956},"matt","Tobias Matt",{"slug":958,"name":959},"mennerich","Christian Mennerich",{"slug":961,"name":962},"menz","Alexander Menz",{"slug":964,"name":965},"meseck","Frederick Meseck",{"slug":967,"name":968},"messner","Oliver Messner",{"slug":970,"name":971},"michael-ploed","Michael Plöd",{"slug":973,"name":974},"mies","Marius Mies",{"slug":976,"name":977},"mihai","Alina Mihai",{"slug":979,"name":980},"moeller","Jörg Möller",{"slug":982,"name":983},"mohr","Rebecca Mohr",{"slug":985,"name":986},"moretti","David Moretti",{"slug":988,"name":989},"mueller","Sven Müller",{"slug":991,"name":992},"muessig","Alexander Müssig",{"slug":994,"name":995},"neupokoev","Grigory Neupokoev",{"slug":997,"name":998},"nussbaecher","Carmen Nussbächer",{"slug":1000,"name":1001},"ochs","Pascal Ochs",{"slug":1003,"name":1004},"oelhoff","Jan Oelhoff",{"slug":1006,"name":1007},"oengel","Yasin Öngel",{"slug":1009,"name":1010},"oezsoy","Enis Özsoy",{"slug":1012,"name":1013},"posch","Maya Posch",{"slug":1015,"name":1016},"ralfmueller","Ralf Müller",{"slug":1018,"name":1018},"redakteur",{"slug":1020,"name":1021},"reich","Michael Reich",{"slug":1023,"name":1024},"reinhard","Karl-Ludwig Reinhard",{"slug":1026,"name":1027},"rmueller","Rebecca Müller",{"slug":1029,"name":1030},"rosum","Jan Rosum",{"slug":1032,"name":1032},"rueckert",{"slug":1034,"name":1035},"ruessel","Sascha Rüssel",{"slug":1037,"name":1038},"sauter","Moritz Sauter",{"slug":1040,"name":1041},"schaefer","Julian Schäfer",{"slug":1043,"name":1044},"scherer","Petra Scherer",{"slug":1046,"name":1047},"schlicht","Anne Schlicht",{"slug":1049,"name":1050},"schmidt","Jürgen Schmidt",{"slug":1052,"name":1053},"schneider","Tobias Schneider",{"slug":1055,"name":1056},"seber","Benjamin Seber",{"slug":1058,"name":1059},"sommer","Marc Sommer",{"slug":1061,"name":1062},"speaker-fels","Jakob Fels",{"slug":1064,"name":1065},"speaker-gierke","Oliver Gierke",{"slug":1067,"name":1068},"speaker-krupa","Malte Krupa",{"slug":1070,"name":1071},"speaker-mader","Jochen Mader",{"slug":1073,"name":1074},"speaker-meusel","Tim Meusel",{"slug":1076,"name":1077},"speaker-milke","Oliver Milke",{"slug":1079,"name":1080},"speaker-paluch","Mark Paluch",{"slug":1082,"name":1083},"speaker-schad","Jörg Schad",{"slug":1085,"name":1086},"speaker-schalanda","Jochen Schalanda",{"slug":1088,"name":1089},"speaker-schauder","Jens Schauder",{"slug":1091,"name":1092},"speaker-unterstein","Johannes Unterstein",{"slug":1094,"name":1095},"speaker-wolff","Eberhard Wolff",{"slug":1097,"name":1098},"speaker-zoerner","Stefan Zörner",{"slug":1100,"name":1101},"stefan-belger","Stefan Belger",{"slug":1103,"name":1104},"steinegger","Roland Steinegger",{"slug":1106,"name":1107},"stern","sternchen synyx",{"slug":1109,"name":1109},"synyx",{"slug":1111,"name":1112},"szulc","Mateusz Szulc",{"slug":1114,"name":1115},"tamara","Tamara Tunczinger",{"slug":1117,"name":1118},"theuer","Tobias Theuer",{"slug":1120,"name":1121},"thieme","Sandra Thieme",{"slug":1123,"name":1124},"thies-clasen","Marudor",{"slug":1126,"name":1127},"toernstroem","Olle Törnström",{"slug":1129,"name":1130},"ullinger","Max Ullinger",{"slug":1132,"name":1133},"ulrich","Stephan Ulrich",{"slug":1135,"name":1136},"wagner","Stefan Wagner",{"slug":1138,"name":1139},"weigel","Andreas Weigel",{"slug":1141,"name":1142},"werner","Fabian Werner",{"slug":1144,"name":1145},"wolke","Sören Wolke",["Reactive",1147],{"$scookieConsent":1148,"$ssite-config":1150},{"functional":1149,"analytics":1149},false,{"_priority":1151,"env":1155,"name":1156,"url":1157},{"name":1152,"env":1153,"url":1154},-10,-15,0,"production","nuxt-app","https://synyx.de",["Set"],["ShallowReactive",1160],{"category-database-migration":-1,"authors":-1},"/blog/tags/database-migration"]