JPA 1-1 Relationships

You have a 1-to-1 relationship when an object of a class has an associated object of another class (only one associated object). It could also be between an object of a class and another object of the same class (obviously). You can create the relationship in 2 ways depending on whether the 2 classes know about each other (bidirectional), or whether only one of the classes knows about the other class (unidirectional). These are described below.



Unidirectional

For this case you could have 2 classes, User and Account , as below.



so the Account class knows about the User class, but not vice-versa. If you define the Meta-Data for these classes as follows

<entity-mappings>
    <entity class="User">
        <table name="USER"/>
        <attributes>
            <id name="id">
                <column name="USER_ID"/>
            </id>
            ...
    </entity>

    <entity class="Account">
        <table name="ACCOUNT"/>
        <attributes>
            <id name="id">
                <column name="ACCOUNT_ID"/>
            </id>
            ...
            <one-to-one name="user">
                <join-column name="USER_ID"/>
            </one-to-one>
        </attributes>
    </entity>
</entity-mappings>

This will create 2 tables in the database, one for User (with name USER ), and one for Account (with name ACCOUNT and a column USER_ID ), as shown below.



Things to note :-

  • Account has the object reference to User (and so is the "owner" of the relation) and so its table holds the foreign-key
  • If you call EntityManager.remove() on the end of a 1-1 unidirectional relation without the relation and that object is related to another object, an exception will typically be thrown (assuming the RDBMS supports foreign keys). To delete this record you should remove the other objects association first.


Bidirectional

For this case you could have 2 classes, User and Account again, but this time as below. Here the Account class knows about the User class, and also vice-versa.



We create the 1-1 relationship with a single foreign-key. To do this you define the MetaData as

<entity-mappings>
    <entity class="User">
        <table name="USER"/>
        <attributes>
            <id name="id">
                <column name="USER_ID"/>
            </id>
            ...
            <one-to-one name="account" mapped-by="user"/>
        </attributes>
    </entity>

    <entity class="Account">
        <table name="ACCOUNT"/>
        <attributes>
            <id name="id">
                <column name="ACCOUNT_ID"/>
            </id>
            ...
            <one-to-one name="user">
                <join-column name="USER_ID"/>
            </one-to-one>
        </attributes>
    </entity>
</entity-mappings>
The difference is that we added mapped-by to the field of User .

This will create 2 tables in the database, one for User (with name USER ), and one for Account (with name ACCOUNT including a USER_ID ). The fact that we specified the mapped-by on the User class means that the foreign-key is created in the ACCOUNT table.

Things to note :-

  • The "mapped-by" is specified on User (the non-owning side) and so the foreign-key is held by the table of Account (the owner of the relation)
  • When forming the relation please make sure that you set the relation at BOTH sides since DataNucleus would have no way of knowing which end is correct if you only set one end.