JPOX
JPOX
 JPOX Version 1.0
Configuration | Tutorials | Worked Examples | Developer
Obtaining JPOX
JPOX Preparation
JPOX Runtime
M-N Relationships

You have a M-to-N (or Many-to-Many) relationship if an object of a class A has associated objects of class B, and class B has associated objects of class A. This relationship may be achieved through Java Set, Map, List or subclasses of these.

With JPOX this can be set up as described in this section, using what is called a Normal relationship. Lets take the following example and describe how to model it with the different types of collection classes. We have 2 classes, Product and Supplier as below.





Here the Product class knows about the Supplier class. In addition the Supplier knows about the Product class, however with JPOX (as with the majority of JDO implementations) these relationships are independent.

Using Set
Normal Relationship

If you define the Meta-Data for these classes as follows

<package name="mydomain">
    <class name="Product" identity-type="datastore">
        <field name="name" persistence-modifier="persistent">
            <extension vendor-name="jpox" key="length" value="max 50"/>
        </field>
        <field name="price" persistence-modifier="persistent">
        </field>
        <field name="suppliers" persistence-modifier="persistent">
            <collection element-type="mydomain.Supplier">
            <collection/>
        </field>
    </class>

    <class name="Supplier" identity-type="datastore">
        <field name="name" persistence-modifier="persistent">
            <extension vendor-name="jpox" key="length" value="max 100"/>
        </field>
        <field name="products" persistence-modifier="persistent">
            <collection element-type="mydomain.Product">
            <collection/>
        </field>
    </class>
</package>

This will create 4 tables in the database, one for Product, one for Supplier, one for the suppliers for a product, and one for the products of a supplier. The two partys of the M-N relationship are independent, hence why there are 2 join tables (in effect it is really 2 1-N relationships).





If you want to have only 1 "join" table, you can define the table and column names, something like this

<package name="mydomain">
    <class name="Product" identity-type="datastore">
        <field name="name" persistence-modifier="persistent">
            <extension vendor-name="jpox" key="length" value="max 50"/>
        </field>
        <field name="price" persistence-modifier="persistent">
        </field>
        <field name="suppliers" persistence-modifier="persistent">
            <collection element-type="mydomain.Supplier">
                <extension vendor-name="jpox" key="table-name" value="PRODUCTS_SUPPLIERS"/>
                <extension vendor-name="jpox" key="owner-column-name" value="PRODUCT_ID"/>
                <extension vendor-name="jpox" key="element-column-name" value="SUPPLIER_ID"/>
            <collection/>
        </field>
    </class>

    <class name="Supplier" identity-type="datastore">
        <field name="name" persistence-modifier="persistent">
            <extension vendor-name="jpox" key="length" value="max 100"/>
        </field>
        <field name="products" persistence-modifier="persistent">
            <collection element-type="mydomain.Product">
                <extension vendor-name="jpox" key="table-name" value="PRODUCTS_SUPPLIERS"/>
                <extension vendor-name="jpox" key="owner-column-name" value="SUPPLIER_ID"/>
                <extension vendor-name="jpox" key="element-column-name" value="PRODUCT_ID"/>
            <collection/>
        </field>
    </class>
</package>
Using List
Normal Relationship

If you define the Meta-Data for these classes as follows

<package name="mydomain">
    <class name="Product" identity-type="datastore">
        <field name="name" persistence-modifier="persistent">
            <extension vendor-name="jpox" key="length" value="max 50"/>
        </field>
        <field name="price" persistence-modifier="persistent">
        </field>
        <field name="suppliers" persistence-modifier="persistent">
            <collection element-type="mydomain.Supplier">
            <collection/>
        </field>
    </class>

    <class name="Supplier" identity-type="datastore">
        <field name="name" persistence-modifier="persistent">
            <extension vendor-name="jpox" key="length" value="max 100"/>
        </field>
        <field name="products" persistence-modifier="persistent">
            <collection element-type="mydomain.Product">
            <collection/>
        </field>
    </class>
</package>
                

There will be 4 tables, one for Product, one for Supplier, and the join tables. The difference from the Set example is in the contents of the join tables. An index column is added to keep track of the position of objects in the Lists.





If you want to have only 1 "join" table, you can define the table and column names in the same way as was done for Set.

Using Map
Normal Relationship

If you define the Meta-Data for these classes as follows

<package name="mydomain">
    <class name="Product" identity-type="datastore">
        <field name="name" persistence-modifier="persistent">
            <extension vendor-name="jpox" key="length" value="max 50"/>
        </field>
        <field name="price" persistence-modifier="persistent">
        </field>
        <field name="suppliers" persistence-modifier="persistent">
            <map key-type="java.lang.String" value-type="mydomain.Supplier">
            <map/>
        </field>
    </class>

    <class name="Supplier" identity-type="datastore">
        <field name="name" persistence-modifier="persistent">
            <extension vendor-name="jpox" key="length" value="max 100"/>
        </field>
        <field name="products" persistence-modifier="persistent">
            <map key-type="java.lang.String" value-type="mydomain.Product">
            <map/>
        </field>
    </class>
</package>
                

This will create 4 tables in the datastore, one for Product, one for Supplier, and the join tables which also contains the keys to the Maps (a String).





If you want to have only 1 "join" table, you can define the table and column names in the same way as was done for Set.

Relationship Behaviour

Please be aware of the following. If you want to delete an object from one end of a M-N relationship you will have to remove it first from the other objects relationship. If you don't you will get an error message that the object to be deleted has links to other objects and so cannot be deleted.