JIRA Issue: https://issues.apache.org/jira/browse/OPENJPA-1188
On Tue, Jul 21, 2009 at 8:42 AM, Kevin Sutter kwsut...@gmail.com wrote:
For those of you interested, here are the details on this problem and
what's required to reproduce it. I will be opening a JIRA and posting a
testcase shortly.
Requirements...
o Your Entity needs to have an attribute that OpenJPA wrappers with a
proxy. This proxy is used to detect changes to these object types. Example
object types that OpenJPA wrappers are Calendar (culprit for this scenario),
Date, Collection, and Map.
o In the Setter method for the proxied attribute, you must modify the
value getting set. In this scenario, the Calendar object was being modified
in the setDate method via the set() method.
o The Entity must be using property-based access (annotations on the
Getter methods).
o The Persistence Context must be clear of any Entities that are being
queried. For example, my testcase was persisting several Entities before
executing the Query that was supposedly generating the extra SQL
statements. If I didn't clear the Persistence Context before executing the
Query, the Entities were already populated and it didn't trigger the extra
SQL statements.
o And, now comes the magic... :-) Access to the attribute's meta data
seems to be done alphabetically. From what I can tell, this seems to be a
Java format convention. In any case, the extra SQL statements are used to
re-populate any attributes that are alphabetically after the proxied
attribute that was modified in the corresponding Setter method.
Given all of that setup, here's an explanation of what's happening...
After the initial query is executed, the resulting Entity objects need to
be populated with the data returned by the query. When the setter was
called for this proxied attribute, and the value was modified, this
attribute (and the Entity) was marked as being dirty. Part of the dirty
processing is to determine which fields need to be re-loaded. Of course,
the proxied attribute does not have to be re-loaded since it was in the
process of being modified. The id field does not have to re-loaded since
we're using id generation for this particular scenario. And, any fields
that are alphabetically before the proxied attribute were just loaded, so
they don't have to be re-loaded. But, any fields that come after the
proxied attribute (alphabetically) don't realize that they will be loaded
(due to the original query), so the extra SQL is pushed out to load these
fields.
As you can see, many stars had to align to reproduce this scenario. I
appreciate Mikhail's patience while we worked through the issue. And, I
appreciate the extra insights from Mike and Ravi. This was actually quite
fun to debug (in a sadistic point of view). :-)
Thanks,
Kevin
On Mon, Jul 20, 2009 at 10:40 AM, Kevin Sutter kwsut...@gmail.com wrote:
I reproduced the problem! There's something about the logic in Mikhail's
resetTime method that is affecting the populating of the entities. My
resetTime() method had similar logic, but not exactly what Mikhail had. I
replaced the implementation and poof I reproduced the problem.
I'll do some more experimenting to further isolate the problem and get a
JIRA filed (maybe even resolved).
Thanks, Mikhail, for your patience and assistance. This was a strange
one, indeed.
Kevin
On Mon, Jul 20, 2009 at 9:30 AM, om mikhail.ostrya...@ubs.com wrote:
Hi,
I don't have simple example. It looks like I can't help you here,
unfortunately. This strange behavior occured on openJPA 1.0 embedded in
WebSphere, OpenJPA 1.2.1 and last 2.0 versions linked to my application
and
initialized explicitly in code ( not through dependency injection ).
Account
object and persistence.xml are provided earlier, and they're extremely
simple. Util.resetTime is extremely simple as well :
public static Calendar resetTime(Calendar date) {
if (date == null) return null;
date.set(Calendar.HOUR_OF_DAY, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);
return date;
}
WebSphere 6.1.0.21 with EJB3.0 pack, ORACLE version has been provided
earlier (10.2.0.3 as I remember).
Can't imagine what else can follow openJPA to this strange behavior...
Kevin Sutter wrote:
Hi Mikhail,
If you can believe this, I still can not reproduce the problem. What
exactly does your util.resetTime() method do?
I have been trying your scenario with old and new versions of OpenJPA.
I
even went back and used the same JVM (IBM JDK 5sr6b). Still no luck.
I can't any references in the spec or the OpenJPA documentation that
restricts the code within getters and setters, but we do document how
we
proxy Date classes (and other similar types) so that we can more easily
detect updates to these fields. You have shown how this affects your
usage.