Last modified by christoph_lechleitner@iteg_at on 2013-01-31 07.32:56

From version 5.1
edited by christoph_lechleitner@iteg_at
on 2013-01-31 06.18:32
Change comment: There is no comment for this version
To version 2.1
edited by 5fbc055b7cc103006957e1ae
on 2012-06-14 06.29:38
Change comment: There is no comment for this version

Summary

Details

Page properties
Author
... ... @@ -1,1 +1,1 @@
1 -XWiki.christoph_lechleitner@iteg_at
1 +XWiki.5fbc055b7cc103006957e1ae
Content
... ... @@ -1,11 +1,9 @@
1 1  = {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-Preliminary"/}}Preliminary =
2 2  
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.
3 +The SchemaManager and SchemaEngine give you an abstracted access to the database schema of your application, 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.
4 4  
5 -==== {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-SchemaHistoryTable"/}}Schema History Table ====
5 +SchemaManager ({{code language="none"}}org.clazzes.jdbc2xml.schema.SchemaManager{{/code}}) will create a table called SCHEMA_HISTORY if it can not find it the first time it is run. This table contains the following columns:
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 -
9 9  {{code language="none"}}
10 10  VERSION:varchar(10), not null, primary key
11 11  DESCRIPTION:varchar(512), nullable
... ... @@ -13,21 +13,17 @@
13 13  SERIALNR:integer(5), not null
14 14  {{/code}}
15 15  
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 -
20 20  = {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-ProjectConfiguration"/}}Project Configuration =
21 21  
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.
16 +To function correctly, SchemaManager needs 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 a database will be created if it finds an empty database. To function properly, it also needs an implementation of ISchemaEngine ({{code language="none"}}org.clazzes.jdbc2xml.schema.ISchemaEngine{{/code}}).
23 23  
24 -Optionally, a base version (default value 0.1.00) and a base description String (default "initial database schema") may be specified.
18 +Optionally, you may set the base version (default value 0.1.00) and base description String (default "initial database schema").
25 25  
26 26  Database updates are passed as a Map<String, ISchemaUpdateSnippet> (org.clazzes.jdbc2xml.schema.ISchemaUpdateSnippet) - details see below.
27 27  
28 28  To perform the operations, call {{code language="none"}}SchemaManager.start(){{/code}}.
29 29  
30 -=== {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-ConfigurationusingSpringorOSGi/Blueprint"/}}Configuration using Spring or OSGi/Blueprint ===
24 +=== {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-UsingSpringorOSGi/Blueprint"/}}Using Spring or OSGi/Blueprint ===
31 31  
32 32  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):
33 33  
... ... @@ -39,7 +39,7 @@
39 39  </bp:reference>
40 40   
41 41  <bp:bean id="sqlDialect" factory-ref="dialectFactory" factory-method="newDialect">
42 -<bp:argument ref="jdbcUrl"><!-- bean jdbcUrl specified above -->
36 +<bp:argument> <!-- Pass JDBC URL as an argument -->
43 43  </bp:argument>
44 44  </bp:bean>
45 45   
... ... @@ -51,35 +51,22 @@
51 51  <bp:bean id="databaseSetup" class="org.clazzes.jdbc2xml.schema.SchemaManager" init-method="start">
52 52  <bp:property name="dataSource" ref="dataSource"></bp:property>
53 53  <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 -->
57 57  <bp:property name="baseVersion" value="0.1.00" />
58 58  <bp:property name="baseTables">
59 -<!-- List of TableDefinitions here (see below), typical: -->
60 - <!-- <bp:bean factory-ref="tableDefinitions" factory-method="getSetup" /> -->
50 +<!-- Add List of TableDefinitions here -->
61 61  </bp:property>
62 - <!-- Add Update-Snippets here, example for updates from 0.1.00 to 0.1.01 and on to 0.2.00
63 63  <bp:property name="upateSnippets">
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>
53 +<!-- Add Update-Snippets here -->
68 68  </bp:property>
69 - -->
70 70  </bp:bean>
71 71  {{/code}}
72 72  
73 -By default, JDBC2XML provides an implementation of IDialectFactory and ISchemaEngineFactory as an OSGi service or via ServiceRegistry for Spring.
58 +By default, JDBC2XML provides an implementation of IDialectFactory and ISchemaEngineFactory as an OSGi service or via ServiceRegistry lookup for Spring.
74 74  
75 75  = {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-Settingupaninitialdatabaseschema"/}}Setting up an initial database schema =
76 76  
77 -To create an initial database schema, SchemaManager needs a list of TableInfo objects.
62 +To create an initial database schema, you will need to provide SchemaManager with a 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:
78 78  
79 -The recommended strategy is to implement a table definition class providing this list through a getter.
80 -
81 -This is an example:
82 -
83 83  {{code language="java"}}
84 84  package org.clazzes.example.jdbc2xml;
85 85  
... ... @@ -94,7 +94,8 @@
94 94   
95 95  public class TableDefinitions {
96 96  
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
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 */
98 98   public static final String TB_EXAMPLE_TABLE_NAME = "ADDRESSBOOK";
99 99   public static final String COL_EXAMPLE_ID = "ID";
100 100   public static final String COL_EXAMPLE_NAME = "NAME";
... ... @@ -101,12 +101,12 @@
101 101   public static final String COL_EXAMPLE_ADDRESS_REF = "ADDRESS";
102 102   public static final String COL_EXAMPLE_BIRTHDAY = "BIRTHDAY";
103 103   
104 - // ...
86 + /* ... */
105 105   
106 106   private List<TableInfo> setup;
107 107  
108 108   public TableDefinitions() {
109 -// Create a table
91 +/* Create a table */
110 110  TableInfo exampleTable = new TableInfo(TB_EXAMPLE_TABLE_NAME);
111 111  exampleTable.setColumns(
112 112   Arrays.asList(new ColumnInfo[] {
... ... @@ -116,21 +116,21 @@
116 116  new ColumnInfo(COL_EXAMPLE_BIRTHDAY, Types.DATE, 12, null, false, null)
117 117  }));
118 118   
119 -// Example for creating a foreign key reference
101 +/* Example for creating a foreign key reference */
120 120  exampleTable.setForeignKeys(Arrays.asList(new ForeignKeyInfo[] {
121 121  new ForeignKeyInfo("FK_EXAMPLE_ADDRESS", COL_EXAMPLE_ADDRESS_REF, TB_ADDRESS, COL_ADDRESS_ID)
122 122  }));
123 123   
124 -// Example for creating a primary key
106 +/* Example for creating a primary key */
125 125  exampleTable.setPrimaryKey(
126 126  new PrimaryKeyInfo("PK_EXAMPLE", COL_EXAMPLE_ID)
127 127  );
128 128  
129 -// ...
111 +/* ... */
130 130   
131 131  this.setup = Arrays.asList(
132 132  exampleTable,
133 -// ...
115 +/* ... */
134 134  );
135 135  
136 136   }
... ... @@ -144,111 +144,20 @@
144 144  
145 145  You must inject {{code language="none"}}TableDefinitions.getSetup(){{/code}} into {{code language="none"}}SchemaManager.setBaseTables(){{/code}} before calling {{code language="none"}}SchemaManager.start(){{/code}}.
146 146  
147 -Using Blueprint/Spring, you can do this by inserting the following snippet in the bean definition for SchemaManager:
129 +Using Blueprint/Spring, you can do this with the following snippet:
148 148  
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 -->
131 +{{code language="none"}}
132
155 155  {{/code}}
156 156  
157 -= {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-UpdatingadatabaseschemawithISchemaUpdateSnippet"/}}Updating a database schema with ISchemaUpdateSnippet =
135 += {{id name="HowTocreateandupdateDatabasesusingSchemaManagerandSchemaUpdateSnippets-UpdatingadatabaseschemawithSchemaUpdateSnippets"/}}Updating a database schema with SchemaUpdateSnippets =
158 158  
159 159  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.
160 160  
161 -An example for an implementation of a schema update snippet could look like this:
139 +
162 162  
163 -{{code language="java"}}
164 -package org.clazzes.example.jdbc2xml.updates;
141 +
165 165  
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 -
252 252  
253 253  
254 254  
Confluence.Code.ConfluencePageClass[0]
Id
... ... @@ -1,1 +1,1 @@
1 -656824
1 +656809
URL
... ... @@ -1,1 +1,1 @@
1 -https://clazzes.atlassian.net/wiki/spaces/JDBC2XML/pages/656824/How To create and update Databases using SchemaManager and SchemaUpdateSnippets
1 +https://clazzes.atlassian.net/wiki/spaces/JDBC2XML/pages/656809/How To create and update Databases using SchemaManager and SchemaUpdateSnippets