Datastore Schema

Some datastores have a well-defined structure and when persisting/retrieving from these datastores you have to have this schema in place. DataNucleus provides various controls for creation of any necessary schema components. This creation can be performed as follows

  • One off task before running your application using SchemaTool. This is the recommended option since it separates schema from operation.
  • At runtime, using some persistence properties.
The thing to remember when using DataNucleus is that the schema is under your control . DataNucleus does not impose anything on you as such, and you have the power to turn on/off all schema components. Some Java persistence tools add various types of information to the tables for persisted classes, such as special columns, or meta information. DataNucleus is very unobtrusive as far as the datastore schema is concerned. It minimises the addition of any implementation artifacts to the datastore, and adds nothing (other than any datastore identities, and version columns where requested) to any schema tables.



Schema Creation

DataNucleus can generate the schema for the developer as it encounters classes in the persistence process. Alternatively you can use the SchemaTool application before starting your application.

If you want to create the schema ("tables"+"columns"+"constraints") during the persistence process, the property datanucleus.autoCreateSchema provides a way of telling DataNucleus to do this. It's a shortcut to setting the other 3 properties to true. Thereafter, during calls to DataNucleus to persist classes or performs queries of persisted data, whenever it encounters a new class to persist that it has no information about, it will use the MetaData to check the datastore for presence of the "table", and if it doesn't exist, will create it. In addition it will validate the correctness of the table (compared to the MetaData for the class), and any other constraints that it requires (to manage any relationships). If any constraints are missing it will create them.

If you wanted to only create the "tables" required, and none of the "constraints" the property datanucleus.autoCreateTables provides this, simply performing the tables part of the above.

If you want to create any missing "columns" that are required, the property datanucleus.autoCreateColumns provides this, validating and adding any missing columns.

If you wanted to only create the "constraints" required, and none of the "tables" the property datanucleus.autoCreateConstraints provides this, simply performing the "constraints" part of the above.

If you want to keep your schema fixed (i.e don't allow any modifications at runtime) then the property datanucleus.fixedDatastore should be set to true and this has the effect of setting the "table"+"columns"+"constraints" autoCreate values to false



Schema Validation

DataNucleus can check any existing schema against what is implied by the MetaData.

The property datanucleus.validateTables provides a way of telling DataNucleus to validate any tables that it needs against their current definition in the datastore. If the user already has a schema, and want to make sure that their tables match what DataNucleus requires (from the MetaData definition) they would set this property to true . This can be useful for example where you are trying to map to an existing schema and want to verify that you've got the correct MetaData definition.

The property datanucleus.validateColumns provides a way of telling DataNucleus to validate any columns of the tables that it needs against their current definition in the datastore. If the user already has a schema, and want to make sure that their tables match what DataNucleus requires (from the MetaData definition) they would set this property to true . This will validate the precise column types and widths etc, including defaultability/nullability settings. Please be aware that many JDBC drivers contain bugs that return incorrect column detail information and so having this turned off is sometimes the only option (dependent on the JDBC driver quality).

The property datanucleus.validateConstraints provides a way of telling DataNucleus to validate any constraints (primary keys, foreign keys, indexes) that it needs against their current definition in the datastore. If the user already has a schema, and want to make sure that their table constraints match what DataNucleus requires (from the MetaData definition) they would set this property to true .



Schema Naming Issues

Some datastores allow access to multiple "schemas" (such as with most RDBMS). DataNucleus will, by default, use the "default" database schema for the Connection URL and user supplied. This may cause issues where the user has been set up and in some databases (e.g Oracle) you want to write to a different schema (which that user has access to). To achieve this in DataNucleus you would set the runtime properties

javax.jdo.mapping.Catalog={the_catalog_name}
javax.jdo.mapping.Schema={the_schema_name}

This will mean that all RDBMS DDL and SQL statements will prefix table names with the necessary catalog and schema names (specify which ones your datastore supports).



Schema Generation and Column Ordering

By default all tables are generated with columns in alphabetical order, starting with root class fields followed by subclass fields (if present in the same table) etc. There is a JDO3.1 attribute that allows you to specify the order of columns for schema generation. This is not present in JPA. It is achieved by specifying the metadata attribute position against the column.

<column position="1"/>

Note that the values of the position start at 0, and should be specified completely for all columns of all fields.



Read-Only

If your datastore is read-only (you can't add/update/delete any data in it), obviously you could just configure your application to not perform these operations. An alternative with JDO is to set the PersistenceManagerFactory as "read-only". You do this by setting the persistence property javax.jdo.option.ReadOnly to true . For JPA you would set the persistence property datanucleus.ReadOnlyDatastore to true .

From now on, whenever you perform a persistence operation that implies a change in datastore data, the JDO operation will throw a JDOReadOnlyException , whereas JPA will throw a PersistenceException .

DataNucleus provides an additional control over the behaviour when an attempt is made to change a read-only datastore. The default behaviour is to throw an exception. You can change this using the persistence property datanucleus.readOnlyDatastoreAction with values of "EXCEPTION" (default), and "IGNORE". "IGNORE" has the effect of simply ignoring all attempted updates to readonly objects.

You can take this read-only control further and specify it just on specific classes. Like this

@Extension(vendorName="datanucleus", key="read-only", value="true")
public class MyClass {...}