Re: Re: OJB: Identity equals method impl.

"Virgo Smart" <[email protected]>
Newsgroups gmane.comp.jakarta.ojb.user
Message-ID <[email protected]>
  
Hello,

I figured out what the problem is. I am using a table per subclass mapping strategy using sub-class/table FK referencing to the super-class/table PK.
However there still is a problem with generating unique values for the id field across all extents. Adapting an example from the Apache-OJB site, consider the scenario Manager and Consultant classes extend Executive extends Employee where in each class is mapped to their own tables.

EMPLOYEE table has columns ID, NAME.
EXECUTIVE table has columns ID, DEPT, EMP_ID (where EMP_ID is a FK referencing EMPLOYEE.ID).
MANAGER table has columns ID, CONSORTIUM_ID, EXEC_ID (where EXEC_ID is a FK referencing EXECUTIVE.ID).
CONSULTANT table has columns ID, EXT_REF_CODE, EXEC_ID (where EXEC_ID is a FK referencing EXECUTIVE.ID).

The class descriptors for Employee, Executive, Manager and Consultant are defined as follows.

<class-descriptor class="Employee" table="EMPLOYEE">

    <extent-class class-ref="Executive" />

    <field-descriptor
        name="id"
        column="ID"
        jdbc-type="BIGINT"
        primarykey="true"
        autoincrement="true"
    />

    <field-descriptor
        name="name"
        column="NAME"
        jdbc-type="VARCHAR"
    />

</class-descriptor>

<class-descriptor class="Executive" table="EXECUTIVE">
    
    <extent-class class-ref="Manager" />
    <extent-class class-ref="Consultant" />

    <field-descriptor
        name="id"
        column="ID"
        jdbc-type="BIGINT"
        primarykey="true"
        autoincrement="true"
    />

    <field-descriptor
        name="department"
        column="DEPT_ID"
        jdbc-type="BIGINT"
    />

    <field-descriptor
        name="employeeId"
        column="EMP_ID"
        jdbc-type="BIGINT"
	access="anonymous"
    />

    <reference-descriptor name="super"
        class-ref="Employee"
    >
        <foreignkey field-ref="employeeId"/>
    </reference-descriptor>

</class-descriptor>

<class-descriptor class="Manager" table="MANAGER">
    
    <field-descriptor
        name="id"
        column="ID"
        jdbc-type="BIGINT"
        primarykey="true"
        autoincrement="true"
    />

    <field-descriptor
        name="consortiumId"
        column="CONSORTIUM_ID"
        jdbc-type="BIGINT"
    />

    <field-descriptor
        name="executiveId"
        column="EXEC_ID"
        jdbc-type="BIGINT"
	access="anonymous"
    />

    <reference-descriptor name="super"
        class-ref="Executive"
    >
        <foreignkey field-ref="executiveId"/>
    </reference-descriptor>
</class-descriptor>

<class-descriptor class="Consultant" table="CONSULTANT">
    
    <field-descriptor
        name="id"
        column="ID"
        jdbc-type="BIGINT"
        primarykey="true"
        autoincrement="true"
    />

    <field-descriptor
        name="externalRefCode"
        column="EXT_REF_CODE"
        jdbc-type="VARCHAR"
    />

    <field-descriptor
        name="executiveId"
        column="EXEC_ID"
        jdbc-type="BIGINT"
	access="anonymous"
    />

    <reference-descriptor name="super"
        class-ref="Executive"
    >
        <foreignkey field-ref="executiveId"/>
    </reference-descriptor>

</class-descriptor>


I wish to have the ID column values unique across all the 4 database tables.
Currently when I insert 1 Manager and 1 Consultant, data in stored in the table as follows.

EMPLOYEE : Two rows are inserted. (1 row each for Manager and Consultant). Here assuming that Manager data was first to be stored, ID = 1 for Manager and ID = 2 for Consultant.
EXECUTIVE: Two rows are inserted with ID same as those stored in the EMPLOYEE table.
MANAGER  : 1 row inserted. ID = 1
CONSULTANT : 1 row inserted. ID = 1

What I wish to have is the ID value in the CONSULTANT table to be set to 2 (matching value stored in EMPLOYEE and EXECUTIVE tables) instead of 1.

I am trying to use SequenceManager implementations but am not able to generate a sequence number. Further more I am not sure if using sequence manager would solve this problem. I some how want to indicate to the OJB broker to use the id attribute value of the base class when persisting the child classes.

Regards,
Gautam  


On Fri, 17 Nov 2006 Armin Waibel wrote :
>Hi,
>
>Virgo Smart wrote:
>>   In my attempt to solve a problem when retrieving object references (collection and simple) from a domain/persistent class, I looked up Identity.java class source as I suspect identity object as the source of the problem.
>>
>>The equals method of the identity class does not seem to take the object's real class type (m_objectsRealClass attrib) into account when comparing two identities. Is the equals method correctly implemented ?
>>
>
>yep! It's expected behavior. In certain circumstances it's not possible to resolve the real class of an object when building the Identity. For example: Interface Article with real classes CdArticle and BookArticle (in mapping file Article is declared with "extent" classes CdArticle and BookArticle). Now we define a 1:1 reference from Class A to Article. In this case we don't know the real class but the top-level class and can build the Identity object using the FK fields (in class A) and the top-level class.
>
>Long time ago it seems to be a good solution to use the top-level class with PK fields as object Identity. This help to avoid problems with "declared class" (interface, abstract class or real class) and the real class of an object in references.
>
>Could you describe more detailed (e.g. with pseudo code or a unit test + class mapping) what your problem is?
>
>regards,
>Armin
>
>
>>Equals method in Identity.java:
>>
>>     public boolean equals(final Object obj)
>>     {
>>         if(this == obj) return true;
>>
>>         boolean result = false;
>>         if (obj instanceof Identity)
>>         {
>>             final Identity id = (Identity) obj;
>>             result = m_objectsTopLevelClass.equals(id.m_objectsTopLevelClass) && isTransient == id.isTransient;
>>             if(result)
>>             {
>>                 final Object[] otherPkValues = id.m_pkValues;
>>                 result = m_pkValues.length == otherPkValues.length;
>>                 if(result)
>>                 {
>>                     for (int i = 0; result && i < m_pkValues.length; i++)
>>                     {
>>                         result = (m_pkValues[i] == null) ? (otherPkValues[i] == null)
>>                                 : m_pkValues[i].equals(otherPkValues[i]);
>>
>>                         // special treatment for byte[]
>>                         if (!result && m_pkValues[i] instanceof byte[] && otherPkValues[i] instanceof byte[])
>>                         {
>>                             result = Arrays.equals((byte[]) m_pkValues[i], (byte[]) otherPkValues[i]);
>>                         }
>>                     }
>>                 }
>>             }
>>         }
>>         return result;
>>     }
>>
>>
>>Javadoc for Identity.java class:
>>
>>public class Identity
>>extends java.lang.Object
>>implements java.io.Serializable
>>
>>Represents the identity of an object. It's composed of: 
>>class of the real object 
>>top-level class of the real object (could be an abstract class or interface or the class of the object itself), used to make an object unique across extent classes
>>  an array of all primary key value objects 
>>a flag which indicates whether this is a transient Identity (identity of a non-persistent, "new" object) or a persistent Identity (identity object of a persistent, "already written to datastore" object). 
>>Thanks and Regards,
>>Gautam.
>>
>>  
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: [email protected]
>For additional commands, e-mail: [email protected]
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.