Defining a Data Entity

Migration of MAPPER data reports to database tables is informed by configuration metadata based on the Spring framework. The configuration addresses several aspects of translating MAPPER report data to a domain entity backed by a table:

The Spring bean primarily responsible for configuring the translation of a MAPPER report into a database table is DataEntityHandler. The features of the DataEntityHandler bean and their usage are explored in greater detail below. Translation of the sample MAPPER report Footwear Orders - Information (RID 12D3954) is used as an example.

Identifying Data Tuples

It's important to identify which data lines in a MAPPER comprise a tuple (or row) of entity data, and how those tuples are organized.

In a typical MAPPER data report, each line beginning with a tab character contains columnar data fields for the primary entity represented by the report. In most reports, each tab line is treated as a distinct data tuple, although MJ supports composition of a data tuple from multiple lines.

A MAPPER data report may contain more than one kind of entity data based on the line type. Trailer lines sometimes occur immediately after a tab line, beginning with a line type character like asterisk or period. Such trailer lines usually specify an entirely different entity from the tab lines.

See more information on the structure of MAPPER data reports, including examples.

Defining the RDBMS Table

The database table created by MJ to host the MAPPER report data adheres to common, best practices such as surrogate primary key, created-by-user, created-by-timestamp, last-updated-by-user and last-updated-by-timestamp columns. The Footwear Orders example below shows setting the FOOTWEAR_ORDER_LINEITEM table name and custom column names for the surrogate key, last-updated-by-timestamp and created-by-user:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/util
                           http://www.springframework.org/schema/util/spring-util-3.0.xsd">

  <bean id="orderEntityHandler"
        . . .
        p:tableName="FOOTWEAR_ORDER_LINEITEM"
        p:surrogateKeyColumnName="fw_order_li_id"
        p:updateTimestampColumnName="DATE_OF_LAST_UPDATE"
        p:createUserColumnName="CREATED_BY_USER"
        . . .
        >

  </bean>
  . . .
</beans>

Notice the example above (along with the other examples on this page) use the XML shortcut with the p-namespace. The p-namespace uses the bean element's attributes, instead of nested <property/> elements, to specify property values and collaborating beans.

Defining the RDBMS Columns

The fields in the MAPPER report are stored as columns in the database table, where each column is specified by a column definition bean. For most fields, an AnnotatedColumnDef bean defines the corresponding database column. Each column definition bean is then referenced by the DataEntityHandler bean. Below are two example column definition beans for the Qty and Price fields in the Footwear Orders report. A la Spring, each column is defined via arguments passed to the AnnotatedColumnDef constructor:

<bean id="orderEntityHandler.coldefQuantity"
        class="com.arsi.mj.maprpt.entity.handler.AnnotatedColumnDef">
    <!-- MAPPER name, MAPPER type, entity attrname, column name, length, NULLABLE, data type -->
    <constructor-arg index="0" value="Qty" />
    <constructor-arg index="1">
      <util:constant static-field="com.arsi.mj.datatype.MaprptDataType.INTEGER"/>
    </constructor-arg>
    <constructor-arg index="2" value="quantity"/>
    <constructor-arg index="3" value="QTY"/>
    <constructor-arg index="4" value="3"/>
    <constructor-arg index="5" value="false"/>
    <constructor-arg index="6">
      <util:constant static-field="org.hibernate.type.StandardBasicTypes.INTEGER"/>
    </constructor-arg>
  </bean>
  . . .
  <bean id="orderEntityHandler.coldefPrice"
        class="com.arsi.mj.maprpt.entity.handler.AnnotatedColumnDef">
    <!-- MAPPER name, MAPPER type, entity attrname, column, length, scale, NULLABLE, data type -->
    <constructor-arg index="0" value="Price" />
    <constructor-arg index="1">
      <util:constant static-field="com.arsi.mj.datatype.MaprptDataType.FLOAT"/>
    </constructor-arg>
    <constructor-arg index="2" value="price"/>
    <constructor-arg index="3" value="PRICE"/>
    <constructor-arg index="4" value="8"/>
    <constructor-arg index="5" value="2"/>
    <constructor-arg index="6" value="false"/>
    <constructor-arg index="7">
      <util:constant static-field="org.hibernate.type.StandardBasicTypes.BIG_DECIMAL"/>
    </constructor-arg>
  </bean>

The example AnnotatedColumnDef beans are wired as dependencies (collaborating bean references) via the ordinal column properties (column2 and column7) of the DataEntityHandler bean for Footwear Orders:

<bean id="orderEntityHandler"
      . . .
      p:column2-ref="orderEntityHandler.coldefQuantity"
      . . .
      p:column7-ref="orderEntityHandler.coldefPrice"
      . . .
>

Note the actual column number don't matter; the column<N> naming covention simply permits definition of an arbitrary number of column properties on the DataEntityHandler bean.

Defining an Enumerated RDBMS Column

When a field in the MAPPER report is restricted to a set of known, discrete values, specify a Java enumeration with the column definition bean. Examples of this are shoe Type ("Basketball", "Running", "Golf", "Tennis") and Gender ("Womens", "Mens") in the Footwear Orders report. In these cases, field values from the report are mapped to enumerated values with StringKeyEnumMapping bean. The example mapping for the shoe Type is:

<bean id="orderEntityHandler.enumShoeType"
        class="com.arsi.mj.maprpt.enums.StringKeyEnumMapping"
        p:enumClassName="com.arsi.mj.testapp.hibgen.enums.ShoeType">

    <property name="enumsFromProperties">
      <value>
      Basketball=BASKETBALL -> Basketball
      Running=RUNNING -> Running
      Golf=GOLF -> Golf
      Tennis=TENNIS -> Tennis
      </value>
    </property>
  </bean>

Important properties of the StringKeyEnumMapping bean are:

enumClassName Full name of enumeration class, including package. For example, com.arsi.mj.testapp.hibgen.enums.ShoeType.
enumsFromProperties Defines enumerated constants and associated keys from a properties object.
defineEnum Define an enumerated constant and specify it's associated key.

Mapping of field values to enumerated values is most easily defined as properties via the enumsFromProperties method and the extended name/value syntax supported by the method:

    key=symbol->value

For StringKeyEnumMapping, key is a field value from the MAPPER report, symbol is an enumerated constant name and value is the enumerated constant value. Here is an example:

    Basketball=BASKETBALL -> Basketball

where key, symbol and value are:

key
Basketball
Field value from MAPPER report for basketball shoes.
symbol
BASKETBALL
The name of the enumerated constant. This is different from the name of the class derived from java.lang.enum, which is specified by enumClassName.
value
Basketball
The value of the enumerated constant; this value is stored in the database column created for the attribute. Typically the same as key when migrating a MAPPER application, but a more succinct value may be supplied if key is unwieldy or multiple keys are mapped to the same enumerated value.

MJ generates the ShoeType enumeration:

package com.arsi.mj.testapp.hibgen.enums;

import com.arsi.mj.IGenericEnum;

/** Enumeration of <code>ShoeType</code>.*/
public enum ShoeType implements IGenericEnum {
  TENNIS("Tennis"),
  BASKETBALL("Basketball"),
  RUNNING("Running"),
  GOLF("Golf");

  /** String value associated with each enumeration constant. */
  private String value;

  /** Restricted ctor for creating an instance of this class. */
  private ShoeType(String aValue) {
    this.value = aValue;
  }

  /**
   * Get canonical name of the enumeration constant, which is the associated string value.
   *
   * @return
   *  canonical name, i.e., associated string value (e.g., if Java enum constant is
   *  <code>AVERAGE</code>, canonical name might be "AVG").
   */
  public String asName() { return this.value; }

  /**
   * Given canonical name (associated string value) of an enumeration constant,
   * return the Java enumeration constant.
   *
   * @param aValue
   *   associated string value (canonical name, e.g., "AVG").
   * @return
   *   enumeration constant associated with string value (e.g., <code>AVERAGE</code>).
   * @throws IllegalArgumentException
   *   if <code>aValue</code> is not associated with any enumeration constant.
   */
  public static ShoeType asValueOf(String aValue) {
    if (TENNIS.asName().equals(aValue))
      return TENNIS;
    else if (BASKETBALL.asName().equals(aValue))
      return BASKETBALL;
    else if (RUNNING.asName().equals(aValue))
      return RUNNING;
    else if (GOLF.asName().equals(aValue))
      return GOLF;
    else
      throw new IllegalArgumentException("invalid enumeration value: " + aValue);
  }
}

Similar to other fields, an AnnotatedColumnDef bean defines the database column that stores the enumerated entity attribute. The column definition bean for shoe Type is:

<bean id="orderEntityHandler.coldefShoeType"
      class="com.arsi.mj.maprpt.entity.handler.AnnotatedColumnDef">
  <!-- MAPPER name, MAPPER type, entity attrname, column name, length, NULLABLE, data type -->
  <constructor-arg index="0" value="Type" />
  <constructor-arg index="1">
    <util:constant static-field="com.arsi.mj.datatype.MaprptDataType.STRING"/>
  </constructor-arg>
  <constructor-arg index="2" value="shoeType"/>
  <constructor-arg index="3" value="SHOE_TYPE"/>
  <constructor-arg index="4" value="10"/>
  <constructor-arg index="5" value="false"/>
  <constructor-arg index="6">
    <util:constant static-field="org.hibernate.type.StandardBasicTypes.STRING"/>
  </constructor-arg>
</bean>

References to the AnnotatedColumnDef and StringKeyEnumMapping collaborating beans are wired as dependencies via ordinal column and enumForColumn properties of DataEntityHandler bean:

<bean id="orderEntityHandler"
      . . .
      p:column3-ref="orderEntityHandler.coldefShoeType"
      p:enumForColumn3-ref="orderEntityHandler.enumShoeType"
      . . .
/>

DataEntityHandler Example: FootwearOrderLineitem

See the full Spring XML for the Footwear Orders sample MAPPER report, including configuration for translating order entity data into the FootwearOrderLineitem persistent, domain entity class and FOOTWEAR_ORDER_LINEITEM table.