DataNucleus JIRA is now in read-only mode. Raise any new issues in GitHub against the plugin that it applies to. DataNucleus JIRA will remain for the foreseeable future but will eventually be discontinued
Issue Details (XML | Word | Printable)

Key: NUCCORE-693
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: Andy Jefferson
Reporter: Guido Anzuoni
Votes: 0
Watchers: 0

If you were logged in you would be able to see more operations.
DataNucleus Core

Get object by id (app identity) does not check if the real class in the datastore for the id matches the requested class

Created: 08/Apr/11 02:42 PM   Updated: 09/May/11 09:58 AM   Resolved: 10/Apr/11 09:45 AM
Component/s: None
Affects Version/s: None
Fix Version/s: 3.0.0.m4

File Attachments: 1. Zip Archive (3 kB)

 Description  « Hide
class A {
long id;
class B extends A {

class C extends A {

If I have this database rows:
1 B
2 C

Now if I call (JPA):
em.find(B.class, new Long(2))
DN returns a Java instance of B class while in the DB the instance with id=2 is of class C.

If I execute a query like
select b from B b where = 2
DN returns correct empty result
If I do:
   select c from C c where = 2
and then
   em.find(B.class, new Long(2))

I have two different java object instances.
A, B, C are mappend onto the same table.

Andy Jefferson added a comment - 08/Apr/11 08:31 PM
If i call em.find(B.class, Long(2)) I get SQL like the following
SELECT `A0`.`TYPE` FROM `A` `A0` WHERE ((`A0`.`TYPE` = 'B' OR `A0`.`TYPE` = 'C')) AND `A0`.`ID` = <2>
and it uses the 'TYPE' to see that it is a C, and creates a C object. No problems with the latter route either.

Andy Jefferson made changes - 08/Apr/11 08:31 PM
Field Original Value New Value
Priority Critical [ 2 ] Incomplete [ 6 ]
Guido Anzuoni added a comment - 08/Apr/11 10:40 PM - edited
Hmmm, I have different results.
I thought that the difference could be cause by A being a mapped superclass but no, it is not the case.....
I get your same result in case of
em.find(A.class, new Long(2);

Guido Anzuoni added a comment - 08/Apr/11 11:44 PM
If I modify RDBMSStoreManager at line 946 into:

            AbstractClassMetaData cmd = getMetaDataManager().getMetaDataForClass(className, clr);
            cmd = cmd.getBaseClassManagingTable();
where (in AbstractClassMetaData )
    public AbstractClassMetaData getBaseClassManagingTable()
        if (getInheritanceMetaData().getStrategy() == InheritanceStrategy.NEW_TABLE)
            return this;
        AbstractClassMetaData cmd = getSuperclassManagingTable();
        return cmd;

I get:
java.lang.ClassCastException: org.datanucleus.test.CClass cannot be cast to org.datanucleus.test.BClass
at org.datanucleus.test.MainOID.main(
if I do
B b = em.find(B.class, new Long(2))
while if I do
Object b = em.find(B.class, new Long(2))
b.getClass() == C.class !!!!

Maybe the should apply in the case :
if (id instanceof OID) at line 931

but this is for RDBMS. And the other store ? DB4O, Excel etc ?

Last but not least, what would be the right outcome ? ClassCastException, null ?

Guido Anzuoni added a comment - 09/Apr/11 12:08 AM
core patch adds the method to get the base class managing a table in a hierarchy and
in ObjectManagerImpl there is the check to verify that the class indicated in the requested id is assignable from the class of the real object that would be returned to the app.
In case of mismatch NucleusObjectNotFoundException is raised

Guido Anzuoni made changes - 09/Apr/11 12:08 AM
Attachment dncore-superclassoidcheck.patch [ 11412 ]
Attachment dnrdbms-superclassoidcheck.patch [ 11413 ]
Guido Anzuoni added a comment - 09/Apr/11 01:07 AM
Added method in AbstractClassMetaData was not considering all the possible inheritance strategies

Guido Anzuoni made changes - 09/Apr/11 01:07 AM
Attachment dncore-superclassoidcheck_fix.patch [ 11414 ]
Guido Anzuoni made changes - 09/Apr/11 01:08 AM
Attachment dncore-superclassoidcheck.patch [ 11412 ]
Andy Jefferson added a comment - 09/Apr/11 06:26 AM
What about a test to demonstrate this? Prerequisite to any changes

Guido Anzuoni made changes - 09/Apr/11 09:17 PM
Attachment [ 11420 ]
Andy Jefferson made changes - 10/Apr/11 09:43 AM
Attachment dncore-superclassoidcheck_fix.patch [ 11414 ]
Andy Jefferson made changes - 10/Apr/11 09:43 AM
Attachment dnrdbms-superclassoidcheck.patch [ 11413 ]
Andy Jefferson added a comment - 10/Apr/11 09:45 AM
The error is actually in the block of code that sees no subclasses of BClass, and assumes that nothing else is needed. But in this case (and some other ones that are introduced by allowing table sharing) there are other instances in the table, so we force a check.

Andy Jefferson made changes - 10/Apr/11 09:45 AM
Status Open [ 1 ] Resolved [ 5 ]
Assignee Andy Jefferson [ andy ]
Fix Version/s 3.0.0.m4 [ 11220 ]
Resolution Fixed [ 1 ]
Andy Jefferson made changes - 10/Apr/11 09:45 AM
Priority Incomplete [ 6 ] Major [ 3 ]
Andy Jefferson made changes - 09/May/11 09:58 AM
Status Resolved [ 5 ] Closed [ 6 ]