Last modified by christoph_lechleitner@iteg_at on 2013-01-31 07.32:56
From version 2.1
edited by 5fbc055b7cc103006957e1ae
on 2012-06-14 06.29:38
on 2012-06-14 06.29:38
Change comment:
There is no comment for this version
To version 5.1
edited by christoph_lechleitner@iteg_at
on 2013-01-31 06.18:32
on 2013-01-31 06.18:32
Change comment:
There is no comment for this version
Summary
-
Page properties (2 modified, 0 added, 0 removed)
-
Objects (1 modified, 0 added, 0 removed)
Details
- Page properties
-
- Author
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki. 5fbc055b7cc103006957e1ae1 +XWiki.christoph_lechleitner@iteg_at - Content
-
... ... @@ -1,9 +1,11 @@ 1 1 = {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-Preliminary"/}}Preliminary = 2 2 3 -The SchemaManager and SchemaEngine giveyouanabstractedaccessto the database schemaofyourapplication, allowing you to add and delete tables, columns, relations and data in the database on application updates.It uses a designated table to keep track of the current schema status, which it will check whenever it is run, and update the database if it is not at the correct version.3 +The SchemaManager ({{code language="none"}}org.clazzes.jdbc2xml.schema.SchemaManager{{/code}}) and SchemaEngine provide means to maintain the database scheme of an application, allowing you to add and delete tables, columns, relations and data in the database along application updates. 4 4 5 - SchemaManager({{codelanguage="none"}}org.clazzes.jdbc2xml.schema.SchemaManager{{/code}}) willcreateatablecalledSCHEMA_HISTORY if it cannot find itthefirst timeit isrun.This tablecontainsthe followingcolumns:5 +==== {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-SchemaHistoryTable"/}}Schema History Table ==== 6 6 7 +A designated schema table, by default named SCHEMA_HISTORY, is used to keep track of the current scheme. It will be automatically at SchemaManager's first run. (% style="font-size: 10.0pt;line-height: 13.0pt;" %)SCHEMA_HISTORY contains the following columns: 8 + 7 7 {{code language="none"}} 8 8 VERSION:varchar(10), not null, primary key 9 9 DESCRIPTION:varchar(512), nullable ... ... @@ -11,17 +11,21 @@ 11 11 SERIALNR:integer(5), not null 12 12 {{/code}} 13 13 16 +In (% style="font-size: 10.0pt;font-weight: normal;line-height: 13.0pt;" %)heterogenous environments as well as in heavily modularized software architectures a single database may be shared by multiple parties each requiring a couple of tables. 17 + 18 +(% style="font-size: 10.0pt;font-weight: normal;line-height: 13.0pt;" %)To allow multiple modules (applications, libraries, other OSGi bundles) to use (% style="font-size: 10.0pt;line-height: 13.0pt;" %)JDBC2XML's SchemaManager concurrently within one database, as of JDBC 1.1.1 SchemaManager hold the name of the schema history table in an overwritable property, {{code language="none"}}versionHistoryTable{{/code}}. See (%%)[[JDBCTOXML-11>>url:https://jira.clazzes.org/browse/JDBCTOXML-11||shape="rect"]](% style="font-size: 10.0pt;line-height: 13.0pt;" %). 19 + 14 14 = {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-ProjectConfiguration"/}}Project Configuration = 15 15 16 - To function correctly,SchemaManagerneeds a DataSource ({{code language="none"}}javax.sql.DataSource{{/code}}) and a list of TableInfo ({{code language="none"}}org.clazzes.jdbc2xml.schema.TableInfo{{/code}}) Objects, from whichadatabase will be created ifit findsan empty database.Tofunctionproperly, it alsoneedsan implementation of ISchemaEngine ({{code language="none"}}org.clazzes.jdbc2xml.schema.ISchemaEngine{{/code}}).22 +SchemaManager requires a DataSource ({{code language="none"}}javax.sql.DataSource{{/code}}) and a list of TableInfo ({{code language="none"}}org.clazzes.jdbc2xml.schema.TableInfo{{/code}}) Objects, from which database structures will be created if an "empty" database is detected. Furthermore, an implementation of ISchemaEngine ({{code language="none"}}org.clazzes.jdbc2xml.schema.ISchemaEngine{{/code}}) is required. 17 17 18 -Optionally, you mayset thebase version (default value 0.1.00) and base description String (default "initial database schema").24 +Optionally, a base version (default value 0.1.00) and a base description String (default "initial database schema") may be specified. 19 19 20 20 Database updates are passed as a Map<String, ISchemaUpdateSnippet> (org.clazzes.jdbc2xml.schema.ISchemaUpdateSnippet) - details see below. 21 21 22 22 To perform the operations, call {{code language="none"}}SchemaManager.start(){{/code}}. 23 23 24 -=== {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets- UsingSpringorOSGi/Blueprint"/}}Using Spring or OSGi/Blueprint ===30 +=== {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-ConfigurationusingSpringorOSGi/Blueprint"/}}Configuration using Spring or OSGi/Blueprint === 25 25 26 26 If you are using OSGi with Blueprint or Spring to set up your project, you can configure a SchemaManager instance by adding the following to your blueprint {{code language="none"}}services.xml{{/code}} (or Spring configuration file): 27 27 ... ... @@ -33,7 +33,7 @@ 33 33 </bp:reference> 34 34 35 35 <bp:bean id="sqlDialect" factory-ref="dialectFactory" factory-method="newDialect"> 36 -<bp:argument ><!--PassJDBCURLas an argument-->42 +<bp:argument ref="jdbcUrl"><!-- bean jdbcUrl specified above --> 37 37 </bp:argument> 38 38 </bp:bean> 39 39 ... ... @@ -45,22 +45,35 @@ 45 45 <bp:bean id="databaseSetup" class="org.clazzes.jdbc2xml.schema.SchemaManager" init-method="start"> 46 46 <bp:property name="dataSource" ref="dataSource"></bp:property> 47 47 <bp:property name="schemaEngine" ref="schemaEngine"></bp:property> 54 + <!-- optional but recommended: special name for schema history table: --> 55 + <bp:property name="versionHistoryTable" value="MYLIB_SCHEMA_HISTORY"/> 56 + <!-- optional but recommended: explicit first version --> 48 48 <bp:property name="baseVersion" value="0.1.00" /> 49 49 <bp:property name="baseTables"> 50 -<!-- Add List of TableDefinitions here --> 59 +<!-- List of TableDefinitions here (see below), typical: --> 60 + <!-- <bp:bean factory-ref="tableDefinitions" factory-method="getSetup" /> --> 51 51 </bp:property> 62 + <!-- Add Update-Snippets here, example for updates from 0.1.00 to 0.1.01 and on to 0.2.00 52 52 <bp:property name="upateSnippets"> 53 -<!-- Add Update-Snippets here --> 64 +<bp:map> 65 + <bp:entry key="0.1.00" value="foo.schema.SchemaUpdate_0_1_01"></bp:entry> 66 + <bp:entry key="0.1.01" value="foo.schema.SchemaUpdate_0_2_00"></bp:entry> 67 +</bp:map> 54 54 </bp:property> 69 + --> 55 55 </bp:bean> 56 56 {{/code}} 57 57 58 -By default, JDBC2XML provides an implementation of IDialectFactory and ISchemaEngineFactory as an OSGi service or via ServiceRegistry lookupfor Spring.73 +By default, JDBC2XML provides an implementation of IDialectFactory and ISchemaEngineFactory as an OSGi service or via ServiceRegistry for Spring. 59 59 60 60 = {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-Settingupaninitialdatabaseschema"/}}Setting up an initial database schema = 61 61 62 -To create an initial database schema, you will need to provideSchemaManagerwitha list of TableInfo objects.The recommended way to do this is to provide a class in your project which creates this list in it's constructor and provides it through a getter. You can instantiate this class in your Spring/Blueprint config as a singleton, and feed the provided List to SchemaManager. An example of this class could look like this:77 +To create an initial database schema, SchemaManager needs a list of TableInfo objects. 63 63 79 +The recommended strategy is to implement a table definition class providing this list through a getter. 80 + 81 +This is an example: 82 + 64 64 {{code language="java"}} 65 65 package org.clazzes.example.jdbc2xml; 66 66 ... ... @@ -75,8 +75,7 @@ 75 75 76 76 public class TableDefinitions { 77 77 78 - /* It is adviseable to provide the Strings used as names for tables and columns as 79 - constants, so they can be reused to build sql-statements */ 97 + // It is adviseable to provide the Strings used as names for tables and columns as constants, so they can be reused outside this object to build sql-statements 80 80 public static final String TB_EXAMPLE_TABLE_NAME = "ADDRESSBOOK"; 81 81 public static final String COL_EXAMPLE_ID = "ID"; 82 82 public static final String COL_EXAMPLE_NAME = "NAME"; ... ... @@ -83,12 +83,12 @@ 83 83 public static final String COL_EXAMPLE_ADDRESS_REF = "ADDRESS"; 84 84 public static final String COL_EXAMPLE_BIRTHDAY = "BIRTHDAY"; 85 85 86 - / *...*/104 + // ... 87 87 88 88 private List<TableInfo> setup; 89 89 90 90 public TableDefinitions() { 91 -/ *Create a table*/109 +// Create a table 92 92 TableInfo exampleTable = new TableInfo(TB_EXAMPLE_TABLE_NAME); 93 93 exampleTable.setColumns( 94 94 Arrays.asList(new ColumnInfo[] { ... ... @@ -98,21 +98,21 @@ 98 98 new ColumnInfo(COL_EXAMPLE_BIRTHDAY, Types.DATE, 12, null, false, null) 99 99 })); 100 100 101 -/ *Example for creating a foreign key reference*/119 +// Example for creating a foreign key reference 102 102 exampleTable.setForeignKeys(Arrays.asList(new ForeignKeyInfo[] { 103 103 new ForeignKeyInfo("FK_EXAMPLE_ADDRESS", COL_EXAMPLE_ADDRESS_REF, TB_ADDRESS, COL_ADDRESS_ID) 104 104 })); 105 105 106 -/ *Example for creating a primary key*/124 +// Example for creating a primary key 107 107 exampleTable.setPrimaryKey( 108 108 new PrimaryKeyInfo("PK_EXAMPLE", COL_EXAMPLE_ID) 109 109 ); 110 110 111 -/ *...*/129 +// ... 112 112 113 113 this.setup = Arrays.asList( 114 114 exampleTable, 115 -/ *...*/133 +// ... 116 116 ); 117 117 118 118 } ... ... @@ -126,20 +126,111 @@ 126 126 127 127 You must inject {{code language="none"}}TableDefinitions.getSetup(){{/code}} into {{code language="none"}}SchemaManager.setBaseTables(){{/code}} before calling {{code language="none"}}SchemaManager.start(){{/code}}. 128 128 129 -Using Blueprint/Spring, you can do this withthe following snippet:147 +Using Blueprint/Spring, you can do this by inserting the following snippet in the bean definition for SchemaManager: 130 130 131 -{{code language="none"}} 132 - 149 +{{code language="html/xml"}} 150 +<!-- SchemaManager bean definition starts here ... --> 151 +<bp:property name="baseTables"> 152 +<bp:bean factory-ref="tableDefinitions" factory-method="getSetup" /> 153 +</bp:property> 154 +<!-- ... and continues here --> 133 133 {{/code}} 134 134 135 -= {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-UpdatingadatabaseschemawithSchemaUpdateSnippet s"/}}Updating a database schema with SchemaUpdateSnippets=157 += {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-UpdatingadatabaseschemawithISchemaUpdateSnippet"/}}Updating a database schema with ISchemaUpdateSnippet = 136 136 137 137 To update the database or it's content with schema updates, you must create a new implementation of ISchemaUpdateSnippet ({{code language="none"}}org.clazzes.jdbc2xml.schema.ISchemaUpdateSnippet{{/code}}) for each consecutive update. SchemaManager takes a {{code language="none"}}Map<String, Class<? extends ISchemaUpdateSnippet>>{{/code}} which contains the update classes keyed by the originating (e.g. previous) version. 138 138 139 - 161 +An example for an implementation of a schema update snippet could look like this: 140 140 141 - 163 +{{code language="java"}} 164 +package org.clazzes.example.jdbc2xml.updates; 142 142 166 +import java.sql.SQLException; 167 +import java.sql.Types; 168 +import java.util.Arrays; 169 +import org.clazzes.jdbc2xml.schema.ColumnInfo; 170 +import org.clazzes.jdbc2xml.schema.ISchemaEngine; 171 +import org.clazzes.jdbc2xml.schema.ISchemaUpdateSnippet; 172 +import org.clazzes.jdbc2xml.schema.PrimaryKeyInfo; 173 +import org.clazzes.jdbc2xml.schema.TableInfo; 174 + 175 +public class SchemaUpdate0_1_01 implements ISchemaUpdateSnippet { 176 + 177 +// This is only accessed through the getter 178 +private static final String TARGET_VERSION = "0.1.01"; 179 + 180 +// Here it is also adviseable to define constants for reuse in statements. 181 +public static final String COL_EXAMPLE_GENDER = "GENDER"; 182 + 183 + 184 +@Override 185 +public String getTargetVersion() { 186 +return TARGET_VERSION; 187 +} 188 + 189 +@Override 190 +public String getUpdateComment() { 191 +return "Adding column "+COL_EXAMPLE_GENDER+" to table "+TableDefinitions.TB_EXAMPLE_TABLE_NAME+"."; 192 +} 193 + 194 +@Override 195 +public void performUpdate(ISchemaEngine schemaEngine) throws SQLException { 196 +TableInfo ti = schemaEngine.fetchTableInfo(TableDefinitions.TB_EXAMPLE_TABLE_NAME, null); 197 + schemaEngine.addColumn(ti, new ColumnInfo(COL_EXAMPLE_GENDER, Types.VARCHAR, 1, null, true, null)); 198 +} 199 +} 200 + 201 + 202 +{{/code}} 203 + 204 +The return values of {{code language="none"}}ISchemaUpdateSnippet.getTargetVersion(){{/code}} and {{code language="none"}}ISchemaUpdateSnippet.getUpdateComment(){{/code}} are written to the {{code language="none"}}SCHEMA_HISTORY{{/code}} table. The update itself is performed in {{code language="none"}}ISchemaUpdateSnippet.performUpdate(){{/code}}. In the above example, it adds a column called {{code language="none"}}GENDER{{/code}} to the example table created by the TableDefinitions class above. 205 + 206 +To add an entire table you would use the {{code language="none"}}ISchemaEngine.createTable(){{/code}} method, like this: 207 + 208 +{{code language="java"}} 209 +@Override 210 +public void performUpdate(ISchemaEngine schemaEngine) throws SQLException { 211 + TableInfo tiGroup = new TableInfo(TB_GROUP); 212 + tiGroup.setColumns(Arrays.asList(new ColumnInfo[] { 213 + new ColumnInfo(TableDefinitions.COL_ID, Types.VARCHAR, 36, null, false, null), 214 + new ColumnInfo(TableDefinitions.COL_NAME, Types.VARCHAR, 100, null, false, null), 215 + new ColumnInfo(TableDefinitions.COL_DESCRIPTION, Types.VARCHAR, 512, null, true, null) 216 + })); 217 + tiGroup.setPrimaryKey(new PrimaryKeyInfo(PK_GROUP, TableDefinitions.COL_ID)); 218 + tiGroup.setIndices(Arrays.asList(new IndexInfo(IDX_GROUP_01, TableDefinitions.COL_NAME, true, null))); 219 + 220 +schemaEngine.createTable(tiGroup, true); 221 +} 222 +{{/code}} 223 + 224 +Executing a PreparedStatement also works, using ISchemaEngine.getConnection() to retrieve the database connection: 225 + 226 +{{code language="java"}} 227 +@Override 228 +public void performUpdate(ISchemaEngine schemaEngine) throws SQLException { 229 + String sql = "UPDATE "+TableDefinitions.TB_EXAMPLE_TABLE_NAME+" SET "+TableDefinitions.COL_EXAMPLE_NAME+"=?"; 230 + 231 + PreparedStatement ps = schemaEngine.getConnection().prepareStatement(sql); 232 + 233 + ps.setNull(1, Types.VARCHAR); 234 + 235 + ps.execute(); 236 +} 237 +{{/code}} 238 + 239 +To create the map of updates in Blueprint/Spring and inject them into SchemaManager, use the following xml-Snippet: 240 + 241 +{{code language="html/xml"}} 242 +<!-- SchemaManager bean definition starts here ... --> 243 +<bp:property name="upateSnippets"> 244 +<bp:map> 245 +<bp:entry key="0.1.00" value="org.clazzes.example.jdbc2xml.updates.SchemaUpdate0_1_01"></bp:entry> 246 +<!-- more entries come here: "key" is the schema version to update, "value" the qualified classname of the schema update --> 247 +</bp:map> 248 +</bp:property> 249 +<!-- ... and continues here --> 250 +{{/code}} 251 + 143 143 144 144 145 145
- Confluence.Code.ConfluencePageClass[0]
-
- Id
-
... ... @@ -1,1 +1,1 @@ 1 -6568 091 +656824 - URL
-
... ... @@ -1,1 +1,1 @@ 1 -https://clazzes.atlassian.net/wiki/spaces/JDBC2XML/pages/6568 09/How To create and update Databases using SchemaManager and SchemaUpdateSnippets1 +https://clazzes.atlassian.net/wiki/spaces/JDBC2XML/pages/656824/How To create and update Databases using SchemaManager and SchemaUpdateSnippets