Schema Usage

All tables used by TJDO in a given schema are recorded in a single master table in that schema called JDO_TABLE. This table determines the mapping between Java classes/fields and tables for that schema. It has the following structure:

TABLE_ID NEXT_ID JAVA_NAME TABLE_NAME
Primary key Next hi-order value for OIDs Fully-qualified Java class or field name Table name

JDO_TABLE constitutes the definitive list of tables managed by JDO. Any existing table not mentioned in JDO_TABLE is assumed to belong to a non-JDO application and is never touched.

Table Name Generation

Table names are generated from Java names with the following procedure:

  1. The Java name is split into its period-separated parts. For classes, the final part is taken; for fields, the final two parts are taken, separated by a '_'.
  2. Underscores are inserted between words, where a word boundary is defined as an upper-case character preceded by a lower-case character.
  3. If the name exceeds the maximum allowed length for table names minus 4 characters then the name is truncated as follows: all excess characters plus two more are removed and replaced by two characters representing the hash code of the removed characters. The other 4 characters are reserved for various suffixes used elsewhere (e.g. "_PK" for primary keys, "_ID" for ID columns, etc.).
  4. Any leading or trailing underscore characters are removed.
  5. The name is converted to all upper-case or all lower-case, depending on the database's default for storing SQL identifiers (for example, Oracle's is upper-case).
  6. If the resulting table name is already in use (whether for a JDO table or a non-JDO table) the procedure repeats at step 2 with an additional part of the Java name, working right-to-left, added to the front. If there are no more parts, sequential integers are appended starting at 1.

The SchemaManager

TJDO includes an interface for performing a few manual operations directly on the JDO schema, such as adding tables for classes or clearing the schema. See SchemaManager.

Table Creation

With auto-table creation mode disabled, TJDO validates (see below) that all necessary database tables already exist and are correctly defined. With auto-table creation mode enabled, TJDO silently adds tables to the schema in the background as needed.

Auto-table creation mode can be enabled for a given PersistenceManagerFactory with:

((com.triactive.jdo.PersistenceManagerFactoryImpl)pmf).setAutoCreateTables(true);

or, alternatively, it can be enabled for all PersistenceManagerFactories by setting the system property:

com.triactive.jdo.AutoCreateTables=true

While it can be very convenient, auto-table creation mode is really intended for sandbox development and should remain disabled (the default) when running in production (if tables are missing in production, you have a bigger problem that you'd probably better not mask by auto-creating the missing tables).

The table(s) for a given class are created together with the tables for all other classes related to it. A failure to auto-create a given table often results in a whole group of related tables failing to be created. Also, see the FAQ list for a case where auto-table creation can sometimes fail unavoidably when using Oracle.

Table Renaming

For the most part it is not possible to rename a TJDO table, and no API exists to do it. Even if a table is manually renamed, and its entry in JDO_TABLE modified accordingly, there are any number of columns, both in that table and others, whose names would have been generated based on the original table name (for example, the ID column of a class table is generated by appending "_ID" to the table name). If the table name changes, TJDO would expect any such columns to appear using the new name. A SchemaValidationException would occur unless every other column and foreign key that incorporates the old name is modified to use the new name. Whether this is even possible is left as an exercise for the intrepid.

Table Removal

With the exceptions of SchemaManager.dropTablesFor() and SchemaManager.dropAllTables(), TJDO never removes tables. It is possible to manually remove tables without disrupting TJDO if you also remove the corresponding entries from JDO_TABLE and restart any JVMs currently using the schema. However, in practice this is difficult to do because any table being removed must also have any other tables that reference it (via foreign keys) removed, and so on (this must be taken into consideration even when using dropTablesFor()).

Schema Validation

As persistent objects are accessed, TJDO's internal StoreManager determines, using JDO_TABLE, which database table(s) are serving as backing for each class or field. Before a table is first accessed in a given JVM, the StoreManager always validates that its structure and keys are defined correctly according to the corresponding class and its JDO metadata. This prevents the software from failing, or the database from becoming corrupt, due to a mismatch between the two.

Validation Failure

A failure of any validation step causes a SchemaValidationException to be thrown and the corresponding class fails to initialize, making it unusable for persistence. Any other unrelated classes that have passed validation remain usable. This allows portions of a system to proceed and work even if other portions are temporarily damaged.

Subsequent attempts to use a class that failed initialization will cause the StoreManager to repeat the initialization and schema validation procedure. If validation then succeeds, the class becomes usable. This allows schema errors to be corrected in the database, and the JDO subsystem to recover, without having to restart the JVM.

Table Validation

Tables are validated by confirming that:

  1. The table exists. If it doesn't, and auto-table creation is enabled, the table and its primary key are automatically created and the remaining table validation steps are skipped.
  2. All expected columns exist.
  3. No unexpected columns exist.
  4. All columns are of the expected data type (and precision and scale, if applicable).
  5. The nullability of all columns is correct.
  6. The primary key exists and is made up of the expected column(s).

Foreign Key Validation

Foreign keys are used wherever an ID column exists that recognizably refers to a specific table. An example of an ID column that would not refer to a specific table is a field declared as an interface type, or declared as a non-persistence-capable superclass having persistence-capable subclasses.

For those tables having foreign keys, their keys are validated by confirming that:

  1. All expected foreign keys exist. If any key doesn't exist, and auto-table creation is enabled, the key is automatically created.

For validation purposes, a foreign key is defined as a list of FK columns, each with an associated PK column in some table. The name of a foreign key is unimportant, although TJDO will always generate names for new keys as tablename_FKn using the next available n.

Index Validation

If not automatically done by the database itself, TJDO will create indices for all columns used as a foreign key, unless a suitable index already exists. Primary keys are always assumed to have a backing index, whether reported by the database or not. An index is considered suitable if it equates to, or begins with, the column(s) that make up the foreign key. This only applies to foreign keys that are themselves managed by TJDO.

For those tables needing indices, the indices are validated by confirming that:

  1. All expected indices exist. If any index doesn't exist, and auto-table creation is enabled, the index is automatically created.

For validation purposes, an index is defined as simply a list of columns. The name of the index is unimportant, although TJDO will always generate names for new indices as tablename_Nn using the next available n.


SourceForge.net