Using Associations - C++

Click here to view in Java

Unidirectional Associations


Defining Unidirectional Associations in the DDL file.

This is how you would define a unidirectional association in the ddl file. You must be sure to specify the propagate property to distinguish it from a reference.

ooRef(classToPointTo) associationName : copy(delete); //one-to-one
ooRef(Person) friend[] : copy(delete); //one-to-many, this class points to many Person

In this example, we have a class Car and a class Part. We will have an association from a part to a car called belongsTo.

objects.ddl


class Car : ooObj
{
private:
    int VIN;
public:
    void setVin(int vinNum)
    {
        ooUpdate();
        VIN = vinNum;
    }
    int returnVin()
    {
        return VIN;
    }
};

class Part : ooObj
{
public:
    int partNum;
    void setPartNum(int num)
    {
        ooUpdate();
        partNum = num;
    }
    int returnPartNum()
    {
        return partNum;
    }
    ooRef(Car) belongsTo : copy(delete);
    //the copy(delete) is the propagate specification
    //must specify to distiguish an association from a reference

    //ooRef(Car) belongsTo[] : copy(delete); //<-- toMany assocation, this part belongs to many cars
};

Note: Unlike bidirectional associations, if you delete an object, you must remember to delete all associations pointing to it.



Bidirectional Associations


Defining Bidirectional Associations in the DDL file.

This is how you would define a bidirectional association in the ddl file.

ooRef(classToPointTo) fromName <-> toName; //one-to-one
ooRef(classToPointTo) fromName[]<-> toName; //many-to-one
ooRef(classToPointTo) fromName <-> toName[]; //one-to-many
ooRef(classToPointTo) fromName[] <-> toName[]; //many-to-many

In this example, we have a class Car and a class Part. We will have an association from a part to a car called belongsTo.

objects.ddl



class Car : ooObj
{
private:
    int VIN;
public:
    void setVin(int vinNum)
    {
        ooUpdate();
        VIN = vinNum;
    }
    int returnVin()
    {
        return VIN;
    }
    ooRef(Part) contains[] <-> belongsTo[]; //many-to-many
};

class Part : ooObj
{
public:
    int partNum;
    void setPartNum(int num)
    {
        ooUpdate();
        partNum = num;
    }
    int returnPartNum()
    {
        return partNum;
    }
    ooRef(Car) belongsTo[] <-> contains[]; //many-to-many
};

Note: Bidirectional association automatically takes care of its own integrity. If you delete one side of the association, the other side is automatically deleted. If you delete an object of one side of the association, the association on the other side is deleted automatically.



Adding Associations.

The ddl processor will create the set_linkname function for setting to-one associations and an add_linkname function for to-many associations.

partObj->set_belongsTo(carObj);
//partObj is the handle to the Part object
//belongsTo is the name of the to-one association attribute.
//carObj is the handle to the Car object

//partObj->add_belongsTo(carObj); //for to-many associations, use add_linkname

The following is an example of adding 100 parts to 1 car.

addAssoc.cpp


#include <iostream>
using namespace std;
#include <ooObjy.h>
#include "objects.h"

int main(int argc, char* argv[])
{
  int returnval = 0;
  //ooObjy::setLoggingOptions(oocLogAll, oocTrue, oocFalse);	//enable session logging for debug
  ooObjy::startup();
  char *bootfile = "test.boot";     //insert bootfile name here
  char *dbName = "testDB";          //insert database name here
  char *contName = "testCont";      //insert container name here

  ooConnection *connection = ooObjy::getConnection(bootfile);

  ooSession *session = connection->createSession("main_session");     //insert session name for log or '0' for default

  try
  {

    session->begin(oocUpdate);

    ooHandle(ooFDObj) fd;
    fd.exist(bootfile, oocUpdate);        //open in update mode

    ooHandle(ooDBObj) db;                 //open/create db
    if (db.exist(fd, dbName));
    else
    {
      db = new ooDBObj(dbName);
    }

    ooHandle(ooContObj) cont;             //open/create cont
    if (cont.exist(db, contName, oocUpdate));
    else
    {
      cont = new(db, 4, 0, contName) ooContObj;
    }

    ooHandle(Car) carObj;
	carObj = new(cont) Car();

	ooHandle(Part) partObj;
    for (int i = 0; i < 100; i++)
    {
      partObj = new(cont) Part();
      partObj->setPartNum(i);
      partObj->set_belongsTo(carObj);
    }


    session->commit();
  }

  catch(ooException &error)
  {
    cerr << error.what() << endl;
    session->abort();
    returnval = 1;
  }

  catch(...)
  {
    cerr << "unknown error" << endl;
    session->abort();
    returnval = 1;
  }

  ooObjy::shutdown();
  return returnval;
}





Deleting Associations.

To delete a to-one association, you use the del_linkname function.
To delete a to-many association, you use sub_linkname.

partObj->del_belongsTo();
//partObj->sub_belongsTo(carObj);  //carObj is the handle to the Car that this association is pointing to

Continuing from the associations created in the last database, here you find a Part with partNum 23 and delete its association to the car.

UnidirectionalAssoc.cpp


#include <iostream>
using namespace std;
#include <ooObjy.h>
#include "objects.h"

int main(int argc, char* argv[])
{
  int returnval = 0;
  //ooObjy::setLoggingOptions(oocLogAll, oocTrue, oocFalse);	//enable session logging for debug
  ooObjy::startup();
  char *bootfile = "test.boot";     //insert bootfile name here
  char *dbName = "testDB";          //insert database name here
  char *contName = "testCont";      //insert container name here

  ooConnection *connection = ooObjy::getConnection(bootfile);

  ooSession *session = connection->createSession("main_session");     //insert session name for log or '0' for default

  try
  {

    session->begin(oocUpdate);

    ooHandle(ooFDObj) fd;
    fd.exist(bootfile, oocUpdate);        //open in update mode

    ooHandle(ooDBObj) db;                 //open/create db
    if (db.exist(fd, dbName));
    else
    {
      db = new ooDBObj(dbName);
    }

    ooHandle(ooContObj) cont;             //open/create cont
    if (cont.exist(db, contName, oocUpdate));
    else
    {
      cont = new(db, 4, 0, contName) ooContObj;
    }

    ooHandle(Part) partObj;

    ooItr(Part) partItr;  //declares iterator to scan for Part objects
    if(partItr.scan(cont, "partNum == 23"))  //scan the container for Part object
    {
	partItr.next();  //iterate
	partObj = (ooHandle(Part)) partItr; //cast iterator to object handle
	partObj->del_belongsTo();

        //ooHandle(Car) carObj;
        //initialize carObj by scan or lookupObj by name
        //partObj->sub_belongsTo(carObj);  //for to-many
	cout << "deleted part 23 association to car" << endl;
    }
    session->commit();
  }

  catch(ooException &error)
  {
    cerr << error.what() << endl;
    session->abort();
    returnval = 1;
  }

  catch(...)
  {
    cerr << "unknown error" << endl;
    session->abort();
    returnval = 1;
  }

  ooObjy::shutdown();
  return returnval;
}