In this example, the Course CMP bean is related to the Student CMP bean. Since one student can take several different courses, and one course can be taught to several different students, this is a many-to-many relation.
We can have Resin-CMP manage this relationship for us so that we don't have
to use JDBC to find related entities.
Our two beans in this example will use the following 3 tables:
# this table stores the course entities
CREATE TABLE many2many_courses (
name VARCHAR(250) NOT NULL,
instructor VARCHAR(250),
PRIMARY KEY(name)
);
# this table stores the student entities
CREATE TABLE many2many_students (
name VARCHAR(250) NOT NULL,
PRIMARY KEY(name)
);
# this table is used by Resin-CMP to maintain the relationships between
# students and courses
DROP TABLE many2many_student_course_mapping;
CREATE TABLE many2many_student_course_mapping (
many2many_students VARCHAR(250) NOT NULL,
many2many_courses VARCHAR(250) NOT NULL
);
In addition to one table each for the two entities, we need a
mapping table. It is called it many2many_student_course_mapping as defined
in the deployment descriptor.
Resin-CMP uses the mapping table to keep track of which students are related
to which courses.
The two entries in this table are the primary key of the student and the
course entity, respectively. The names of the two fields in the mapping table
need to match the names of the two CMP Beans that participate in this relation.
Note that only a many2many relation needs a mapping table -- one2one and one2many
relations can make do with the two entity tables because at least one
entity involved has a multiplicity of one.
Setting up the deployment descriptor
All setup related to CMR is done in the <relationships> section. We set up our many2many relationship like this:
 <relationships>
  <ejb-relation>
   <ejb-relation-name>many2many_student_course_mapping</ejb-relation-name>
   <ejb-relationship-role>
    <multiplicity>Many</multiplicity>
    <relationship-role-source>
     <ejb-name>many2many_StudentBean</ejb-name>
    </relationship-role-source>
    <cmr-field>
     <cmr-field-name>courseList</cmr-field-name>
     <cmr-field-type>java.util.Collection</cmr-field-type>
    </cmr-field>
   </ejb-relationship-role>
   <ejb-relationship-role>
    <multiplicity>Many</multiplicity>
    <relationship-role-source>
     <ejb-name>many2many_CourseBean</ejb-name>
    </relationship-role-source>
    <cmr-field>
     <cmr-field-name>studentList</cmr-field-name>
     <cmr-field-type>java.util.Collection</cmr-field-type>
    </cmr-field>
   </ejb-relationship-role>
  </ejb-relation>
 </relationships>
Every <ejb-relation> has two participating entity beans. Their role in the relation is defined within a <ejb-relationship-role> section. Use the <ejb-name> tag to describe which entity the <ejb-relationship-role> block belongs to.
Resin-CMP expects the mapping table to have the same name as the relation it is used for. We can set the relation's name with the <ejb-relation-name> tag. In this case, the relation is called many2many_student_course_mapping, which is why we also have a table called many2many_student_course_mapping in our schema.
Writing code for the CMR fields
For the CourseBean, we have defined studentList
as a CMR
field. We need to match this with a method declaration in CourseBean.java:
abstract public Collection getStudentList();
which Resin-CMP will implement for us. The getStudentList()
method will return a Collection of all students enrolled in a course.
For adding Students to the course, instead of defining a set-method,
we can simply add to the Collection:
// adding a student to a house
house.getStudentList().add(student);
We have the reverse case with StudentBean's courseList
CMR field. In StudentBean.java, we need to define
abstract public Collection getCourseList();
Resin-CMP will implement this method to return a Collection of all Courses
that a student is currently enrolled in. To enroll the student in another
Course, we can call
// enrolling a student in a course
student.getCourseList().add(course);