The solution

You must code getters and setters on your entity interface, and make an informed decision as to the level of visibility of each field.

For each column on your database table, you must decide:

Example

You'll step through an example database table and code getters/setters in your API.

Let's say that the database table MyNewEntity has these columns:
  • myNewEntityID - primary key;
  • name - String;
  • startDate - date;
  • endDate - date;
  • typeCode - codetable code, specifying the "type" of the entity; and
  • myParentEntityID - foreign key to a row on a different database table.

Let's go through the attributes on MyNewEntity and flesh out the entity API.

myNewEntityID

In general, getters and setters for your primary key column are straightforward - you don't write any.

You rarely need to code anything for the primary key of an entity, because each entity already has a getID method (inherited from StandardEntity).

Important: Do not be tempted to write your own getter for the ID:
Figure 1. Incorrect - redundant getter method for entity ID
/** ********** VERY VERY BAD - DO NOT DO THIS! ********** */
  /**
   * @return the primary key of MyNewEntity.
   */
  public Long getMyNewEntityID();

  /** ********** VERY VERY BAD - DO NOT DO THIS! ********** */

Similarly, each entity implementation typically takes care of assigning its own primary key, and so callers of the entity API do not require a facility to set the primary key themselves.

Important: Do not be tempted to write your own setter for the ID:
Figure 2. Incorrect - setter method for entity ID
/** ********** VERY VERY BAD - DO NOT DO THIS! ********** */
  /**
   * @param value
   *          the primary key of MyNewEntity.
   */
  public void setMyNewEntityID(final Long value);

  /** ********** VERY VERY BAD - DO NOT DO THIS! ********** */

name

After analysis of requirements, you determine that callers of your API require to both get and set the name column of a database row.

Code a field getter as follows:

Figure 3. Interface declaration for a simple get method
/**
   * Gets the name.
   *
   * @return the name
   */
  public String getName();
Note that:
  • by convention, the method is named get<Fieldname> with the first letter of the field name upper-cased (one exception is that getters that return a boolean value often read better as is<Condition>); and
  • the name column holds a String, so the getter must return a String.

Code a field setter as follows:

Figure 4. Interface declaration for a simple set method
/**
   * Sets the name.
   *
   * @param value
   *          the name
   */
  public void setName(final String value);
Note that:
  • by convention, the method is named set<Fieldname>, with the first letter of the field name upper-cased;
  • by convention, the variable name of the value passed in is "value";
  • the setter returns void; and
  • the name column holds a String, so the setter must take a String value.

startDate and endDate

After analysis of requirements, you determine that:
  • callers of your API require to get the start and end dates, to compare the range of dates covered with dates supplied by other processing;
  • the start date is always set to the current business date when a new row is created; and
  • the end date is only set (to a specified date) when the entity enters a state of "closed".
Accordingly, you decide that:
  • the start date and end date should be returned to callers as a DateRange "helper" object; and
  • callers should not be free to set the start and end dates - manipulation of these end dates should be taken care of by specialized methods on the entity (see e.g. State Transitions).

You require your entity to return a DateRange helper object - rather than coding a getDateRange method, instead it's better to change your API to extend DateRanged:

Figure 5. Extending the DateRanged interface
/**
 * Description of my wonderful new entity.
 */
public interface MyNewEntity extends StandardEntity, DateRanged {

The DateRanged interface provides your entity with a getDateRange method and also allows access to helper functions which provide commonly-used processing on entities which contain a date range.

typeCode

After analysis, you determine that your entity stores a codetable code describing the "type" of the entity instance.

Create a codetable specifying the permitted values:

Figure 6. Codetable for the type of an entity
<?xml version="1.0" encoding="UTF-8"?>
<codetables package="curam.mypackage.codetable">
  <codetable
    java_identifier="MYNEWENTITYTYPE"
    name="MYNEWENTITYTYPE"
  >
    <code
      default="false"
      java_identifier="SOMETYPE"
      status="ENABLED"
      value="TYPE1"
    >
      <locale
        language="en"
        sort_order="0"
      >
        <description>Some type</description>
        <annotation/>
      </locale>
    </code>
    <code
      default="false"
      java_identifier="SOMEOTHERTYPE"
      status="ENABLED"
      value="TYPE2"
    >
      <locale
        language="en"
        sort_order="0"
      >
        <description>Some other type</description>
        <annotation/>
      </locale>
    </code>
  </codetable>
</codetables>

The Persistence Infrastructure includes a code generator to generate a class per codetable. These classes provide a type-safe mechanism for passing around an entry from the codetable, and each class is named after its codetable suffixed with the word Entry:

Figure 7. Excerpts from a generated "Entry" class for a codetable
package curam.mypackage.codetable.impl;

/**
 * Represents an entry from the
 * {@linkplain curam.mypackage.codetable.MYNEWENTITYTYPE} code
 * table.
 */
public class MYNEWENTITYTYPEEntry extends
    curam.util.type.CodeTableEntry {

  // ...

  /**
   * Private constructor.
   */
  private MYNEWENTITYTYPEEntry(final String code) {
    super(TABLENAME, code);
  }

  /**
   * Gets the
   * {@linkplain curam.mypackage.codetable.impl.MYNEWENTITYTYPEEntry}
   * for the specified code value.
   *
   * @param code
   *          the String representation of the code value required.
   *
   * @return a
   *         {@linkplain curam.mypackage.codetable.impl.MYNEWENTITYTYPEEntry}
   *         representation of the specified code value.
   *
   * @throws curam.util.exception.AppRuntimeException
   *           if the specified code value is not present in the
   *           {@linkplain curam.mypackage.codetable.MYNEWENTITYTYPE}
   *           code table.
   */
  public static curam.mypackage.codetable.impl.MYNEWENTITYTYPEEntry get(
      final String code) {
    // ...
  }

  /**
   * The name of the
   * {@linkplain curam.mypackage.codetable.MYNEWENTITYTYPE} table -
   * {@value}.
   */
  public static String TABLENAME =
      curam.mypackage.codetable.MYNEWENTITYTYPE.TABLENAME;

  /**
   * Not specified (i.e. blank).
   */
  public static final curam.mypackage.codetable.impl.MYNEWENTITYTYPEEntry
      NOT_SPECIFIED = get(null);

  /**
   * TYPE1 en = Some type
   */
  public static final curam.mypackage.codetable.impl.MYNEWENTITYTYPEEntry
      SOMETYPE =
      get(curam.mypackage.codetable.MYNEWENTITYTYPE.SOMETYPE);

  /**
   * TYPE2 en = Some other type
   */
  public static final curam.mypackage.codetable.impl.MYNEWENTITYTYPEEntry
      SOMEOTHERTYPE =
      get(curam.mypackage.codetable.MYNEWENTITYTYPE.SOMEOTHERTYPE);

}

Use of this generated class is preferable to using a String to pass around the value, as (in particular) a String can be constructed with any text whereas the generated class only permits values corresponding to the underlying code table.

Code:
  • a getter to return an instance of this generated class; and
  • a setter which takes an instance of this generated class:
Figure 8. Getter and setter methods for a codetable-based value
/**
   * Gets the type of this entity instance.
   *
   * @return the type of this entity instance
   */
  public MYNEWENTITYTYPEEntry getType();

  /**
   * Sets the type of this entity instance.
   *
   * @param value
   *          the type of this entity instance
   */
  public void setType(final MYNEWENTITYTYPEEntry value);
Note: Getter and setter methods do not have to be named exactly after their database columns (in this example, the data column typeCode is accessed via methods named getType and setType, not getTypeCode and setTypeCode.

In particular, some database column names are abbreviated to comply with database name length constraints, and for these the getter and setter names should not slavishly repeat the abbreviation, e.g. use getSomeVeryVeryLongDatabaseColumnName rather than getSmVyVyLgDbColNm.

myParentEntityID

For foreign keys to related entity instances, in general you should not create getters and setters for the entity ID, but instead code getters and setters which deal with the API of the related entity:

Figure 9. Interface declaration for getting/setting a related entity instance
/**
   * Gets the parent instance of MyParentEntity.
   *
   * @return the parent instance of MyParentEntity, or null if not
   *         yet set
   */
  public MyParentEntity getMyParentEntity();

  /**
   * Sets the parent instance of MyParentEntity.
   *
   * @param value
   *          the parent instance of MyParentEntity
   */
  public void setMyParentEntity(final MyParentEntity value);

Note that this code assumes that the MyParentEntity API has already been coded. If not, you must create a skeletal API:

Figure 10. Creating a skeletal API for a related entity
public interface MyParentEntity extends StandardEntity {

}
Important: Do not be tempted to expose the related entity ID directly:
Figure 11. Incorrect - getting/setting a related ID instead of the related entity
/** ********** VERY VERY BAD - DO NOT DO THIS! ********** */
  /**
   * @return the foreign key to the parent MyParentEntity instance
   */
  public Long getMyParentEntityID();

  /**
   * @param value
   *          the foreign key to the parent MyParentEntity instance
   */
  public void setMyParentEntityID(final Long value);

  /** ********** VERY VERY BAD - DO NOT DO THIS! ********** */

Child instances

Each instance of your entity has a set of associated child entity instances (from a different database table).

If callers of your API require to navigate to these child instances, code a getter which returns a Set, typed with the API of the child entity:

Figure 12. Interface declaration for getting a set of related entities
/**
   * Gets the MyChildEntity children of this entity instance.
   *
   * @return the MyChildEntity children of this entity instance
   */
  public Set<MyChildEntity> getMyChildren();

Note that this code assumes that the MyChildEntity API has already been coded. If not, you must create a skeletal API:

Figure 13. Creating a skeletal API for another related entity
public interface MyChildEntity extends StandardEntity {

}