1<?xml version="1.0" encoding="UTF-8" standalone="no"?> 2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 6 <title>Retrieving Multiple Objects</title> 7 <link rel="stylesheet" href="gettingStarted.css" type="text/css" /> 8 <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /> 9 <link rel="start" href="index.html" title="Getting Started with Berkeley DB" /> 10 <link rel="up" href="persist_access.html" title="Chapter 5. Saving and Retrieving Objects" /> 11 <link rel="prev" href="simpleget.html" title="Retrieving Objects from an Entity Store" /> 12 <link rel="next" href="dpl_entityjoin.html" title="Join Cursors" /> 13 </head> 14 <body> 15 <div class="navheader"> 16 <table width="100%" summary="Navigation header"> 17 <tr> 18 <th colspan="3" align="center">Retrieving Multiple Objects</th> 19 </tr> 20 <tr> 21 <td width="20%" align="left"><a accesskey="p" href="simpleget.html">Prev</a> </td> 22 <th width="60%" align="center">Chapter 5. Saving and Retrieving Objects</th> 23 <td width="20%" align="right"> <a accesskey="n" href="dpl_entityjoin.html">Next</a></td> 24 </tr> 25 </table> 26 <hr /> 27 </div> 28 <div class="sect1" lang="en" xml:lang="en"> 29 <div class="titlepage"> 30 <div> 31 <div> 32 <h2 class="title" style="clear: both"><a id="getmultiple"></a>Retrieving Multiple Objects</h2> 33 </div> 34 </div> 35 </div> 36 <div class="toc"> 37 <dl> 38 <dt> 39 <span class="sect2"> 40 <a href="getmultiple.html#dpl_cursor_initialize">Cursor Initialization</a> 41 </span> 42 </dt> 43 <dt> 44 <span class="sect2"> 45 <a href="getmultiple.html#dpl_dups">Working with Duplicate Keys</a> 46 </span> 47 </dt> 48 <dt> 49 <span class="sect2"> 50 <a href="getmultiple.html#dpl_cursor_range">Key Ranges</a> 51 </span> 52 </dt> 53 </dl> 54 </div> 55 <p> 56 It is possible to iterate over every object referenced 57 by a specific index. You may want to do this if, for 58 example, you want to examine or modify every object 59 accessible by a specific primary index. 60 </p> 61 <p> 62 In addition, some indexes result in the retrieval of multiple 63 objects. For example, <code class="literal">MANY_TO_ONE</code> 64 secondary indexes can result in more than one object for any given 65 key (also known as <span class="emphasis"><em>duplicate keys</em></span>). 66 When this is the case, you must iterate 67 over the resulting set of objects in order to examine 68 each object in turn. 69 </p> 70 <p> 71 There are two ways to iterate over a collection of 72 objects as returned by an index. One is to use a 73 standard Java <code class="classname">Iterator</code>, which you 74 obtain using an <code class="classname">EntityCursor</code>, 75 which in turn you can obtain from a <code class="classname">PrimaryIndex</code>: 76 </p> 77 <pre class="programlisting">PrimaryIndex<String,SimpleEntityClass> pi = 78 store.getPrimaryIndex(String.class, SimpleEntityClass.class); 79EntityCursor<SimpleEntityClass> pi_cursor = pi.entities(); 80try { 81 Iterator<SimpleEntityClass> i = pi_cursor.iterator(); 82 while (i.hasNext()) { 83 // Do something here 84 } 85} finally { 86 // Always close the cursor 87 pi_cursor.close(); 88} </pre> 89 <p> 90 Alternatively, you can use a Java "foreach" statement 91 to iterate over object set: 92 </p> 93 <pre class="programlisting">PrimaryIndex<String,SimpleEntityClass> pi = 94 store.getPrimaryIndex(String.class, SimpleEntityClass.class); 95EntityCursor<SimpleEntityClass> pi_cursor = pi.entities(); 96try { 97 for (SimpleEntityClass seci : pi_cursor) { 98 // do something with each object "seci" 99 } 100// Always make sure the cursor is closed when we are done with it. 101} finally { 102 sec_cursor.close(); 103} </pre> 104 <div class="sect2" lang="en" xml:lang="en"> 105 <div class="titlepage"> 106 <div> 107 <div> 108 <h3 class="title"><a id="dpl_cursor_initialize"></a>Cursor Initialization</h3> 109 </div> 110 </div> 111 </div> 112 <p> 113 When a cursor is first opened, it is not 114 positioned to any value; that is, 115 it is not <span class="emphasis"><em>initialized</em></span>. 116 Most of the <code class="classname">EntityCursor</code> 117 methods that move a cursor will initialize it 118 to either the first or last object, depending 119 on whether the operation is moving the cursor 120 forward (all <code class="literal">next...</code> 121 methods) or backwards (all 122 <code class="literal">prev...</code>) methods. 123 </p> 124 <p> 125 You can also force a cursor, whether it is 126 initialized or not, to return the first object 127 by calling 128 <code class="methodname">EntityCursor.first()</code>. 129 Similarly, you can force a return of the last 130 object using 131 <code class="methodname">EntityCursor.last()</code>. 132 </p> 133 <p> 134 Operations that do not move the cursor (such as 135 <code class="methodname">EntityCursor.current()</code> 136 or <code class="methodname">EntityCursor.delete()</code> 137 will throw an 138 <code class="classname">IllegalStateException</code> 139 when used on an uninitialized cursor. 140 </p> 141 </div> 142 <div class="sect2" lang="en" xml:lang="en"> 143 <div class="titlepage"> 144 <div> 145 <div> 146 <h3 class="title"><a id="dpl_dups"></a>Working with Duplicate Keys</h3> 147 </div> 148 </div> 149 </div> 150 <p> 151 If you have duplicate secondary keys, you can return an 152 <code class="classname">EntityIndex</code> class object for them 153 using <code class="methodname">SecondaryIndex.subIndex()</code> 154 Then, use that object's 155 <code class="methodname">entities()</code> 156 method to obtain an <code class="classname">EntityCursor</code> 157 instance. 158 </p> 159 <p> 160 For example: 161 </p> 162 <pre class="programlisting">PrimaryIndex<String,SimpleEntityClass> pi = 163 store.getPrimaryIndex(String.class, SimpleEntityClass.class); 164 165SecondaryIndex<String,String,SimpleEntityClass> si = 166 store.getSecondaryIndex(pi, String.class, "sKey"); 167 168EntityCursor<SimpleEntityClass> sec_cursor = 169 si.subIndex("skeyone").entities(); 170 171try { 172for (SimpleEntityClass seci : sec_cursor) { 173 // do something with each object "seci" 174 } 175// Always make sure the cursor is closed when we are done with it. 176} finally { 177 sec_cursor.close(); } </pre> 178 <p> 179 Note that if you are working with duplicate keys, you can 180 control how cursor iteration works by using the following 181 <code class="classname">EntityCursor</code> methods: 182 </p> 183 <div class="itemizedlist"> 184 <ul type="disc"> 185 <li> 186 <p> 187 <code class="methodname">nextDup()</code> 188 </p> 189 <p> 190 Moves the cursor to the next object with the 191 same key as the cursor is currently 192 referencing. That is, this method returns the 193 next duplicate object. If no such object 194 exists, this method returns 195 <code class="literal">null</code>. 196 </p> 197 </li> 198 <li> 199 <p> 200 <code class="methodname">prevDup()</code> 201 </p> 202 <p> 203 Moves the cursor to the previous object with the 204 same key as the cursor is currently 205 referencing. That is, this method returns the 206 previous duplicate object in the cursor's set 207 of objects. If no such object exists, this method returns 208 <code class="literal">null</code>. 209 </p> 210 </li> 211 <li> 212 <p> 213 <code class="methodname">nextNoDup()</code> 214 </p> 215 <p> 216 Moves the cursor to the next object in the 217 cursor's set that has a key which is different 218 than the key that the cursor is currently 219 referencing. That is, this method skips all 220 duplicate objects and returns the 221 next non-duplicate object in the cursor's set 222 of objects. If no such object exists, this method returns 223 <code class="literal">null</code>. 224 </p> 225 </li> 226 <li> 227 <p> 228 <code class="methodname">prevNoDup()</code> 229 </p> 230 <p> 231 Moves the cursor to the previous object in the 232 cursor's set that has a key which is different 233 than the key that the cursor is currently 234 referencing. That is, this method skips all 235 duplicate objects and returns the 236 previous non-duplicate object in the cursor's set 237 of objects. If no such object exists, this method returns 238 <code class="literal">null</code>. 239 </p> 240 </li> 241 </ul> 242 </div> 243 <p> 244 For example: 245 </p> 246 <pre class="programlisting">PrimaryIndex<String,SimpleEntityClass> pi = 247 store.getPrimaryIndex(String.class, SimpleEntityClass.class); 248 249SecondaryIndex<String,String,SimpleEntityClass> si = 250 store.getSecondaryIndex(pi, String.class, "sKey"); 251 252EntityCursor<SimpleEntityClass> sec_cursor = 253 si.subIndex("skeyone").entities(); 254 255try { 256 SimpleEntityClass sec; 257 Iterator<SimpleEntityClass> i = sec_cursor.iterator(); 258 while (sec = i.nextNoDup() != null) { 259 // Do something here 260 } 261// Always make sure the cursor is closed when we are done with it. 262} finally { 263 sec_cursor.close(); } </pre> 264 </div> 265 <div class="sect2" lang="en" xml:lang="en"> 266 <div class="titlepage"> 267 <div> 268 <div> 269 <h3 class="title"><a id="dpl_cursor_range"></a>Key Ranges</h3> 270 </div> 271 </div> 272 </div> 273 <p> 274 You can restrict the scope of a cursor's movement 275 by specifying a <span class="emphasis"><em>range</em></span> when you 276 create the cursor. The cursor can then never be 277 positioned outside of the specified range. 278 </p> 279 <p> 280 When specifying a range, you indicate whether a 281 range bound is <span class="emphasis"><em>inclusive</em></span> or 282 <span class="emphasis"><em>exclusive</em></span> by providing a 283 boolean value for each range. 284 <code class="literal">true</code> indicates that the provided 285 bound is inclusive, while <code class="literal">false</code> 286 indicates that it is exclusive. 287 </p> 288 <p> 289 You provide this information when you call 290 <code class="classname">PrimaryIndex.entities()</code> 291 or 292 <code class="classname">SecondaryIndex.entities()</code>. 293 For example, suppose you had a class indexed by 294 numerical information. Suppose further that you 295 wanted to examine only those objects with indexed 296 values of 100 - 199. Then (assuming the numerical 297 information is the primary index), you can bound 298 your cursor as follows: 299 </p> 300 <pre class="programlisting"> 301EntityCursor<SomeEntityClass> cursor = 302 primaryIndex.entities(100, true, 200, false); 303 304try { 305 for (SomeEntityClass sec : cursor { 306 // Do something here to objects ranged from 100 to 199 307 } 308// Always make sure the cursor is closed when we are done with it. 309} finally { 310 cursor.close(); } </pre> 311 </div> 312 </div> 313 <div class="navfooter"> 314 <hr /> 315 <table width="100%" summary="Navigation footer"> 316 <tr> 317 <td width="40%" align="left"><a accesskey="p" href="simpleget.html">Prev</a> </td> 318 <td width="20%" align="center"> 319 <a accesskey="u" href="persist_access.html">Up</a> 320 </td> 321 <td width="40%" align="right"> <a accesskey="n" href="dpl_entityjoin.html">Next</a></td> 322 </tr> 323 <tr> 324 <td width="40%" align="left" valign="top">Retrieving Objects from an Entity Store </td> 325 <td width="20%" align="center"> 326 <a accesskey="h" href="index.html">Home</a> 327 </td> 328 <td width="40%" align="right" valign="top"> Join Cursors</td> 329 </tr> 330 </table> 331 </div> 332 </body> 333</html> 334