View on GitHub

exedio persistence

Persistence Framework for Java.

Go to top

Field Reloaded Trail

While the Field Trail covered the most fundamental fields only, this trails shows you some more special ways to store data. Although most of the features below are not fields in a formal sense (means subclasses of class Field) you don't have to care about this until you want to develop such features yourself.

Contents

Hashes

If you want to store a string encoded by a hash algorithm, such as the password of the customer, then put the following into class Customer:

static final MD5Hash password = new MD5Hash();

The instrumentor will generate a method for checking the password instead of a getter method:

boolean checkPassword(String password)
{
   return Customer.password.check(this, password);
}

Using the super classes of MD5Hash you can choose any hash algorithm provided by the java.security package or even implement a custom algorithm.

List Fields

Sometimes you may want to store multiple values for an field, such as multiple email addresses for the customer. This can be achieved with list fields:

static final ListField<String> emails =
    ListField.newList(new StringField());

Internally this is implemented by an extra table in the database, so you can store lists of any size. If you are sure, that the list cannot a exceed a certain size, you may decide to use a limited list field:

static final LimitedListField<String> emails =
    LimitedListField.newList(new StringField().optional(), 4);

Internally there are 4 string fields used for storing the elements of the list. If someone tries to store a list of more than 4 elements, an exception is thrown.

Map Fields

Especially in international applications you may want to store multiple field values, such as one price of a product for each country or one description for each language. The following example specifies the latter:

static final MapField<Language,String> description =
    MapField.newMap(newItemField(Language.class),
                        new StringField());

The instrumentor will create appropriate methods for accessing the field map:

String getDescription(Language k)
{
    return Product.description.get(this, k);
}

void setDescription(Language k, String description)
{
    Product.description.set(this, k, description);
}

This example assumes, that there is already a persistent item Language. If you decide to use use a fixed set of languages in your application, you may use an enum instead:

static enum Language { DE, EN, PL; }

static final MapField<Language,String> description =
    MapField.newMap(newEnumField(Language.class),
                        new StringField());

As with list fields this is implemented by an extra table in the database, so you can store maps of any size. If the key space of the map is limited to an enum, you may decide to use a enum map field instead:

static enum Language { DE, EN, PL; }

static final EnumMapField<Language,String> description =
    EnumMapField.newMap(Language.class,
                        new StringField().optional());

Internally three string fields nameDE, nameEN, namePL are used for storing the values of the map.

Day Fields

Class DateField already stores time stamps with millisecond precision. However, sometimes you just want to store a day. Millisecond precision is then just an additional source for mistakes. Since the java runtime library does not provide a value class for this, exedio persistence has to introduce it's own Day. To define a day field within a type write:

static final DayField dateOfBirth = new DayField();

Check Constraints

exedio persistence makes it easy to define check constraints for persistent fields. Here an example with a string field, that holds at most 40 characters and an integer field that must not be negative:

class Customer extends Item
{
   static final StringField email =
       new StringField().lengthMax(40);
   static final IntegerField loginCounter =
       new IntegerField().min(0);
}

Trying to violate such a constraint when modifying or creating a Customer causes a StringLengthViolationException or IntegerRangeViolationException to be thrown.

Further Reading

This was the advanced field trail of the tour. You may now proceed to trails: