Hi Gautam,

Virgo Smart wrote:
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.


This isn't a SequenceManager issue, so a user-based SequenceManager implementation will not help. I think there is a documentation bug in OJB and when using TPS-inheritance with foreign key settings there is a bug when overriding the id fields in sub-classes.

The autoincrement setting in the sub-classes will always be ignored by OJB (and the PK of the base table will be copied to all sub-table PK columns, thus there is no need to use a FK field), except the id field is overridden in the sub-class (then the mapping via FK is mandatory):

class Employee
{
 Integer id;
...
}

class Executive extends Employee
{
// override field
Integer id;
...
}

But this will not work correct with current version of OJB. Will try to fix this ASAP.

Don't declare "extent-class" entries when using TPS inheritance (think this could cause side-effects).
So I recommend to use the "normal" TPS inheritance.

regards,
Armin

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]





---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to