Java Persistence/OneToOne

OneToOne


A  relationship in Java is where the source object has an attribute that references another target object and (if) that target object had the inverse relationship back to the source object it would also be a   relationship. All relationships in Java and JPA are unidirectional, in that if a source object references a target object there is no guarantee that the target object also has a relationship to the source object. This is different than a relational database, in which relationships are defined through foreign keys and querying such that the inverse query always exists.

JPA also defines a  relationship, which is similar to a   relationship except that the inverse relationship (if it were defined) is a   relationship. The main difference between a  and a   relationship in JPA is that a   always contains a foreign key from the source object's table to the target object's table, where as a   relationship the foreign key may either be in the source object's table or the target object's table. If the foreign key is in the target object's table JPA requires that the relationship be bi-directional (must be defined in both objects), and the source object must use the  attribute to define the mapping.

In JPA a  relationship is defined through the   annotation or the   element. A  relationship typically requires a   or   if a composite primary key is used.

Example of a OneToOne relationship database
EMPLOYEE (table)

ADDRESS (table)

Inverse Relationships, Target Foreign Keys and Mapped By
A typical object centric perspective of a  relationship has the data model mirror the object model, in that the source object has a pointer to the target object, so the database source table has a foreign key to the target table. This is not how things always work out in the database though, in fact many database developers would think having the foreign key in the target table to be logical, as this enforces the uniqueness of the  relationship. Personally I prefer the object perspective, however you will most likely encounter both.

To start considering a bi-directional  relationship, you do not require two foreign keys, one in each table, so a single foreign key in the owning side of the relationship is sufficient. In JPA the inverse  must use the   attribute (with some exceptions), this makes the JPA provider use the foreign key and mapping information in the source mapping to define the target mapping.

See also, Target Foreign Keys, Primary Key Join Columns, Cascade Primary Keys.

The following gives an example of what the inverse  relationship would look like.

Foreign key is also part of the primary key.

 * See Primary Keys through OneToOne Relationships.

Foreign key is also mapped as a basic.

 * If you use the same field in two different mappings, you typically require to make one of them read-only using.
 * See Target Foreign Keys, Primary Key Join Columns, Cascade Primary Keys.

Constraint error on insert.

 * This typically occurs because you have incorrectly mapped the foreign key in a  relationship.
 * See Target Foreign Keys, Primary Key Join Columns, Cascade Primary Keys.


 * It can also occur if your JPA provider does not support referential integrity, or does not resolve bi-directional constraints. In this case you may either need to remove the constraint, or use     to ensure the order your objects are written in.

Foreign key value is null

 * Ensure you set the value of the object's, if the   is part of a bi-directional   relationship, ensure you set   in both objects, JPA does not maintain bi-directional relationships for you.
 * Also check that you defined the  correctly, ensure you did not set   or use a , or.

=Advanced=

Target Foreign Keys, Primary Key Join Columns, Cascade Primary Keys
If a  relationship uses a target foreign key (the foreign key is in the target table, not the source table), then JPA requires that you define a   mapping in both directions, and that the target foreign key mapping use the   attribute. The reason for this, is the mapping in the source object only affects the row the JPA writes to the source table, if the foreign key is in the target table, JPA has no easy way to write this field.

There are other ways around this problem however. In JPA the  defines an   and   attribute, these can be used to instruct the JPA provider that the foreign key is actually in the target object's table. With these enabled JPA will not write anything to the source table, most JPA providers will also infer that the foreign key constraint is in the target table to preserve referential integrity on insertion. JPA also defines the  that can be used to define the same thing. You still must map the foreign key in the target object in some fashion though, but could just use a  mapping to do this.

Some JPA providers may support an option for a unidirectional  mapping for target foreign keys.

Target foreign keys can be tricky to understand, so you might want to read this section twice. They can get even more complex though. If you have a data model that cascades primary keys then you can end up with a single  that has both a logical foreign key, but has some fields in it that are logically target foreign keys.

For example consider,  ,. 's id is,  's id is a composite primary key of   and  , and  's id is a composite primary key of  ,  , and. So for an  its relationship to   uses a normal   with a foreign key, but its relationship to   uses a   with a foreign key, but the   uses   or , because it is actually mapped through the   relationship. The 's relationship to its   then uses a normal foreign key for   but a target foreign key for ,  , and.

This may work in some JPA providers, others may require different configuration, or not support this type of data model.

Example of cascaded primary keys database
COMPANY(table)

DEPARTMENT(table)

EMPLOYEE (table)

ADDRESS(table)

Mapping a OneToOne Using a Join Table
In some data models, you may have a  relationship defined through a join table. For example consider you had existing  and   tables with no foreign key, and wanted to define a   relationship without changing the existing tables. To do this you could define an intermediate table that contained the primary key of both objects. This is similar to a  relationship, but if you add a unique constraint to each foreign key you can enforce that it is   (or even  ).

JPA defines a join table using the  annotation and   XML element. A  can be used on a   or   mappings, but the JPA 1.0 specification is vague whether it can be used on a. The  documentation does not state that it can be used in a , but the XML schema for   does allow a nested   element. Some JPA providers may support this, and others may not.

If your JPA provider does not support this, you can workaround the issue by instead defining a  or   relationship and just define a get/set method that returns/sets the first element on the collection.

Example of a OneToOne using a JoinTable database
EMPLOYEE (table)

EMP_ADD(table)

ADDRESS (table)

Example of simulating a OneToOne using a OneToMany JoinTable
/Mapping