4 Replies Latest reply on Jul 4, 2002 3:59 AM by stephenbibby

    parent/child cmp2 relationship

      Does anyone have any good design pointers on a cmp2 entity which has one cmr parent and also 0 to many cmr children of the same type as it is? Any examples?

      The ejb-jar.xml doesn't seem too hard in that respect but the jbosscmp-jdbc.xml file seems limiting in that on deployment, jboss doesn't let me specify keyfields for both roles in the relationship. Of course, mabye my design is flawed and I won't have to.

      Thanks for any and all help, sharing experiences, etc.

        • 1. Re: parent/child cmp2 relationship
          objectwizatlycos

          Hi David,

          I have managed to code this and I can deploy it. However, once deployed, if I call setParent() or addChild() on my bean, the relationships are not maintained (though the same code works in Orion server). I've included my jbosscmp-jdbc.xml in case it helps. If you can get it working - or even if you can't - perhaps between us we can make it work!! ;-)

          Regards,

          Peter.

          <INCLUDED TEXT>

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE jbosscmp-jdbc PUBLIC "-//JBoss//DTD JBOSSCMP-JDBC 3.0//EN" "http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_3_0.dtd">

          <jbosscmp-jdbc>

          java:/DefaultDS
          <datasource-mapping>Hypersonic SQL</datasource-mapping>


          <enterprise-beans>


          <ejb-name>forum/Message</ejb-name>
          <create-table>true</create-table>
          <remove-table>true</remove-table>
          <read-only>true</read-only>
          <time-out>100</time-out>
          <table-name>message</table-name>

          <cmp-field>
          <field-name>children</field-name>
          <column-name>children</column-name>

          </cmp-field>
          <cmp-field>
          <field-name>id</field-name>
          <column-name>id</column-name>

          </cmp-field>
          <cmp-field>
          <field-name>parent</field-name>
          <column-name>parent</column-name>

          </cmp-field>
          <cmp-field>
          <field-name>subject</field-name>
          <column-name>subject</column-name>

          </cmp-field>
          <cmp-field>
          <field-name>text</field-name>
          <column-name>text</column-name>

          </cmp-field>
          <!--
          To define load groups for this entity, write a file named
          jbosscmp-jdbc-load-MessageBean.xml and put it in
          your mergedir. Write it according to the following DTD slice:
          <!ELEMENT load-groups (load-group+)>
          <!ELEMENT load-group (load-group-name, description?, field-name+)>
          <!ELEMENT load-group-name (#PCDATA)>
          <!ELEMENT description (#PCDATA)>
          <!ELEMENT field-name (#PCDATA)>
          <!ELEMENT eager-load-group (#PCDATA)>
          <!ELEMENT lazy-load-groups (load-group-name+)>
          -->



          </enterprise-beans>


          <ejb-relation>
          <ejb-relation-name>parent</ejb-relation-name>
          <foreign-key-mapping/>
          <ejb-relationship-role>
          <ejb-relationship-role-name>children</ejb-relationship-role-name>
          <key-fields>
          <key-field>
          <field-name>id</field-name>
          <column-name></column-name>
          </key-field>
          </key-fields>
          </ejb-relationship-role>
          <ejb-relationship-role>
          <ejb-relationship-role-name>parent</ejb-relationship-role-name>
          <key-fields/>
          </ejb-relationship-role>
          </ejb-relation>


          <dependent-value-classes>

          </dependent-value-classes>

          </jbosscmp-jdbc>

          • 2. Re: parent/child cmp2 relationship

            Though I think I found the right way to do it a while ago, I've negleted to share what I've learned with the community. (bad me.) So here goes (granted, I haven't tested this completely yet, but it's looking good so far)...

            If you want a bidierectional parent-child relationship where both the parent and the child are of the same bean, *you have to define two relationships, not one*:

            - The first specifies the one-2-one unidirectional relationship an entity has with its parent. This will correlate with an abstract get/setParent(YourBeanLocal) in the bean.

            - The second specifies the one-2-many unidirectional relationship an entity has with its children. This will correlate with an abstract get/setChildren(Collection) in the bean.

            It seems impossible to do this bidirectionaly in a single relationship definition.

            Here is an "Album" example:

            <!-- ejb-jar.xml snippet -->
            <ejb-relation>
            <ejb-relation-name>Album-AlbumChildren</ejb-relation-name>
            <ejb-relationship-role>
            <ejb-relationship-role-name>
            Album-Has-AlbumChildren
            </ejb-relationship-role-name>
            One
            <relationship-role-source>
            <ejb-name>Album</ejb-name>
            </relationship-role-source>
            <cmr-field>
            <cmr-field-name>children</cmr-field-name>
            <cmr-field-type>java.util.Collection</cmr-field-type>
            </cmr-field>
            </ejb-relationship-role>
            <ejb-relationship-role>
            <ejb-relationship-role-name>
            AlbumChildren-For-Album
            </ejb-relationship-role-name>
            Many
            <cascade-delete/>
            <relationship-role-source>
            <ejb-name>Album</ejb-name>
            </relationship-role-source>
            </ejb-relationship-role>
            </ejb-relation>
            <ejb-relation>
            <ejb-relation-name>Album-AlbumParent</ejb-relation-name>
            <ejb-relationship-role>
            <ejb-relationship-role-name>
            Album-Has-AlbumParent
            </ejb-relationship-role-name>
            One
            <relationship-role-source>
            <ejb-name>Album</ejb-name>
            </relationship-role-source>
            <cmr-field>
            <cmr-field-name>parent</cmr-field-name>
            </cmr-field>
            </ejb-relationship-role>
            <ejb-relationship-role>
            <ejb-relationship-role-name>
            AlbumParent-For-Album
            </ejb-relationship-role-name>
            One
            <relationship-role-source>
            <ejb-name>Album</ejb-name>
            </relationship-role-source>
            </ejb-relationship-role>
            </ejb-relation>

            <!-- jbosscmp-jdbc.xml snippet -->
            <ejb-relation>
            <ejb-relation-name>Album-AlbumParent</ejb-relation-name>
            <foreign-key-mapping/>
            <ejb-relationship-role>
            <ejb-relationship-role-name>
            Album-Has-AlbumParent
            </ejb-relationship-role-name>
            <key-fields>
            <key-field>
            <field-name>key</field-name>
            <column-name>PARENT_KEY</column-name>
            </key-field>
            </key-fields>
            </ejb-relationship-role>
            <ejb-relationship-role>
            <ejb-relationship-role-name>
            AlbumParent-For-Album
            </ejb-relationship-role-name>
            <key-fields/>
            </ejb-relationship-role>
            </ejb-relation>
            <ejb-relation>
            <ejb-relation-name>Album-AlbumChildren</ejb-relation-name>
            <relation-table-mapping>
            <table-name>ALBUM_CHILDREN</table-name>
            </relation-table-mapping>
            <ejb-relationship-role>
            <ejb-relationship-role-name>
            Album-Has-AlbumChildren
            </ejb-relationship-role-name>
            <key-fields>
            <key-field>
            <field-name>key</field-name>
            <column-name>PARENT_KEY</column-name>
            </key-field>
            </key-fields>
            </ejb-relationship-role>
            <ejb-relationship-role>
            <ejb-relationship-role-name>
            AlbumChildren-For-Album
            </ejb-relationship-role-name>
            <key-fields>
            <key-field>
            <field-name>key</field-name>
            <column-name>CHILD_KEY</column-name>
            </key-field>
            </key-fields>
            </ejb-relationship-role>
            </ejb-relation>

            • 3. Re: parent/child cmp2 relationship

              After working with Dain on the jboss-user list, he seems to think that it should be possible to do a same-bean parent/child relationship with just one cmr-rel, not two. Though I know how to represent this in a database easily enough, I can't figure out how to do it properly in the xml. Dain said he is looking into putting together an example for us. :)

              • 4. Re: parent/child cmp2 relationship
                stephenbibby

                I dont know if anyone is interested in this anymore, or infact if they are using XDoclet to generate the parent/child relationship, but I came across the same problem (Project EJB has a child/parent relationship with itself).

                I found a solution by using XDoclet to generate the relationships. It detects that the relationship is bi-directional and creates a child/parent relationship that works (for JBoss 3.0). The following is the XDoclet tags, and generated deployment descriptors. I hope this helps.

                /**
                * Get the parent project.
                *
                * @ejb:interface-method view-type="local"
                * @ejb:relation name="Project-ParentProject"
                * role-name="one-Project-belongs-to-one-Project"
                * target-role-name="one-Project-has-many-Project"
                * target-multiple="yes"
                *
                * @jboss:relation related-pk-field="name"
                * fk-column="parentProject"
                */
                public abstract com.dca.timesheet.beans.ejb.ProjectEJBLocal getParentProject();

                /**
                * This sets a parent project
                *
                * @ejb:interface-method view-type="local"
                */
                public abstract void setParentProject(com.dca.timesheet.beans.ejb.ProjectEJBLocal parent);

                /**
                * Gets child projects.
                *
                * @ejb:interface-method view-type="local"
                * @ejb:relation name="Project-ParentProject"
                * role-name="one-Project-has-many-Project"
                * target-role-name="one-Project-belongs-to-one-Project"
                *
                */
                public abstract Collection getChildProjects();

                /**
                * Sets child projects.
                *
                * Mutator for the virtual relationship field.
                *
                * @ejb:interface-method view-type="local"
                */
                public abstract void setChildProjects(Collection childProjects);

                These XDoclet tags generate lots of output, but the important stuff is here...
                jbosscmp-jdbc.xml:
                <ejb-relation>
                <ejb-relation-name>Project-ParentProject</ejb-relation-name>
                <foreign-key-mapping/>
                <ejb-relationship-role>
                <ejb-relationship-role-name>one-Project-has-many-Project</ejb-relationship-role-name>
                <key-fields>
                <key-field>
                <field-name>name</field-name>
                <column-name>parentProject</column-name>
                </key-field>
                </key-fields>
                </ejb-relationship-role>
                <ejb-relationship-role>
                <ejb-relationship-role-name>one-Project-belongs-to-one-Project</ejb-relationship-role-name>
                <key-fields/>
                </ejb-relationship-role>
                </ejb-relation>

                and in ejb-jar.xml:
                <ejb-relation >
                <ejb-relation-name>Project-ParentProject</ejb-relation-name>
                <!-- bidirectional -->
                <ejb-relationship-role >
                <ejb-relationship-role-name>one-Project-has-many-Project</ejb-relationship-role-name>
                One
                <relationship-role-source >
                <ejb-name>ProjectEJB</ejb-name>
                </relationship-role-source>
                <cmr-field >
                <cmr-field-name>childProjects</cmr-field-name>
                <cmr-field-type>java.util.Collection</cmr-field-type>
                </cmr-field>
                </ejb-relationship-role>
                <ejb-relationship-role >
                <ejb-relationship-role-name>one-Project-belongs-to-one-Project</ejb-relationship-role-name>
                Many
                <relationship-role-source >
                <ejb-name>ProjectEJB</ejb-name>
                </relationship-role-source>
                <cmr-field >
                <cmr-field-name>parentProject</cmr-field-name>
                </cmr-field>
                </ejb-relationship-role>
                </ejb-relation>