Columns

Column

A Column can represent one or more of the following: -

  • A Table Column.
  • An Index Column.
  • A Bean property.
  • An Object value.
  • An XML Attribute.

Properties Reader

Columns are specified in the properties file using the following syntax: -

<ClassName>.column.<index>=<propertyName> <Type> <Null Modifiers> [<Relationship Modifier>]

Where the null modifiers can be one of: -

NULL | NOT NULL | PRIMARY KEY

and the relationship modifier can be one of : -

ASSOCIATE | ASSOCIATES | DEPENDENT | DEPENDENTS <ClassName>

For example: -

readColumn.House.0=houseKey      INT PRIMARY KEY
readColumn.House.1=postmanKey    INT NULL ASSOCIATES Person
readColumn.House.2=houseType     CHAR(2) NOT NULL
readColumn.House.3=number        INT NULL

More information on Types, Primary Keys, Foreign Keys, Enumerated Types and Optimistic locks can be found in their corresponding sections.

Columns can be marked as read only, using the following syntax

<ClassName>.<propertyName>.readOnly=true

Columns can be marked as pseudo columns. This means that they are not to be persisted using the following syntax: -

<ClassName>.<propertyName>.pseudo=true

By default columns are bidirectional. Columns can be marked as unidirectional. This means that corresponding methods are added to the target object of a relationship, using the following syntax: -

<ClassName>.<propertyName>.unidirectional=true

Jdbc Reader

The JdbcReader will read types from the table.

The following properties can be set on the Jdbc metaData.getColumns() method, they default to null: -

jdbc.columnCatalog=<columnCatalog>
jdbc.columnSchemaPattern=<columnSchemaPattern>
jdbc.columnNamePattern=<columnNamePattern>

Once columns have been read in from the database their types and relationship can be modified using the readTable syntax. The types and nullability must still remain compatible with those in the database, or the code will fail at runtime.

For example if a column has been read in from the database as a Timestamp and you would like to treat it as a Date then the Properties reader will match the column and overwrite the type information as follows: -

readColumn.SalesTotalsByAmount.0=shippedDate DATE NULL

Column Names

The Column in the Dictionary has a number of names, these are: -

  • ColumnName - the logical name used to refer to the column.
  • Physical Name - the name in the underlying store.
  • Property Name - the Object Oriented Name
  • Attribute Name - the xml name

The name can be read in from the database, by the JdbcReader or read from a properties file by the PropertiesReader, using the readColumn syntax.

The propertyName can be overriden using the syntax:-

<ClassName>.<propertyName>.propertyName=<Property Name>

The Column Name, is defaulted to the Property name, but can set in the properties file using the following syntax: -

<ClassName>.<propertyName>.columnName=<Column Name>

The Entity Name, is defaulted to the Property name, but can set in the properties file using the following syntax: -

<ClassName>.<propertyName>.attributeName=<Attribute Name>

For example: -

CurrentAccounts.balance.columnName=BLNC
CurrentAccounts.balance.propertyName=currentBalance
CurrentAccounts.balance.attributeName=CurrentAccount_balance

Column Types

Importantly Columns are Properties. This means that they often have an underlying type and a bean type. For example an EnumeratedType might have an underlying INT type but on the bean its property is an EnumeratedType class Name. Another example is a foreignKey, which might have a CHAR(3) as the underlying type, but on the bean its property is another Bean.

The Column object can access its underlying Type using the following method: -

public Type getTypeMethod().

The Type object has a number of methods to refer to the type name. Different names are used depending whether the column is nullable or not. The following methods can be used to access the underlying Java type name: -

  • Class getJavaClass(); - get the primitive class (e.g. Integer.TYPE)
  • String getJavaClassName(); - get the name of the primitive class)
  • Class getJavaObject(); - get the object class (e.g. Integer.class).
  • String getJavaObjectName(); - get the name of the Object class.

The issue of underlying types is not clear cut either for primary keys. A non-nullable INT type would normally be an int, but for singleton primary keys it is an Integer Object. However for compound keys the key types on the Primary Key object are primitive types.

The Column object has a number of methods to refer to the logical (property) and physical(underlying) Java type, and these will take into account whether the column is nullable or not.

  • getEnumeratedType() - get the enumerated type name.
  • getLogicalTypeName() - get the name for the Property (e.g. Person, int).
  • getPhysicalTypeName() - get the name for the underlying type (e.g. Integer, int)

 

Decimal Columns

Once a column has been read in it can be modified using the properties file.

Jdbc drivers often read the decimal precision, scale and rounding wrongly. This can be controlled on a database, table or column level.

The following properties define the decimal precision at the column, table or database level: -

<ClassName>.<propertyName>.decimalPrecision=<precision>
<ClassName>.decimalPrecision=<precision>
decimalPrecision=<precision>

The following properties define the decimal scale at the column, table or database level: -

<ClassName>.<propertyName>.decimalScale=<scale>
<ClassName>.decimalScale=<scale>
decimalScale=<scale>

The following properties define the decimal rounding at the column, table or database level: -

<ClassName>.<propertyName>.decimalRounding=<rounding>
<ClassName>.decimalRounding=<rounding>
decimalRounding=<rounding>

In some circumstances (such as creating a BigDecimal from a double) the decimal scale may be set to a value greater than the decimal precision on the database. This will result in a database error. The Validation classes make a check for this error and can either throw a ValidationException or truncate the BigDecimal by setting the scale of the decimal value to the precision. Decimal value truncation can be set on and off using the following property.

decimalTruncation=<true|false>

In some circumstances (e.g. return from Oracle) the drivers remove extra fractions that are redundant. For example 1.00 becomes 1. By setting the decimalPadding to true any decimals that are returned from the database are padded with 0.

<ClassName>.<propertyName>.decimalPadding=<true|false>
<ClassName>.decimalPadding=<true|false>
decimalPadding=<true|false>


Removing Columns

Columns may need to be hidden. To remove a column specify the following in the properties file: -

<ClassName>.<propertyName>.removed=[true|false]

e.g.

Address.line4.removed=true

Column Validation

When a Column is validated the following checks are made: -

  • Check the Column Name has been set.
  • Check the type has been set.
  • Check there is a foreign table for every foreign key.
  • Check the foreign key cardinality has been set.
  • Check the foreign key dependency has been set.
  • Check nullability and cardinality is compatible.
  • Check Columns that map to Objects.


Example Tables

For example: -

readTable.0=House
readColumn.House.0=houseKey      INT PRIMARY KEY
readColumn.House.1=postmanKey    INT NULL ASSOCIATES Person
readColumn.House.2=ownerKey      INT NOT NULL ASSOCIATE Person
readColumn.House.3=gardenKey     INT NULL DEPENDENT Garden
readColumn.House.4=roadKey       INT NOT NULL DEPENDENTS Road
readColumn.House.5=houseType     CHAR(2) NOT NULL
readColumn.House.6=number        INT NULL
readColumn.House.7=name          VARCHAR(30) NULL
readColumn.House.8=price         DOUBLE NOT NULL
readColumn.House.9=dateTimeStamp TIMESTAMP NOT NULL

readTable.1=Room
readColumn.Room.0=houseKey      INT PRIMARY KEY
readColumn.Room.1=houseKey      INT NOT NULL DEPENDENTS House
readColumn.Room.2=roomType      INT
readColumn.Room.3=dateTimeStamp TIMESTAMP NOT NULL

Using just this information JGenerator will create a bean interface with the following methods: -

public Integer getHouseKey();
public void setHouseKey( Integer houseKey ) throws ValidationException;
public Person getPostman() throws ValidationException;
public void setPostman( Person postman ) throws ValidationException;
public Person getOwner() throws ValidationException;
public void setOwner( Person owner ) throws ValidationException;
public Garden getGarden() throws ValidationException;
public void setGarden( Garden garden ) throws ValidationException;
public Road getRoad() throws ValidationException;
public void setRoad( Road road ) throws ValidationException;
public HouseType getHouseType();
public void setHouseType( HouseType houseType ) throws ValidationException;
public Integer getNumber();
public void setNumber( Integer number ) throws ValidationException;
public String getName();
public void setName( String name) throws ValidationException;
public double getPrice();
public void setPrice( double price ) throws ValidationException;
public void addRoom( Room room ) throws ValidationException;
public void removeRoom( Room room ) throws ValidationException;
public Enumeration getRooms() throws ValidationException;
public void clearRooms();

The example shows a mixture of types and modifiers. There are a few points to note: -

  • The tables are ordered using an index.
  • The houseKey is the primary key
  • The neighbourKey refers to zero or more Neighbours associated with this House.
  • The ownerKey refers to one Person associated with this House.
  • The gardenKey refers to zero or one Gardens dependent on the House.
  • The roadKey refers to one or more Houses Dependent on the Road.
  • The houseType refers to a HouseType EnumeratedType.
  • The house number is a Integer on the House Bean, as it can be null.
  • The name is limited to 30 characters by the HouseValidator.
  • The price is a double on the House Bean.
  • The dateTimeStamp refers to an Optimistic Lock.
  • The add/remove Room methods are added to the House Bean.

 

Writing Example

The following code fragment shows how to write a set of property values into a bean: -

for( Enumeration columns = table.getColumns(); columns.hasMoreElements(); )
{
    Column column = (Column)columns.nextElement();
    writer.println( "\t protected " + column.getLogicalTypeName() + " " + column.getPropertyName() + ";" );
}