The application server is running out of memory doing a JPQL query. The query
loads an entity with a simple – "SELECT Object(o) from Order o where o.id=:id".
id is the primary key for Order.
This is happening specifically for the JOINED inheritance strategy when the base
class has a Secondary table annotation. The id being passed to the query matches
an instance of an entity derived from Order.
Running the same query for a SINGLE_TABLE strategy does not cause the same problem.
For the JOINED strategy, the appserver is doing more Full GCs which take 30-45
seconds and eventually runs out of memory. Again, the SINGLE_TABLE does not have
A memory profile of JOINED strategy with the above query shows a large of number
of Strings, char and other objects being created, mostly by the jdbc driver.
It also shows a large number of
oracle.toplink.essentials.sessions.DatabaseRecord objects being created in the
fetchRow method of
oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor class [which
eventually seems to be hitting the jdbc driver which creates the above String,
A CPU profile shows that the fetchRow method of DatabaseAccessor is being called
a large number of times, this in turn is creating a large number of
A comparison of the CPU profile to the SINGLE_TABLE strategy shows that there is
large difference in the number of calls being made to fetchRows.
SINGLE_TABLE – 1510 invocations
JOINED – 391865 invocations
The SINGLE_TABLE profile shows that all 1510 invocations are originating from
the application used for profiling.
The JOINED profile shows that all 391865 invocations originate from
DatabaseAccessor.basicExecuteCall, but there is only one invocation of this
(basicExecuteCall) method from the application which means a large number of
data is being read from the db, which should not be the case.
So looking at the SQL generated for JOINED strategy when the base class has
Secondary table shows –
SELECT t0.ID, t0.DTYPE, t1.ID, t1.REVISION, t1.NAME, t0.DESCRIPTION,
t0.CUSTOMER_ID, t0.CARRIER_ID, t2.ID, t2.SMALLORDERTAG, t3.ID,
t3.MEDIUMORDERTAG, t4.ID, t4.LARGEORDERTAG FROM LARGEORDER t4, MEDIUMORDER t3,
SMALLORDER t2, ORDER_SEC t1, J1Order t0 WHERE ((t0.ID = ?) AND (t1.ID = t0.ID))
Although the where clause contains the join for secondary table, it does not
contain any constraints for joining between the base entity and the derived
entities, so this is really a colossal cartesian product.