Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>By default, a join will not be done when the Employee entity is fetched from the datastore, it will only be done when Employee.position is actually read (this is called lazy loading).</p> <p>Additionally, this second fetch can be avoided using the <a href="http://www.datanucleus.org/products/accessplatform_2_0/jdo/cache.html#level2" rel="nofollow noreferrer">level 2 cache</a>. First check that the level 2 cache is actually enabled (in DataNucleus 1.1 it is disabled by default, in 2.0 it is enabled by default). You should probably then "pin" the class so that the Position entities it will be cached indefinitely:</p> <p>The level 2 cache can cause issues if other applications use the same database, however, so I would recommend only enabling it for classes such as Position which are rarely changed. For other classes, set the "cacheable" attribute to false (default is true).</p> <p><strong>EDITED TO ADD:</strong></p> <p>The &lt;join&gt; tag in your metadata is not suitable for this situation. In fact you don't need to specify the relationship explicitly at all, DataNucleus will figure it out from the types. But you are right when you say that you need POSITION_ID to be read in the default fetch group. This can all be achieved with the following change to your metadata:</p> <pre><code>&lt;field name="position" default-fetch-group="true"&gt; &lt;column name="POSITION_ID" jdbc-type="int" /&gt; &lt;/field&gt; </code></pre> <p><strong>EDITED TO ADD:</strong></p> <p>Just to clarify, after making the metadata change descibed above I ran the test code which you provided (backed by a MySQL database) and I saw only these two queries:</p> <pre><code>SELECT 'com.example.staff.Position' AS NUCLEUS_TYPE,`THIS`.`ID`,`THIS`.`TITLE` FROM `POSITION` `THIS` FOR UPDATE SELECT 'com.example.staff.Employee' AS NUCLEUS_TYPE,`THIS`.`ID`,`THIS`.`NAME`,`THIS`.`POSITION_ID` FROM `EMPLOYEE` `THIS` FOR UPDATE </code></pre> <p>If I run only the second part of the code (the Employee extent), then I see <em>only</em> the second query, without any access to the POSITION table at all. Why? Because DataNucleus initially provides "hollow" Position objects and the default implementation of Position.toString() inherited from Object doesn't access any internal fields. If I override the toString() method to return the position's title, and then run the second part of your sample code, then the calls to the database are:</p> <pre><code>SELECT 'com.example.staff.Employee' AS NUCLEUS_TYPE,`THIS`.`ID`,`THIS`.`NAME`,`THIS`.`POSITION_ID` FROM `EMPLOYEE` `THIS` FOR UPDATE SELECT `A0`.`TITLE` FROM `POSITION` `A0` WHERE `A0`.`ID` = &lt;2&gt; FOR UPDATE SELECT `A0`.`TITLE` FROM `POSITION` `A0` WHERE `A0`.`ID` = &lt;1&gt; FOR UPDATE </code></pre> <p>(and so on, one fetch per Position entity). As you can see, there are no joins being performed, and so I'm surprised to hear that your experience is different.</p> <p>Regarding your description of how you hope caching should work, that <em>is</em> how the level 2 cache ought to work when a class is pinned. In fact, I wouldn't even bother trying to pre-load Position objects into the cache at application start-up. Just let DN cache them cumulatively.</p> <p>It's true that you may have to accept some compromises if you adopt JDO...you'll have to relinquish the absolute control that you get with hand-rolled JDBC-based DAOs. But in this case at least you should be able to achieve what you want. It really is one of the archetypal use cases for the level 2 cache.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload