Creating a database schema
Introduction
A Torque database schema consists of one or more XML files
describing the structure of the databases.
The files which are considered by the generator can be configured
by the sourceIncludes and sourceExcludes settings of the
maven plugin or ant task. By default, all files are considered
ending with the suffix schema.xml
.
All schema files should comply either to database-5-0-strict.xsd or to database-5-0.xsd. The difference between the strict schema and the normal schema is that in the strict schema, additional naming restrictions are made which are aimed at better interoperability between databases.
It is recommended to ensure schema compliance by adding xsd information into the root database element, e.g.
<database xmlns="http://db.apache.org/torque/5.0/templates/database" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://db.apache.org/torque/5.0/templates/database http://db.apache.org/torque/torque-5.0/documentation/orm-reference/database-5-0-strict.xsd" ...
or
<database xmlns="http://db.apache.org/torque/5.0/templates/database" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://db.apache.org/torque/5.0/templates/database http://db.apache.org/torque/torque-5.0/documentation/orm-reference/database-5-0.xsd" ...
A reference of the Torque schema can be found below.
Example schema file
For an example schema file containing most of the discussed features, look at the bookstore-schema.xml from the test project.
Organisation of the schema files
A single database can consist of one or more schema files.
For small database definitions, it is best to use one schema file
per database.
For complicated database definitions, it can be better to use
more than one schema files.
To have foreign key references between tables in different files,
other schema files can either be included using the
include-schema
element,
or they can be referenced using the external-schema
element.
The difference between included and referenced schemata is that
included schema are considered under torque's control, whereas
tables and views defined in an external schema file can be
referenced, but are not under torque's control.
In practice that means that an included schema can have
foreign key relations between all tables in all files,
and the ddl generation generates create (and possibly drop)
commands for all tables.
With referenced schema files, relations from the
referenced schema to the main schema are forbidden,
and the ddl generation only generates create (and/or drop)
commands for tables in the main schema, not the external schema.
With both included and referenced schema files,
care should be taken that the imported/included files
are not read on their own by the maven plugin or ant tasks.
For example, in the test project, the files included-schema.xml and ext-schema.xml are included respectively referenced by the test-schema.xml. In the configuration of the torque-maven-plugin in the pom, these files are excluded as source files in order to read them only via the include-schema/external-schema element and not as schema files of their own.
More than one database
Torque can access multiple databases with different structure and even different database vendors from within one Torque instance. Basically this means that Torque's inbuilt connection handling can handle more than one database connection pool.
There are three different scenarios for multiple databases, with different levels of support from Torque:
- Each table has a unique name; different tables belong to different databases. This situation is fully supported by the Torque runtime. If the generated peer classes (generated by the torque generator using the torque templates) are used, the different databases are handled automatically in the standard cases because each table has a default database to which it belongs.
- Some or all table names are not unique (there are tables with the same name in different databases), and the tables with the same name have the same structure (same column names and data types etc). This situation is also fully supported by the Torque runtime. However, the generated peer classes are not generated for this situation; meaning that by default, a connection for querying and saving is always opened to the default database for the given table name. This means you will either need to pass the correct database handle name for querying and saving, or not use the connection handling provided by the peer classes.
- Some or all table names are not unique (there are tables with the same name in different databases), and some of the tables with the same name have a different structure than other tables with the same name. This situation is not recommended, it is unclear to which extent it is supported.
Databases with the same structure
If your databases have the same structure, define the schema and generate the classes as if it were only one database. Accessing different databases using the generated classes is covered later in this documentation.
Databases with different structures
On schema creation time, make sure that the different databases are defined in different schema files. Also make sure that the different databases have different name attributes in the database element. Then, define different database handles using the database names from the schema files. Torque will then use the database handle with the key equal to the database element's name attribute for each table.
It is recommended to generate the classes for the different databases into different packages to keep them apart. To achieve this, the corresponding classes must be generated in different generator runs with different package settings.
Using database Schema names
It is possible to qualify table names with schema names (as in ${schema}.${table}) at generate time. To do this, use the fully qualified table name as name attribute in the <table> element of your schema.xml. For example, to use the schema "bookstore" for the table "book", use the following table definition:
... <table name="bookstore.book" description="Book table"> ...
If the standard options are used, the resulting java class name will ignore the leading database name (e.g. the class will be named Book for the example above). If you want to retain the schema names in the java names, (i.e. the resulting java class should be named "BookstoreBook"), you can either use the javaName attribute of the table definition:
... <table name="bookstore.book" javaName="BookstoreBook" description="Book table"> ...
or you can set the generation option
torque.om.retainSchemaNamesInJavaName
to true
.
If you use a sequence to autogenerate ids, the sequence will be generated in the same schema as the table.
In some databases (hsqldb, postgresql, mssql), a schema exists independly of other database objects (user or database). In these databases, a "create schema" (but no "drop schema") command(s) are created automatically in the ddl-sql script if qualified names are used as table names.
Creating a schema from an existing database
Torque can create a starting point for a schema file from an existing database. For doing this, Torque uses the JDBC metainformation provided by the database driver. Not all information about the schema can be collected from JDBC metainformation, so this can only serve as a starting point.
See the information about running the Torque generator on how to generate a schema file from an existing database.
Schema Reference
The database element
Each schema file contains one database element as root element.
The database element must have a name
attribute,
which defines the default handle by which the database can be accessed.
For example, in the test project, most databases have the name
bookstore
, so by default they are accessed by the
bookstore configuration settings.
A database can also define whether by default primitive or object types
are used (via the defaultJavaType
attribute),
or which is the default id method to use to generate primary keys
(via the defaultIdMethod
attribute).
For more information and possible value ranges, see also the xsd
database-5-0.xsd.
The database element can contain the following elements:
element | description / reference | |
---|---|---|
option | currently not used by the torque templates | 0 or more times |
include-schema | see Organisation of the schema files | 0 or more times |
external-schema | see Organisation of the schema files | 0 or more times |
table | see Tables | 0 or more times |
view | see Views | 0 or more times |
domain | definition of common data types, see Domains | 0 or more times |
The database element can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
name | The default handle by which the database can be accessed | |
defaultJavaType | Whether by default primitive or object types are used. Permitted values are object or primitive | primitive |
defaultIdMethod | The default id method to use to generate primary keys. Permitted values are native, idbroker and none. |
Tables
Tables are defined by the table element and have the tableType XSD type depicted in the image above. All tables must have a name and should have at least some columns. It is recommended that each table has a primary key (see below for reasons). Torque supports composite primary keys; to create one, simply set the primary-key attribute to true in more than one column of the same table.
Torque can auto-generate numeric primary keys using either the native database mechanism (idMethod="native", recommended) or a method involving an extra table (idMethod="idbroker"). For defining primary keys manually, use idMethod="none".
Foreign key relations between tables can be defined using the foreign-key element. Foreign keys can consist of one or more columns, simply add a reference elements for each column in the foreign key.
Indexes on the table can be set using the index element. Indexes can also consist of one or more columns. "Normal" indexes are not unique, use the unique element for defining unique constraints.
The table element can contain the following elements:
element | description / reference | |
---|---|---|
option | Currently used only for MySQL. See the supported database page for details. | 0 or more times |
column | see Columns | 1 or more times |
foreign-key | see Foreign Keys | 0 or more times |
index | see Index | 0 or more times |
unique | see Unique | 0 or more times |
id-method-parameter | The name of the sequence, if a sequence is used to generate the primary key. See ID Method Parameters | 0 or more times |
The table element can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
name | The SQL name of the table | |
description | A description of the table. | |
idMethod | The id method to use to generate primary keys for this table. Permitted values are native, idbroker and none. | The value of the defaultIdMethod attribute in the database element |
skipSql | Whether to skip generation of DDL SQL(CREATE TABLE...) for this table. | false |
javaName | The base name of the java classes representing the table | autogenerated from the name attribute |
interface | The interface which the generated data object class for this table should implement | |
peerInterface | The interface which the generated peer class for this table should implement | |
baseClass | The class from which the generated data object class for this table should inherit | |
basePeer | The class from which the generated peer class for this table should inherit | |
abstract | Whether the generated data object class should be an abstract class | false |
Columns
The column element defines a column in a table. Each column must have a name and a type.
There are some column names which you can not use in Torque although your database would support them. These are any column name that contains characters that are not in Java's variable identifier character set. The reason is that column names are used as variable names in the OM Peer classes and these columns will cause the Torque generated code to not compile.
Note however, that SQL92 standard and up uses the same identifier characters as Java for non-delimited columns. So this should only apply to columns defined by the SQL standard as delimited columns, i.e. columns referred to surrounded by double quotes. Delimited column are considered to be case sensitive and/or contain non-standard characters. However, most good cross DB server designs should avoid these special types of column since some servers don't support delimited columns.
In addition, there are two column names that are handled slighly differently in the OM Peer classes. This is so they will not produce constants twice in the generated code. The following column names (case is ignored) will have an "_" prefixed in front of them in the Peer classes:
- TABLE_NAME => _TABLE_NAME
- DATABASE_NAME => _DATABASE_NAME
Furthermore, it is recommended that you do not use words which have a defined meaning in SQL as column names. Even if you can trick your database into using them, it is not sure whether Torque can do the same. And besides, even if it works for one database, if you ever decide to use another database, you may run into trouble then.
The column element can contain the following elements:
element | description / reference | |
---|---|---|
option | currently not used by the torque templates | 0 or more times |
inheritance | see Inheritance | 0 or more times |
enum-value | see EnumValue | 0 or more times |
The column element can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
name | The SQL name of the column. Required. | |
type | The SQL type of the column, also determines the java type. Required unless the domain attribute is set. Note that not every type is supported by every database. Also note that for most (but not all) data types, the javaType of the column can be automatically determined from the SQL type. Possible values are BIT, TINYINT, SMALLINT, INTEGER, BIGINT, FLOAT, REAL, NUMERIC, DECIMAL, CHAR, VARCHAR, LONGVARCHAR, DATE, TIME, TIMESTAMP, BINARY, VARBINARY, LONGVARBINARY, NULL, OTHER, JAVA_OBJECT, DISTINCT, STRUCT, ARRAY, BLOB, CLOB, REF, BOOLEANINT, BOOLEANCHAR and DOUBLE. | |
description | A description of the column. | |
size | The SQL size of the column. Must be an integer. Does only make sense for some SQL Types. | |
scale | The SQL scale of the column (number of digits after the comma). Must be an integer. Does only make sense for some SQL Types. | |
default | The default value of the column. | |
useDatabaseDefaultValue | Whether to use the database default value if a new object is saved and the attribute value is equal to the java default value. Has no effect on primitive boolean columns. | false |
primaryKey | Whether this column is part of the primary key of the column. Allowed values are true and false. | false |
required | Whether this column is required, i. e. it must be not-null Allowed values are true and false. | true for columns which are part of the primary key, false otherwise |
autoIncrement | Whether the value for this column should be autogenerated. Has only effect for primary key columns. Allowed values are true and false. | true for columns which are part of the primary key, false otherwise |
javaName | The base name for the column for generating java methods and fields. | Determined from the name attribute. |
javaType | The java type for the java representation of the column. | For most types, determined from the type attribute. |
domain | The domain to use for this column. | |
inheritance | The inheritance type defined by this column, see the inheritance guide. Allowed values are single and false. | |
enumType | If set, declares this column as an enum. The attribute value defines the enum class name and can either be unqualified, in which case the enum will be generated using the enum-value child elements, or the content can be fully qualified, in which case the enum must be hand-written, and needs to contain the methods getValue(), which returns the SQL value of the enum instance, and the static method getByValue(${javaType} sqlValue), which returns the enum instance corresponding to the sqlValue. | false |
protected | If true, the generated java setters and getters for this property will be protected rather than public. Allowed values are true and false. | false |
version | If true, this column is used as a version number for optimistic locking. I.e. for updates, Torque will check that the version number in the database is equal to the version number of the supplied object and it will automatically increase the version number of the updated row. Setting version to true will only work for numeric columns and will produce code that does not compile if applied to other column types. Allowed values are true and false. |
Primary keys
For every table, you should create a primary key which has no meaning in real life. The reasons for this are:
You should use a primary key at all because it creates a well-defined link between the objects in the database and the objects in memory. Often, one has to decide whether a java object in memory describes "the same" object as a certain row in the database. For example if you read an object from a database, change a field value and write it again to the database, you would usually want to update the row you read from. This is only possible if Torque can find the row in the database from which the object originated. For this, the primary key is used in relational databases. If two java objects have the same primary key, they describe "the same thing" and refer to the same row in the database. If you do not have a primary key, there is no well-defined way to decide if two java objects describe "the same thing". You might run into not being able to update an object.
Now that we know why we want to have a primary key at all, why should it have no meaning in real life ? This can be explained best by an example. Consider a table which holds manufactured parts. Each part has an unique serial number. So it is tempting to use the serial number as a primary key. But now imagine that we have registered the wrong serial number for a certain part in the database. Remember that the primary key is used to decide "is it the same object?" So we cannot change the serial number of a specified object without making it another object.
In Torque, this problem manifests itself in that there is no easy way to change the primary key of an object; you must trick Torque into it by using Torque's internals. This should be avoided if possible. If you use a primary key which has no meaning in real life, you do not run into that trouble.
Foreign keys
A foreign-key element defines a SQL foreign-key relation between two tables. The columns which constitute the foreign key relation are added as reference elements.
The foreign-key element can contain the following elements:
element | description / reference | |
---|---|---|
option | currently not used by the torque templates | 0 or more times |
reference | see Reference | 1 or more times |
The foreign-key element can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
name | The SQL name of the foreign key relation. | |
foreignTable | The name of the foreign table. Must be a table name known in this schema. Required. | |
onDelete | The action to be executed by the database when the referenced entry is deleted. Allowed values are cascade, setnull or restrict. | |
onUpdate | The action to be executed by the database when the referenced entry is updated. Allowed values are cascade, setnull or restrict. |
Reference
A reference defines a link between local and foreign column for a foreign-key element.
The reference element can contain no child elements. It can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
foreign | The SQL name of the column in the foreign table. The column name must be known in the Torque schema. Required. | |
local | The SQL name of the column in the local table. The column name must be known in the Torque schema. Required. |
EnumValue
An enum-value element defines one possible value of a column.
The enum-value element can contain the following attributes:
attribute | description | default value |
---|---|---|
value | The SQL value of the enum. | |
javaName | The name of the enum key. | computed from the value attribute |
description | A description of the enum value |
Index
An index element defines a SQL index on a table. The columns which constitute the index are added as index-column elements.
The index element can contain the following elements:
element | description / reference | |
---|---|---|
option | currently not used by the torque templates | 0 or more times |
index-column | see Index column | 1 or more times |
The index element can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
name | The SQL name of the index. |
Index Column
A index-column defines a column which is part of an index.
The index-column element can contain no child elements. It can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
name | The SQL name of the column which is part of the index. The column name must be known in the Torque schema. Required. |
Unique
An unique element defines a SQL unique index on a table. The columns which constitute the unique index are added as unique-column elements.
The unique element can contain the following elements:
element | description / reference | |
---|---|---|
option | currently not used by the torque templates | 0 or more times |
unique-column | see Unique column | 1 or more times |
The unique element can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
name | The SQL name of the unique index. |
Unique Column
A unique-column defines a column which is part of an unique index.
The unique-column element can contain no child elements. It can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
name | The SQL name of the column which is part of the unique index. The column name must be known in the Torque schema. Required. |
Id method parameters
A id-method-parameter is currently only used to define the name of a sequence if th database uses a sequence for generating primary keys for a table.
The id-method-parameter element can contain no child elements. It can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
name | Currently not used by Torque. | |
value | The SQL name of the sequence. |
Inheritance
A inheritance element defines the usage of a column with respect to inheritance. See the inheritance guide for details.
The id-method-parameter element can contain no child elements. It can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
key | A value found in the column marked as the inheritance key column. | |
class | The class name for the object that will inherit the record values | |
extends | The class that the inheritor class will extend |
Views
Views behave much as tables, except that they cannot be written to. and that they usually reference data from other tables.
A view definition must contain the column names and types.
To let Torque create the sql for the view, you can specify a sql suffix for the view, e.g. "from book join author on book.author_id=author.author_id", and the select snippet for each column using the select attribute, e.g. "author.author_id". E.g.
<view name="BOOK_AUTHORS" sqlSuffix="from book join author on book.author_id=author.author_id"> <column name="book_id" type="INTEGER" select="book.book_id"/> <column name="author_id" type="INTEGER" select="author.author_id"/> <column name="book_title" type="VARCHAR" select="book.title"/> <column name="author_name" type="VARCHAR" select="author.name"/> </view>
This will usually work only for simple views, but is easy to read in the schema. If you cannot create the sql like this, you can also fill the attribute createSql with the sql needed to create the sql.
The view element can contain the following elements:
element | description / reference | |
---|---|---|
option | currently not used by the torque templates | 0 or more times |
column | see View columns | 1 or more times |
The view element can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
name | The SQL name of the view | |
baseClass | The fully qualified name of class which the generated data object class extends | |
basePeer | The fully qualified name of class which the generated peer class extends | |
abstract | Whether the generated data object class should be abstract | false |
javaName | The base name of the generated java classes | generated from the SQL name |
sqlSuffix | The suffix after the select column for the view creation SQL. | |
createSql | The SQL to create the view. | computed from the select attributes of the columns and the sqlSuffix attribute of the view |
skipSql | Whether to skip the create statement when generating the schema creation sql | false |
description | A description of the view |
View Columns
View columns are similar for table columns, but have a different set of attributes because views are read-only and have a different creation SQL than tables.
The column element in a view can contain the following elements:
element | description / reference | |
---|---|---|
option | currently not used by the torque templates | 0 or more times |
inheritance | see Inheritance | 0 or more times |
The column element in a view can contain the following attributes:
attribute | description / reference | default value |
---|---|---|
name | The SQL name of the column | |
type | The SQL type of the column, also determines the java type. Required unless the domain attribute is set. Note that not every type is supported by every database. Also note that for most (but not all) data types, the javaType of the column can be automatically determined from the SQL type. Possible values are BIT, TINYINT, SMALLINT, INTEGER, BIGINT, FLOAT, REAL, NUMERIC, DECIMAL, CHAR, VARCHAR, LONGVARCHAR, DATE, TIME, TIMESTAMP, BINARY, VARBINARY, LONGVARBINARY, NULL, OTHER, JAVA_OBJECT, DISTINCT, STRUCT, ARRAY, BLOB, CLOB, REF, BOOLEANINT, BOOLEANCHAR and DOUBLE. | |
description | A description of the column. | |
size | The SQL size of the column. Must be an integer. Does only make sense for some SQL Types. | |
scale | The SQL scale of the column (number of digits after the comma). Must be an integer. Does only make sense for some SQL Types. | |
javaName | The base name for the column for generating java methods and fields. | Determined from the name attribute. |
javaType | The java type for the java representation of the column. | For most types, determined from the type attribute. |
domain | The domain to use for this column. | |
protected | If true, the generated java setters and getters for this property will be protected rather than public. Allowed values are true and false. | false |
select | The SQL snippet which reads the view column value. |
Domains
A domain is used to create a common type definition. A domain must have a name and a data type and can have a size, scale and default value. Once the domain is defined, it can be used as any other data type in columns.