JPA : Constraints

A datastore often provides ways of constraining the storage of data to maintain relationships and improve performance. These are known as constraints and they come in various forms. These are :-

  • Indexes - these are used to mark fields that are referenced often as indexes so that when they are used the performance is optimised.
  • Unique constraints - these are placed on fields that should have a unique value. That is, only one object will have a particular value.
  • Foreign-Keys - these are used to interrelate objects, and allow the datastore to keep the integrity of the data in the datastore.
  • Primary-Keys - allow the PK to be set, and also to have a name.
Unique constraints
Applicable to RDBMS, db4o, NeoDatis, MongoDB

Some datastores provide the ability to have unique constraints defined on tables to give extra control over data integrity. JPA1 provides a mechanism for defining such unique constraints. Let's take an example class, and show how to specify this

public class Person
{
    String forename;
    String surname;
    String nickname;
    ...
}

and here we want to impose uniqueness on the "nickname" field, so there is only one Person known as "DataNucleus Guru" for example !

<entity class="Person">
    <table name="PEOPLE"/>
    <attributes>
        ...
        <basic name="nickname">
            <column name="SURNAME" unique="true"/>
        </basic>
        ...
    </attributes>
</entity>

The second use of unique constraints is where we want to impose uniqueness across composite columns. So we reuse the class above, and this time we want to impose a constraint that there is only one Person with a particular "forename+surname".

<entity class="Person">
    <table name="PEOPLE">
        <unique-constraint>
            <column-name>FORENAME</column-name>
            <column-name>SURNAME</column-name>
        </unique-constraint>
    </table>
    <attributes>
        ...
        <basic name="forename">
            <column name="FORENAME"/>
        </basic>
        <basic name="surname">
            <column name="SURNAME"/>
        </basic>
        ...
    </attributes>
</entity>

In the same way we can also impose unique constraints on <join-table> and <secondary-table>

See also :-



Indexes
Applicable to RDBMS, db4o, NeoDatis, MongoDB

Many datastores provide the ability to have indexes defined to give performance benefits. With RDBMS the indexes are specified on the table and the indexes to the rows are stored separately. In the same way an ODBMS typically allows indexes to be specified on the fields of the class, and these are managed by the datastore. JPA does not provide a way of defining indexes, but when using DataNucleus to create the datastore schema, will create indexes on all foreign key and primary key fields. In addition DataNucleus allows you to annotate fields/properties that should be indexed, like this

import org.datanucleus.api.jpa.annotations.Index;

@Entity
public class MyClass
{
    @Index
    long someValue;

    ...
}


Foreign Keys
Applicable to RDBMS

When objects have relationships with one object containing, for example, a Collection of another object, it is common to store a foreign key in the datastore representation to link the two associated tables. Moreover, it is common to define behaviour about what happens to the dependent object when the owning object is deleted. Should the deletion of the owner cause the deletion of the dependent object maybe ? JPA1 doesnt allow the user to define any foreign-keys in the datastore. The only thing you can define is the cascading of delete operations, which is described elsewhere.



Primary Keys
Applicable to RDBMS

In RDBMS datastores, it is accepted as good practice to have a primary key on all tables. You specify in other parts of the MetaData which fields are part of the primary key (if using application identity). Unfortunately JPA1 doesnt allow specification of the name of the primary key constraint, nor of whether join tables are given a primary key constraint at all.