users@glassfish.java.net

Does Toplink JPA hold older version of entities in transactional cache?

From: <glassfish_at_javadesktop.org>
Date: Wed, 25 Feb 2009 19:44:37 PST

JPA Implementation - Toplink JPA
Version - Current release: version 2 build 41
Application mode - Standalone
Transaction Manager - Atomikos JTA 3.3.
Database - MS Sql Server 2005

I have been struggling with this problem for a while now. I cant seem to figure out what is going on. Looks like this is a bug in toplink. Here is a description of the problem. I am using simple A and B names for classes for simplicity, hope that helps.

Any help is appreciated.

I have Entity A that has one-to-many relationship with Entity B. C and D are subtypes of B based on an integer attribute(discriminating column) called type. All of these relationships are configured in orm.xml for JPA. All entities have unique indentifiers, "id" ,that are integer values.

One particular instance of A has 20 items of B.

I delete one instance of B (of concrete type C) from A's list of Bs. I see that toplink executes the sql command to delte rows in appropriate table, and it updates object to remove the reference. In the same transaction, I add an instance of D into the list with the same id as the previously deleted instance of C. When I update A entityManager.merge(), with this new list, I get a DescriptorException saying cannot update object of type C with attribute of D.

In the same transaction, this is what happens.

begintransaction()
A a = entityManager.find(A.class, id);
//a has 10 objects, one of them with id bid
//remove that object from A
C c = a.remove(bid);
//merge A
entityManager.merge(a);
//i see the database commands for deletion of a row in the log
entityManager.flush()

...
//get object again, later in the same transaction
A a = entityManager.find(A.class, id);
//I confirm that a has only 9 items now, and there is no object c with id bid
a.add(new D(bid));
//i add a new object of type D with same id and add it into the list of A
entityManager.merge(a); ==> throws exception that looks like below.
commitTransaction()

Exception [TOPLINK-32] (Oracle TopLink Essentials - 2.0 (Build b41-beta2 (03/30/2007))): oracle.toplink.essentials.exceptions.DescriptorException
Exception Description: Trying to set value [0] for instance variable [fullTextOptions] of type [int] in the object. The specified object is not an instance of the class or interface declaring the underlying field, or an unwrapping conversion has failed.
Internal Exception: java.lang.IllegalArgumentException: Can not set int field com.bmc.arsys.server.persistence.CharFieldEntity.fullTextOptions to com.bmc.arsys.server.persistence.DateFieldEntity
Mapping: oracle.toplink.essentials.mappings.DirectToFieldMapping[fullTextOptions-->field_char.fullTextOptions]
Descriptor: RelationalDescriptor(com.bmc.arsys.server.persistence.CharFieldEntity --> [DatabaseTable(field), DatabaseTable(field_char)])


Now, if I do the same exact thing in two different transactions, it works fine. For eg. this below seems to work fine.

begintransaction()
A a = entityManager.get(id);
//a has 10 objects, one of them with id bid
//remove that object from A
C c = a.remove(bid);
//merge A
entityManager.merge(a);
//i see the database commands for deletion of a row in the log
entityManager.flush()

commitTransaction()
...
beginTrasaction()
//get object again, later in the same transaction
A a = entityManager.get(id);
//I configm that a has only 9 items now, and there is no object c of id bid
a.add(new D(bid));
//i add a new object of type D with same id and add it into the list of A
entityManager.merge(a);
commitTransaction()
[Message sent by forum member 'pmysore' (pmysore)]

http://forums.java.net/jive/thread.jspa?messageID=333910