This snippet shows how to define collection classes, join classes, and many-to-many relationships. An intermediate join class is used to hold the references for a many-to-many relationship. The snippet also shows examples of deep and shallow operations involving related objects. For a many-to-many relationship, the entities involved in the relationship are considered independent in the sense that insert, update, and delete operations don't go beyond the intermediate join class (table).
In the example object model, one user may have many groups and one group may have many users.
- package com.softwaretree.jdxrelationshipsexample.model;
- import java.util.List;
- public class Group {
- public int gId;
- public String gName;
- public List<User> users; // A collection of User objects
- public Group() {
- }
- // Other constructors and accessor (setter/getter) methods omitted
- package com.softwaretree.jdxrelationshipsexample.model;
- import java.util.Vector;
- public class User {
- public int uId;
- public String uName;
- public Vector<Group> groups; // A Collection of Group objects
- public User() {
- }
- // Other constructors and accessor (setter/getter) methods omitted
- package com.softwaretree.jdxrelationshipsexample.model;
- public class UserGroup {
- public int uId;
- public int gId;
- public UserGroup() {
- }
- // Other constructors and accessor (setter/getter) methods omitted
- JDX_OBJECT_MODEL_PACKAGE com.softwaretree.jdxandroidrelationshipsexample.model
- CLASS .UserGroup TABLE USER_GRP
- PRIMARY_KEY uId gId
- ;
- JOIN_COLLECTION_CLASS ListUsers COLLECTION_TYPE JAVACOLLECTION ELEMENT_CLASS .User JOIN_CLASS .UserGroup
- PRIMARY_KEY gId
- JOIN_KEY uId
- ORDERBY uName
- ;
- CLASS .Group TABLE GRP
- PRIMARY_KEY gId
- RELATIONSHIP users REFERENCES ListUsers BYVALUE WITH gId
- ;
- JOIN_COLLECTION_CLASS VectorGroups COLLECTION_TYPE VECTOR ELEMENT_CLASS .Group JOIN_CLASS .UserGroup
- PRIMARY_KEY uId
- JOIN_KEY gId
- ;
- CLASS .User TABLE USER
- PRIMARY_KEY uId
- RELATIONSHIP groups REFERENCES VectorGroups BYVALUE WITH uId
- ;
- // Obtain ORM handles.
- JXResource jxResource = jdxSetup.checkoutJXResource();
- JXSession jxSessionHandle = jxResource.getJXSessionHandle();
- JDXS jdxHandle = jxResource.getJDXHandle();
- String userClassName = User.class.getName();
- String groupClassName = Group.class.getName();
- int gId = 1;
- int uId = 101;
- String gNameBase = "group";
- String uNameBase = "user";
- // Many-to-many relationship among two classes employs an intermediate join class (table).
- //
- // If an insert, update, and delete operation on the instances of such classes is done
- // in a 'deep' fashion, the operation is limited to the top-level objects and the
- // associated join class objects. In other words, these operations do not change
- // the related objects in the database to avoid unintended recursion.
- //
- // A 'deep' query operation does extend upto the related objects but avoids recursion by
- // not fetching the related top-level original objects.
- try {
- // ********** Start a transaction to delete all the existing objects. ***********
- jxSessionHandle.tx_begin();
- // First delete all the existing User objects from the database.
- // This should also get rid of the associated join table entries
- // because of the use of the parameter JDXS.FLAG_DEEP.
- jdxHandle.delete2(userClassName, null, JDXS.FLAG_DEEP);
- // Now delete all the existing Group objects from the database.
- // There is no need of getting rid of the associated join table entries because
- // they would have already been deleted while deleting User object earlier.
- // Hence the use of the parameter JDXS.FLAG_SHALLOW.
- jdxHandle.delete2(groupClassName, null, JDXS.FLAG_SHALLOW);
- // Commit the transaction.
- jxSessionHandle.tx_commit();
- // ********** Now create a new Group with 2 new User objects.
- Group g1 = new Group(gId, gNameBase+gId);
- User u1 = new User(uId, uNameBase+uId);
- uId++;
- User u2 = new User(uId, uNameBase+uId);
- List <User> users = new ArrayList <User>();
- users.add(u1);
- users.add(u2);
- g1.setUsers(users);
- // ********** Now insert the new Group and its Users under a transaction *********
- jxSessionHandle.tx_begin();
- // Users have to be inserted separately because a many_to_many insert does
- // not go beyond the join table. Users can be inserted after the join table is
- // populated if there is no referential integrity specified
- // at the database level. Otherwise, user instances have to be inserted first.
- jdxHandle.insertMany(users, JDXS.FLAG_SHALLOW, null);
- // Insert the Group object now. This would also populate the join table
- // for the associated User objects.
- jdxHandle.insert(g1, JDXS.FLAG_DEEP, null);
- // Commit the transaction.
- jxSessionHandle.tx_commit();
- // Now do a shallow query for all the Group objects
- List queryResults = jdxHandle.query(groupClassName, null, -1, JDXS.FLAG_SHALLOW, null);
- // Now do a deep query for all the Group objects along with the associated User objects
- queryResults = jdxHandle.query(groupClassName, null, -1, JDXS.FLAG_DEEP, null);
- // Now do a shallow query for all the User objects
- queryResults = jdxHandle.query(userClassName, null, -1, JDXS.FLAG_SHALLOW, null);
- // Now do a deep query for all the User objects along with the associated Group objects
- queryResults = jdxHandle.query(userClassName, null, -1, JDXS.FLAG_DEEP, null);
- // ********** Now create a new User u3 belonging to a new Group g2.
- uId++;
- User u3 = new User(uId, uNameBase+uId);
- gId++;
- Group g2 = new Group(gId, gNameBase+gId);
- Vector<Group> groups = new Vector<Group>();
- groups.addElement(g2);
- u3.setGroups(groups);
- // ********** Now insert the new User u3 and its Group under a transaction *********
- jxSessionHandle.tx_begin();
- // First insert the Group g2
- jdxHandle.insert(g2, JDXS.FLAG_SHALLOW, null);
- // Now insert the User u3. This would also populate the join table for
- // the associated Group object.
- jdxHandle.insert(u3, JDXS.FLAG_DEEP, null);
- // Make the new User u3 also associated with Group g1.
- // The following is an alternate way of showing how existing objects can be connected
- // in many-to-many relationships by just populating the join object UserGroup.
- // We could have added Group g1 in the Vector groups above before inserting
- // User u3 to get the same effect.
- UserGroup ug = new UserGroup(u3.getuId(), g1.getgId());
- jdxHandle.insert(ug, JDXS.FLAG_SHALLOW, null);
- // Commit the transaction.
- jxSessionHandle.tx_commit();
- // At this point, we have the following situation:
- // Group g1 has User u1, u2, and u3.
- // Group g2 has User u3
.- // User u1 belongs to Group g1.
- // User u2 belongs to Group g1.
- // User u3 belongs to Group g1 and g2.
- // Now do a deep query for all the User objects along with the associated Group objects
- queryResults = jdxHandle.query(userClassName, null, -1, JDXS.FLAG_DEEP, null);
- // Now do a deep query for the Group g1 along with the associated User objects
- queryResults = jdxHandle.query(groupClassName, "gId=" + g1.getgId(), -1, JDXS.FLAG_DEEP, null);
- // Now update the User object u3 in memory and then persist the changes in the database
- u3.setuName("new " + u3.getuName());
- jdxHandle.update(u3, JDXS.FLAG_SHALLOW, null);
- // Now do a deep query for the Group g2 along with the associated updated User u3
- queryResults = jdxHandle.query(groupClassName, "gId=" + g2.getgId(), -1, JDXS.FLAG_DEEP, null);
- // Now do a deep delete of a Group g1. This will also delete the join table
- // entries for Group g1 effectively removing all its relationships with any User
- // objects. The deep delete operation does not delete the related User objects though.
- jdxHandle.delete(g1, JDXS.FLAG_DEEP, null);
- // At this point, we have the following situation:
- // Group g1 does not exist.
- // Group g2 has User u3.
- // User u1 belongs to none of the groups.
- // User u2 belongs to none of the groups.
- // User u3 belongs to Group g2.
- // Do a deep query for all the User objects along with the associated Group objects
- queryResults = jdxHandle.query(userClassName, null, -1, JDXS.FLAG_DEEP, null);
- // Now do a deep query for the Group objects along with the associated User objects
- queryResults = jdxHandle.query(groupClassName, null, -1, JDXS.FLAG_DEEP, null);
- } catch (Exception ex) {
- throw ex;
- } finally {
- jdxSetup.checkinJXResource(jxResource);
- }