tag:blogger.com,1999:blog-291350082024-03-07T23:03:16.691+01:00Seaview, a Developers PerspectiveBjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.comBlogger46125tag:blogger.com,1999:blog-29135008.post-50788133085097177372015-10-27T22:23:00.001+01:002015-10-27T22:24:51.982+01:00What makes a conference talk a good talk?<h2>
What makes a conference talk a good talk?</h2>
<br />
Now; I've spent two days at <a href="http://conferences.oreilly.com/oscon/open-source-eu-2015">#oscon</a> in Europe. A commercial event, but mainly about stuff that concerns open source as you would expect. It has been a while since I have been to a conference, so i kind of feel a little bit rusty. I am in no sense of the word a seasoned conference attendee, even if I have had a few talks myself at <a href="http://2015.javazone.no/">#JavaZone</a> and some other minor events, participated in quite a few conferences both in Norway, US, and Europe. Short version; I always get excited by people that seems to know what they are talking about and as an added bonus excel in giving presentations.<br />
<br />
The funny thing is the delicate balance between being able to deliver a message that is persuasive, concise, composed by recognition points aligned with some fragments of prior knowledge. Being enthusiastic, charismatic, scientific and visible might trump the latter, but it is rarely the case that one or the other is exposed in singularity. I think, being able to convey the essence of something that is important to you is also about wanting you to learn more about the subject or the scientific field. This is the subtle relationships between immediate versus longer term perceived properties of a talk. A talk that might be entertaining at first might not be the one that you appreciated the most in retrospect. For that matter; to evaluate sessions as you go might not be a just way to give feedback when you evaluate sessions at a conference. Note to self, wait a day or two before evaluating talks. Humbleness, being able to refer to real-world cases and observations, good and bad will increase credibility. I think some people, including myself tend to like talks where I may say something like "He/She has experienced the same thing as myself!". Well, it does not bring much new stuff to the table does it?. That someone else feels like you does not make it a scientific fact. However, did you need recognition from someone else to state the same thing that you already knew? The bottom line should be, what is the origin of the problem that you have encountered? Is this solved? If not, what is the alternative?. It is equally important to know what is known, and what is not known. And if the ratio between known and unknown gets to high, it is caught in the sales-rep filter.<br />
I will take some of these note to self points into account when attending my next conference.Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com3tag:blogger.com,1999:blog-29135008.post-17999841241937932672009-08-04T22:58:00.001+02:002009-08-04T22:58:21.292+02:00Rigid definition of done considered harmfulMost people that has been doing iterative development in general and scrum in particular are probably familiar with the concept of discussing a definition of done. I have more than once been on projects where the concept of done has been defined in one form or another, and where project members have been trying to deliver running parts of a system that is compliant with such a definition. Even more I have witnessed scrum-masters proudly announcing that their definition of done is really done, done, done. The concept of done, done, done will of course be different from appliance to appliance, but it usually ends containing some of these:<br><ul><li>Code checked into SCM</li><li>Code passed QA</li><li>Tests running green in the Continuous build system</li><li>Running part of the code in a test system ready to be accessed by functional experts and product-owners</li><li>Possible discussed and assessed by product-owner before staged to the demonstration environment</li><li>Possibly accompanied by customer driven tests like <a title="fitnesse" href="http://fitnesse.org/" id="o_q1">fitnesse</a></li><li>Ready to be put into production</li></ul><br>My claim goes as follows; forcing your team members to adhere to a definition of done that is to rigid, and using that same definition as a criteria before moving it to the done category on the scrum board (complete in the current iteration), will cause your team to deliver less functionality than they could, and with properties that will make that functionality more difficult to change or even remove. I will try pinpoint why following such a rigid definition along with some indicators on going in the wrong direction.<br>Just to clarify one thing; for me, writing code with accompanying tests that are checked in and runs green in the CI system is all about the same thing. Make no mistake, I do it and I encourage my team-members, and everybody else for that matter, to do the same.<br><h3>Team-members are reluctant to pushing functionality out</h3>All those parts that need to be completed to get the "done, done, done" badge might not be necessary or even productive work to deliver the functionality ready for test. Maybe the criteria that says that all functional tests should be supported by a FIT test or some test specified in some BDD-flavor just isn't the way to go if the functionality doesn't lend itself to such a definition easily. Maybe only programmers are going write tests and specifications for that part of the system, in which case JUnit will probably be the best choice for a Java-based system. Not easily being able to comply with the done-criteria will probably cause some developers to go that extra mile to comply even if it is probably not worth the effort for that particular piece of functionality.<br><br>Consistency is will of course matter here. Using the same techniques for every bit and piece of the system will make it more consistent. But the strive for consistency will also manifest in supporting test-code or a greater number of test artifacts. These bi-products will have to be maintained and refactored together with everything else, and may actually make it more difficult to change the system later on. It takes experience to know when to put emphasis on consistency over throughput.<br><h3>Somebody is questioning why we need to work further on something that we have moved off the board</h3>Does this question sound familiar: "I thought you said that this task was done, done, done. We really doesn't have time to take this task back in again". I have heard it quite a few times and although it tends to be accepted, it still surprises me that this is not perceived as the rule, not the exception. If you get all the functionality right most of the time, my claim is that your lead-time to production is probably much longer than it should have been. If you develop build and deploy fast, like in hourly or daily increments, the likelihood of getting it right the first time is probably lower, but the basis for distilling the functional requirement is the running system itself, not some temporary artifact used just for aiding the specification process. Do as much of the specification work as possible in the production code. <br><br>The irony of all this is that it is the people evangelizing on how to eliminate waste that are most prone to push forward a framework to assist in the specification-process where that framework is not part of the code running in the production system. The observant reader may have understood that I am being intentionally vague here, and I have chosen not to prove my point with an example.<br><h3>It tends to propagate into rigid definitions of other areas of development<br></h3>The work to be put down to comply to a rigid definition of done to sign off on a user story or a task has the tendency to propagate into all areas in development. I think this is partially caused by the fact that you tend to move the some finalization-criteria out of the common-sense and ad-hoc part of decision making and into an (often) static set of rules. We need some statement on what the rules are, if not for anything else, at least to get some transparency related to the development process so that it may be explained to architects, management and other stakeholders and decision makers.<br>I believe that the urge to push rigid definitions of compliance rules forward is partially caused by the strive for consistency. The expectation is as follows; if you have rules that govern the development process, in the case the definition of done to move something off the scrum-board, then you will end up having delivering functionality in a consistent and predictable manner. That may be, but what if the functionality delivered is delivered slower than it could be and, and much more hardened in the source-code in terms of difficult to refactor tests and Fit tables.<br><br>The same goes for code-qa (pair programming is not always how code comes to light). Way too often this boils down to developers commenting on each-other code that may have been developed another way. Some times it identifies and prevents serious design-flaws, which is great. Developers produce at different levels of quality, use this input in the QA-process as well, it is nothing wrong with checking A's code with a great level of scrutiny while you may browse through B's commit-log in a split second. That's life, learn and educate instead, don't force the same compliance requirements on everyone.<br><h3>What to do and where to go?</h3>"There is no sense being exact about something if you don´t even know what you´re talking about." (John von Neumann).<br><br>It is very important that you observe and take notes of undesired effects of certain rules that your team is using to guide their day-to-day operation. This goes for code and architecture-centric rules as well as for rules that are meant to support the day to day process of harvesting requirements. When undesired effects show up, maybe it is time to remove or adjust the rule accordingly. Maybe this particular web-module wont need the Selenium-harness?, or maybe it does.<br><br>All in all it is about delivering functionality in the running system, supported by tests so that you may change code when new knowledge and requirement tells you to. A rumor says that Thomas Edison did not hire employees if the person on the interview salted his/her soup without tasting it. Use your ruleset the same way, don't always strive for consistency when applying your rules, it may lead to code manifesting in a way that makes it harder to implement your functionality fast and with less effort. <br><br>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com0tag:blogger.com,1999:blog-29135008.post-24785617417393882012009-07-31T23:00:00.001+02:002009-07-31T23:00:11.617+02:00Laptop retrospectiveInspired by ma latest post on <a title="different cell-phones I have had" href="http://devperspective.blogspot.com/2009/07/cellphone-retrospective.html" id="pthh">different cell-phones I have had</a>, I thought I would give it a second go, but now replace cellphones with laptops . I have been using laptops on a regular basis since the 80's because my father had a genuine interests for computers in combination with spreadsheets. I have decided to include these as well since it reflects my overall exposure to these kind of devices, even though they not reflect laptops I have owned, but merely laptops that I have used.<br><br><h3>IBM Portable 5155</h3><div id="iewm" style="text-align: left;"><img src="http://docs.google.com/File?id=dcs9tn98_78g9qbx2hk_b" width="424" height="186"></div><br><br>To call the first laptop a laptop would be to classify the infamous but very effective German <a title="Tiger tank" href="http://en.wikipedia.org/wiki/Tiger_II" id="fxiz">Tiger tank</a> of the WW2 light artillery. <a title="IBM Portable 5155" href="http://oldcomputers.net/ibm5155.html" id="bz8t">The IBM Portable 5155</a> was an awesome computer at the time and the model my father had was equipped with 256Kb of memory. I was at the time barely able to lift the computer; in its heavy-duty plastic case it weighed in at almost 15Kgs!! I had access to this computer from 1985-1987, it was my first experience with a computer apart from using the Commodore 64 at some friends, because I newer actually had one myself.<br><h3>Power Book 150</h3><div id="cnr5" style="text-align: left;"><img src="http://docs.google.com/File?id=dcs9tn98_79d76vk6gc_b" width="519" height="497"></div><br>The next time I got to use a portable computer on a regular basis after those that my father brought home from work in the late 80's wasn't before 1997 when I had a part time job for SINTEF. The (at the time outdated) laptop was given to me so that I could do some work while doing my military service as a conscript in the Royal Norwegian Airforce. I used the computer to write user manuals and documentation for a system I was working on at the time. I has no connectivity and was offline while doing the work. This was my first experience using a Mac, but I found it quite easy to master.<br><br>IBM Thinkpad 380<br><div id="uze3" style="text-align: left;"><img style="width: 266px; height: 275px;" src="http://docs.google.com/File?id=dcs9tn98_81d2s4s6fg_b"></div><br>I got this laptop while I was stationed as a conscript at Kjeller airfield just outside Oslo. I was lucky enough to part of a project programme that was part of a cooperation between Det Norske Veritas, Aerospatiale Missile and Royal Norwegian Airforce. I used it to program a reporting application in Visual Basic for Applications and MS Access. This was the first really nice laptop that I got to work with and the quality and robustness of the Thinkpad series has appealed to me ever since, even though I never got to own one myself. I also used it for a fair amount of gaming, especially Command and Conquer (one of the earlier versions I believe), excellent game BTW. I think that the keyboard on the Thinkpad models have been in a league of their own. <br><br><h3>Compaq (unknown)</h3>This was the first laptop that was handed to me for my personal use after I started my first full-time job as a consultant in Sybase, Copenhagen Denmark. The laptop was not new at the time that I got it, but had been used by a consultant that had stopped working there. It had an SVGA screen and a 150MHz CPU. Before started working there I had really been looking forward to the unpacking of my work-laptop, and all I got was this second hand Compaq. To all you guys hiring staff working as consultants. Please give them new equipment when they start working there. This way you will retain loyal staff for a much longer time. I guess however that unpacking a brand new laptop is not much of a big deal now as it was in the 90's. <br><br>I haven't been able to retrieve an image of this laptop, and I dond't have have a picture of myself using it so, sorry...<br><br><h3>Compaq Armada 7400</h3><div id="wd4v" style="text-align: left;"><img style="width: 400px; height: 445px;" src="http://docs.google.com/File?id=dcs9tn98_83gkk97whp_b"></div><br><br>Fortunately I got my hand on a much better laptop after complaining about my first laptop for almost a year. This time it was equipped with a 300Mhz cpu and a neater casing. I cannot completely recall but I think it was equipped with 128MB RAM. Decent laptop as far as I remeber, but nothing to be remember as special after I turned it in when I left the company that I was working for at the time, that must have been in 1999.<br><h3>Dell Latitude (unknown model)</h3>I got my first Dell as my home-office computer while working for Nokia. I did not really need one because I worked so many late hours there that I could not possibly have squeezed in some more office time after I got home from work. It was nothing special with this laptop. I actually didn't use it much as a laptop, it kind of had its home in the docking station at work. It was however good enough to persuade me to get a Dell as my next laptop. I don't remember the exact spec, but I seem to recall that my stationary computer at the time was a 600Mhz, 512Mb something, so I it was along those lines. I really cannot remember how it looked, it was stuck in the docking most of the time. For the same reason I was not able to find a picture.<br><h3>Dell Inspiron 8100</h3><div id="hk7g" style="text-align: left;"><img style="width: 380px; height: 327px;" src="http://docs.google.com/File?id=dcs9tn98_82ck9nwkhm_b"></div><br>Equipped with a 1,1GhZ processor, 30GB harddisk, 512MB memory, DVD, WIFI and a 15" 1600X1200 screen this laptop is the most expensive piece of equipment that I have ever bought. Bought in 2001, it was a true kick-ass laptop at the time, and I still have it although I don't use it. Staying at the top of the throne is costly, and you don't stay there for very long. I actually kept this laptop for a record-long period of 3,5 years, so it paid itself in the end. The lesson learned was however to use another long-time strategy; buy cheaper equipment and upgrade more often. This was the first laptop I bought after founding Zenior, also the place where I still work. I could choose whatever laptop I wanted, I guess that is one of the reasons it ended up to be a bit too expensive.<br><br><h3>Dell Inspiron 8600</h3><div id="oq6t" style="text-align: left;"><img style="width: 314px; height: 314px;" src="http://docs.google.com/File?id=dcs9tn98_85crkrvrd9_b"></div>I had been quite happy with my previous Dells so I wouldn't change a winning team. I actually believe that Dell being the only vendor having a decent site allowing for massive customization of the equipment was one of their reasons behind their success. The laptop had a Intel mobile 1,6GHz CPU, 1GB RAM and a 60GB Hdd running at 5400. The display 1600x1200 screen which was good. Apart from the CPU and double up of memory, 2Gb, , it's specifications wasn't that much different from the previous Dell, but the price was about one third. This was to be my last PC, possibly ever.<br><br><h3>MacBook Pro</h3><br><div id="tl5f" style="text-align: left;"><img src="http://docs.google.com/File?id=dcs9tn98_86drcfp2cn_b" width="285" height="178"></div>After using PC-based laptops (apart from the brief encounter with a PowerBook in 1997) for more than a decade, I finally decided to give in and get myself a MacBook Pro. I must say, apart for some annoying issues when running Mac-OSX I am very happy with the Mac. My Macbook has a 2,33 GHz CPU, 2Gb RAM and a 15" monitor. I have never regretted to not getting the 17" screen, it is simply too big. I believe that even my graphics-card is the same as in the 17" model so why bother. I got this laptop in 2007, and given my adopted two-year replacement strategy, I am now opting for a new MacBook Pro. I am planning on using that computer as a desktop replacement for my workstation as well. The MacBook is one of the more pleasing products I have ever bought, regardless of category. I am not an Apple-addict, I just find joy working with pleasant technology in an appealing wrapping; the MacBokk fits these attributes nicely.<br><br><br><br><br><br>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com0tag:blogger.com,1999:blog-29135008.post-82839622514947825352009-07-27T00:26:00.001+02:002009-07-27T16:47:10.364+02:00Cellphone retrospectiveA couple of days ago when I used my iPhone to post a Twitter kind-of status, I was contemplating on how many different cellphones I've had, some excellent, good, some mediocre and some just very bad. I must say after buying an iPhone and being on a couple of trips this summer, for the first time i didn't regret bringing my laptop. The maps application in combination with Safari on the iPhone did the job just fine. Cellphones has come a long way since I bought my first Ericsson phone back in 1995. Some of the phones have been lost on the way, others has been borrowed (and probably never returned) and given away. The first phone I bought I actually managed to sell for 50Dkr in 1999. I have attempted to rate the phones according to a relative rating-scheme; what did I think of the phone when I had it back in whenever. I actually still have quite a few of these phones in my possession still, but they are scattered in different boxes in the attic or maybe in different storage bins in my home office,....sigh. <br><br><h4>Ericsson GA 318</h4><br><div id="p.67" style="text-align: left;"><img style="width: 139px; height: 184px;" src="http://docs.google.com/File?id=dcs9tn98_66cjrj7ggz_b"></div><br>This is the cellphone I bought back in 1995 when i still went to university. The phone was nice, and leaner than most other models that was on the market at the time. The display a very simple black and white (no color lcds at the time i'm afraid) LCD that barely had enough real-estate for an international phone number. Netcom did not charge for SMS at the time, and they also provided a gateway that enabled you to send sms-messages directly to the cellphone using mail on the form: MSISDN@gw.netcom.no. I actually forwarded alarms from a production system to the phone using this gateway.<br><br>Verdict: 4.<br><h4>Nokia 6150</h4><div id="e.nw" style="text-align: left;"><img style="width: 139px; height: 184px;" src="http://docs.google.com/File?id=dcs9tn98_67c8b5ghmj_b"></div>I bought this phone when I worked as a consultant in Denmark back in 1998. My needs were really simple. I basically used this phone as a replacement for the fixed line that I terminated back then, and being a consultant, I had to be available. This is one of the most durable phones I have ever had, and I actually got this as a work-phone when I started working for Nokia Networks back in 1999. Later I have used that particular instance as a replacement phone for other phones that have ceased to work. However this was the first time I encountered the "it just shut itself of" syndrome that seems to have been haunting Nokia phones ever since.<br><br>Verdict: 4<br><h4><br />Nokia 7110</h4><br /><br /><div id="wur5" style="text-align: left;"><img style="width: 139px; height: 184px;" src="http://docs.google.com/File?id=dcs9tn98_695crjsvgn_b"></div><br />This was a truly amazing phone at the time. It was, I believe, the<br />first Nokia model to support WAP and T9. It also had this neat little<br />keyboard-cover that you could release by pressing a small button on the<br />side of the phone. It made this "wsssh-click" that was very easy<br />to recognize. This phone was actually engineered and developed at the<br />research-facility in Copenhagen where I worked at the time. The early<br />prototypes had some flaws and one of them that I remember particularly<br />well was the problem with the ejecting spring for the cover being too<br />strong so that the cover would actually separate from the phone and be<br />ejected several meters. I more than once had to pick such a cover out<br />from my lunch (not my cover) being ejected from one of my coworkers<br />trying to enjoy their lunch while receiving a call, and sitting at my right side.<br><br /><br><br />Verdict:5<br><br><h4>Nokia 3310</h4> <div id="p259" style="text-align: left;"><img style="width: 139px; height: 184px;" src="http://docs.google.com/File?id=dcs9tn98_68cwrvfhcg_b"></div>I got this phone as a prototype back in 1999, 4 months before it went into full production. At the <a title="Nokia facilities at Fredrikskaj" href="http://plazes.com/plazes/126026_nokia_office_fre" id="uj:0">Nokia facilities at Fredrikskaj</a> they handed out this model to all employees. It was nothing special with this model, and it was ugly. It had, however, a sms-chat function that was pretty neat that I haven't seen on any phone models since this one. This phone was one of the first ones with widely available snap-on covers, i had only one cover, grey.....<br><br>Verdict:3<br><h4>Nokia 6210</h4><div id="zinp" style="text-align: left;"><img style="width: 75px; height: 100px;" src="http://docs.google.com/File?id=dcs9tn98_70cspm84dj_b"></div><br>I got this phone as a replacement after my 7110 was lost on a business-trip to Finland. The phone had many of the same features as in the 7110 but had a much better mechanical design and no antennas pointing out. The screen was nice and it had a small lean design so that it would easily fit in to any pocket. It also turned out to be one of the more robust models I have had.<br><br>Verdict:4<br><h4>Nokia 9110i</h4><div id="o7yy" style="text-align: left;"><img style="width: 139px; height: 184px;" src="http://docs.google.com/File?id=dcs9tn98_71f9r9fdd2_b"></div>Wow, I felt like a kid the first time a got my hands on one of these. I first got it in 2000 and given the functionality it had at the time still amazes me. It is one of the reasons I loved (and still do) Nokia as a company, being truly innovative. When the first Communicator was launched, virtually nobody knew, before the lightning came out of the sky. This was one of the predecessors, only with even more features. I had work-mail using a VPN connection, and I more than once used the built-in telnet terminal to log into test and development-servers to launch new builds, check build-status and so on. The excellent QWERTY keyboard was one of the reasons I really had a hard time to switch back to more regular type phone models.<br>The only problem with this phone was its limited durability. I had to send it away on repair twice before it finally gave in in 2002. The backbone was an AMD 486, I had a Cyrix 486 as a refrigerator magnet several years erlier :-)<br><br>Despite it's mechanical weaknesses I have to give this phone a verdict:6<br><br>In the period after the decease of the legendary 9110i but before the 2003 i used my old 6150 and 6210 before finally giving in ans buying my first Sony Ericsson phone with MMS.<br><h4>Sony Ericsson T610</h4><div id="xek1" style="text-align: left;"><img style="width: 75px; height: 100px;" src="http://docs.google.com/File?id=dcs9tn98_72cfx3q4dh_b"></div><br>I just wanted one of these phones to try something else than Nokia. It also was to my knowledge one of the first Sony Ericsson mobiles to come around apart from the legendary T68i and of course the P800. The phone was my first MMS-phone. A lot of service providers campaigned this as part of their MMS launch. The phone was OK, nothing more. Its dimensions in combination with a lousy keyboard made it very difficult to write sms-messages using only one hand, the bottom part of the keyboard was simply to close to the edge.<br><br>In fall of 2004, a scratching disturbing background noise made it difficult for the people I was talking to too hear what I was saying. That made an end to a not very exiting relationship.<br><br>Verdict:3,5<br><h4>Nokia 9210i</h4><div id="hxqy" style="text-align: left;"><img style="width: 75px; height: 100px;" src="http://docs.google.com/File?id=dcs9tn98_73gm4gj4cw_b"></div>My brief encounter with what we referred to as "those other guys" when I worked for Nokia up to February 2001, the Ericsson part of Sony Ericsson, made me want to go back to Nokia. During the last couple of years I hadn't been able to get the Communicator out of my head. I will admit to possibly being a bit nostalgic, but it was no other way, I had to get back to the life I had with the Communicator. So I went down up to Telekiosken at Storo and got myself a 9210i. The form factor of this phone was better than the previous Communicator models, and the foldable antenna was all gone which was about time. The mechanical flaws from the previous models had vanished and it now had a color TFT which today I still remember as one of the best cellphone-displays ever. Even in broad daylight the screen was completely unaffected, as pristine as a piece of paper. Some of the magic feeling I had from the first model was gone, that together with a battery with limited quality made the re-encounter shorter than I hoped for. After the phone shutting down when I was about to agree on a rendezvous point with my off-piste friends in Hemsedal, for doing some serious downhill just before I was able to communicate my location, aided me lin shutting it down. I decided to get a more robust and less amp-hungry friend.<br><br>Verdict:4,5<br><h4>Sony Ericsson W950i</h4><div id="pi65" style="text-align: left;"><img style="width: 139px; height: 184px;" src="http://docs.google.com/File?id=dcs9tn98_74dbrgvdc2_b"></div><br><br>A good friend of mine (and co-worker) that was much more knowledgeable about cellphones than I was, became all worked up about this new model. It had a decent size, heaps of functionality and a touch screen that was usable together with the pen that accompanied the phone. No fuzz, I got one immediately. This became my first mp3 player as well I am embarrassed to say. The phone was decent and even had a radio which I have missed on most of the other models I have had (and still miss). But it did not take long before I re-discovered the flaw that I had seen on other Sony Ericsson phones as well, a keypad that relly sucks. The keyboard is one of those plastic ones where a thick film of plastic covers a keypad with mechanical devices sensing keypresses underneath. The problem with this model was that they had messed up the placement of those sensors completely so that you actually had to press slightly above the marked digit to get the desired result. I wonder what kind of substance the engineers designing such a piece of ***** had been consuming before they hardened the design....<br><br>Verdict:3<br><h4>Nokia 6500 Classic</h4><div id="h3tt" style="text-align: left;"><img style="width: 75px; height: 100px;" src="http://docs.google.com/File?id=dcs9tn98_75hbk3zdf8_b"></div><br>After been doing my fair share of smartphone-hype, carrying around power hungry and feature-bulky phone for almost a decade, I wanted to go for a small, feature stripped phone with an appealing and urban design (!!?). I went for this simple and not very expensive model from Nokia. It had Java as well so together with the small but very nice screen it made a good company for the J2ME version of GMail. All in all I was quite happy with this phone that I got in the summer of 2007.<br><br>Verdict:5<br><h4>iPhone 3G</h4><div id="dp_g" style="text-align: left;"><img style="width: 139px; height: 184px;" src="http://docs.google.com/File?id=dcs9tn98_76sc88fqfr_b"></div><br>I finally gave in in in 28'th of march 2009, my wife convinced me to finally get myself an iPhone. I gave in because I was very pleased with my acquisition of an iPod touch a couple of weeks earlier. After the 3.0 upgrade which arrived fashionably late in my opinion i think this is probably the best device with a cellphone I have ever had. Even though it does not matter it kind of pisses me of that it does not run Java.<br><br>Verdict:6<br><br><br><br> <br><br><br><br><br><br>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com11tag:blogger.com,1999:blog-29135008.post-21137781665833148222009-07-24T22:34:00.001+02:002009-07-24T22:47:43.793+02:005 things I wish for in the near and not so near futureIn no particular order or priority.<br><br>I am currently on vacation, spending time with family and friends, and approaching things a little bit differently. By doing something else than going to work and not going about the normal routine (which I really enjoy, don´t get me wrong), you get new ideas on how to approach things, which is great. The small deviation in how to approach a problem can get you into new areas of unexplored ground. Here another day, inspired by <a title="Thinkertoys" href="http://www.creativethinkingwith.com/Thinkertoys.html" id="n9-u">Thinkertoys</a>, I took another way to work. I drove passed a building I had never seen before with a name on it. I started thinking and it gave me an idea of a company name dealing with a business idea I have been puzzling with for a while. Small change may yield inspiring side-effects.<br><br>Speaking of business idea, I thought I would like to share the tings that I would like to have, of which some exists, but most don't. Some of the products or solutions are things I want and will probably get in the near future, some are products where the technology is and may never become available. Some of the things may address a small and not very important part of everday life, others may affect the way we live. Some of these things that I suggest may already exist, then excuse me for my incompetence and inadequate investigation of prior art. To avoid stepping on to many toes, I have chosen not to go into areas that may offend groups of people committing to a specific religion or political direction, maybe with the exception of public transportation :-) <br><br><h3>Wireless everything</h3>Everytime I want to install a new piece of equipment in my house, the thing that caused me the most headache is wiring. Coax for television, cat 5e for networking (no, Gigabit WiFi is not available outside laboratories, at least not to my knowledge), wiring for speakers, and of course, the infamous houshold power. And for crying out loud, when are we going to standardize on power transformers for DC devices, and I am not just talking of cellphones here (where they, believe it or not have agreed on a common standard). I think i have at least 50 different transformers in the house, where at least 15 of them are in use regularly, most of them ranging between 5 and 12 volts and 0.1 to 1.2 amps. None of them has a common physical interface. All these transformers make parts of my office space into a mess. By not being constrained by cabling, you can probably mount heating devices, lighting, stereo systems and everything else so that it will be more energy efficient, but also more pleasing from an aesthetic point of view. Giving what I save on my electrical bill I may no spend on buying more television sets, because I may now mount them on the wall without anything else, right? But then, what about the set-top box...well I don't think that there is enough storage space available in the world to actually store a persistent version of that topic, so that will have to wait for later.<br> <br><h3>Choose my own hardware when working at client site</h3>Why is it that all businesses standardize on a workstation platform that is supposed to accommodate occasional needs for creating office documents and e-mail running on MS-Windows, often bundled with a 19"-inch monitor, insufficient amounts of RAM and a CPU that was at best mediocre two years ago. This is about as far as you can get from the specification of a decent development platform. In addition to that you usually have to go through the regular process of getting administrative rights, and to disable virus-control. You security people don't really get it, do you. Believe it or not, developers may need privileges to actually install applications on their workstation other than those approved and already installed by support. Why not trying to save some money, and let contractors and consultants use their own equipment instead, most possibly a laptop that they probably have already, but maybe also an external display as well. If networking is properly configured this should not be a problem neither from a maintenance nor a security perspective. And in order to avoid any potential envy or conflict, please provide your employees with the best possible equipment.<br><br>As for software, I am usually allowed to work with whatever tools that I want to as long as I don't expect my clients to provide them. My primary concern is hardware. <br><h3>An Amazon Kindle or other e-book device</h3><br>I am a regular Amazon customer, I buy mostly science and programming books, but recently I have also been buying my fair share of books on parenting, productivity, entrepreneurship and creative thinking. Books take up physical space and is heavy to carry around. More than once have I needed a book that I have bought without having it where and when I need it. I gudd this is partially caused by the ambulant nature of my work. With a decent e-book device I could possibly bring as many titled that I want in a package about the size of a regular book. Most titles would always be in stock and I would never-ever again be concerned again that the delivery service would deliver the package while I was away. I really need one of these things. The only little hitch about this device that made me quite worried may be found in <a title="this" href="http://www.publishersweekly.com/article/CA6671793.html" id="r..f">this</a> article. Words are not sufficient to describe the irony and hopelessness of such an act.<br><h3>Seamless and effortless public transportation</h3><br>If you do not live in Oslo or another provincial Nordic town, parts of this section may not apply to you. I have been using my car for work for years to go now. It is very convenient and has made it possible to cut down transportation-time to around 15 minutes each way. In addition to that, getting groceries or other things on the way home is the easiest of things. After getting my first child some time ago, me and my wife now share the car more and more, so I use the subway for work maybe twice a week. With good timing and no delays, I am able to get to work in around 45 minutes each way. This is from what I hear pretty decent, but still almost the triple of what I use today. I just don't have an extra hour a day to waste. I guess that without having to do a transfer, I could be down to around 20 minutes which is comparable to what I use in a car. Taking transfers out of the equation as long as both home and work is nearby a station for public transportation, or making transfers transparent will make this a competitive alternative for a much larger group of potential commuters.<br><br>The kind of system I had in mind consists of a network of autonomous small cubicles that may accommodate up to four passengers each. The backbone of the infrastructure is s grid of rails that may transfer a large set of these cubicles at high speeds and to their programmed destination. The grid may be powered by small electric motors or, preferably by magnetic leviation. A google search on "fremtidsrettet kollektivtransport" gave me 101 hits. When I get this few number of hits it is usually because I have mis-spelled something or that it doesn't exist. When it takes +7 years to get a <a title="non-working ticketing system for Ruter" href="http://arkiv.na24.no/Tema/Flexus.html" id="wmn_">non-working ticketing system for Ruter</a> to go into production, i don't see this alternative being available anytime soon.<br><br><h3>Being able to attribute the electrical consumption down to individual devices</h3>In Norway, we are fortunate enough to cover most of our electrical needs from hydropower. From an emission perspective this is probably the cleanest, currently available source of energy that exists, but it cannot be exploited without significant consequences for the wildlife and environment that surrounds the power plant and any dams possibly built to provide for sufficient flow of water. The electrical consumption in Norwegian households have been increasing significantly and will continue to do so for the years to come. During periods with limited water supply, we are dependent upon supply from Denmark, that are more than willing to crank up their old coal-based power plants in Jutland to provide frozen Norwegians with stand-by power for their brand new LED tv's. Don't get me wrong, I am not a saint, I use my fair share of stand-by power. My point here is that most of our daily activities are assisted by some kind of device powered by electricity, and the electrical bill being a major part of the household budget, it is just fair that we should be able to have some more transparency utilization down to individual devices.<br><br>The power meter in my house has no means of even exposing the aggregated consumption of the household, it is one of those arcane, antiquated devices with a rotating disk. I guess that the likelihood of getting one of these equipped with some kind of interface that would enable me to offload some data is close to nothing. If I had one of the more recent meters I could do something like <a title="this" href="http://ondskap.net/stroem/" id="jrwt">this</a> but I don't and it will not provide me with all the information that I need.<br><br>If being able to attribute the power consumption down to individual devices, it would be much easier to convince people how to actually be more conscious on how they use their household devices and implicitly giving them the ability to understand how to reduce or improve their use. I think that getting this level of transparency is the key to get people to really understand how to spend the household-budget in a more environment friendly way. So are there any takers for developing this kind of infrastructure? I guess that the only thing it will take is for each device that consumes power to emit a signal containing an identifier of the device for every miliamp consumed. <br><br>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com2tag:blogger.com,1999:blog-29135008.post-63403431892933877932008-09-18T12:11:00.000+02:002009-02-16T08:36:46.811+01:00 <BR><H2>Continuously translating requirements into code in production fulfilling user expectations<BR></H2><BR>This is a long phrase, but that is the term that I use when I refer to what I am doing as a developer through consultancy. Being a Senior Consultant, my workday consists of much more than just writing code. Although I like to refer to myself as a programmer, just coding won't do it. It is all about coding the right stuff. Avoid coding to much of the wrong stuff, and get the code into production as fast as possible. This is my mission, that is what i want to be good at.<BR><BR>Mary Poppendieck is <A id="kexy" href="http://javazone.no/incogito/session/The+Double+Paradox+of+Lean+Software+Development.html" title="talking about waste">talking about waste</A>. Waste is pretty much anything that you do in your production line (aka project :-) that does not provide value for customers either directly or indirectly. I just came from a talk where she was talking about how to maximize throughout and how to reduce utilization. It is funny how many metrics not directly related to providing value for customers we have been measured against. It has been a long time since I have have been measured against how many lines of code I produce. Now we are measured using <A id="hv8g" href="http://en.wikipedia.org/wiki/Story_points" title="Story Points">Story Points</A>. This is better but in most cases, far from measuring the right thing. <BR>The right thing is value for end-users delivered in production, this is what we should measure, or, we should at least know when we provide it :-)<BR><BR><BR><BR>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com1tag:blogger.com,1999:blog-29135008.post-85548614758681525902008-09-17T14:25:00.000+02:002010-02-23T17:11:21.796+01:00 <BR><H2>Nordås on domain-driven design<BR></H2><P>I must say, very nice introduction on Andres Nordås' talk on <A id="f3zq" href="http://javazone.no/incogito/session/Better+Domain+Driven+Design.html" title="Doing Domain driven design better">Doing Domain driven design better</A> at JavaZone. He has really raised the bar with respect to getting someones attention to start with. Unfortunately It was no space left in Lab III for me and my co-worker. But now we are chilling out in the Overflow area, with really good audio and video so this is really great. Star Wars, get outa heeee....good work Anders.</P><P><BR>Being able to provide infinite flexibility in the borderline between your domain and your infrastructure and to be more specific, repositories. When you want infinite flexibility, you also need to be sure that your coupling is loose so that you may adjust implementation strategies without afecting your domain, e.g what an order looks like or what it means to place an order. <BR>Being able to refer to a repository in form of a generic repository interface is a very nice thing. It is even better that use you generically typed interface without knowing if it is an in-memory repository, or a Hibernate reposiory. Dealing with persistent lifecycle is in concept trivial, you store/delete and retrieve objects by query or by id. This is how all interaction with repositories should be stated.<BR><BR>Anders presens several examples that shows how easy it is to achieve loose coupling using generic types a container and pluggable strategies. You should really take a look to see how our code may be improved. Eirik Maus and myself will touch briefly into the same topics in our talk on Dealing with one to too many relations in Hibernate. I beleive that if you are able to correctly model your repositories as Anders does, all the other bits and pieces will fall into place.<BR><BR></P><br>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com1tag:blogger.com,1999:blog-29135008.post-38685027709738006882008-09-17T13:03:00.000+02:002010-02-23T17:11:21.831+01:00<H2> Talk about dynamic languages using Glassfish.<BR></H2><BR>Just came from a talk of using <A id="xax2" href="http://javazone.no/incogito/session/Dynamic+languages+and+frameworks+in+an+enterprise+application+server+world+-+an+approach+with+GlassFish+v3.html" title="dynamic languages in Glassfish">dynamic languages in Glassfish</A>. I would actually have expected some more in-depth information about practical appliances of dynamic languages, but the examples was pretty basic. I am really fond of the idea being able to pick the language of choice when confronted with a problem. If you are encountering a problem that would call for a functional language, pick Scala. If you want to leverage your existing investments in Rails-development, pick Ruby or Jruby. I don't thing that the strength of actually being able to do this cross-language is something that we are going to see much of. However, being able to use a hug range of languages in the same runtime is a very good thing. <BR><BR>Bringing web into all this is a problem. The package and deploy-step is a mess, and one of the reasons why I am looking into actually moving away from java for web. War-files is a mess, deployment is a mess and app-servers and standards (and deviations of them) is a mess. Why cant we just get some mod_java stuff for Apache and just use apt-get to install it so we can get faster into production. This is where I want to go.<BR><BR><BR>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com0tag:blogger.com,1999:blog-29135008.post-77652036315069113492008-09-17T10:28:00.000+02:002010-02-23T17:11:21.834+01:00<H2> Javazone 2008.<BR></H2><BR>It is finally time for doing JavaZone 2008 which I have been looking forward to quite some time. This year, I will try to go to as many hardcore presentations as possible. The reasons for that are pretty simple. Usually when I read articles and watch conference videos online, it is usually late in the evening after a long days work. My ability to dig into hardcore stuff is limited. Whereas, when I attend conferences, which I really enjoy, it something I can do fully rested, therefore I want to dive into technical stuff, closely related to what I do the most, programming.<BR><BR>The program this year looks OK, a good mix of technical and non-technical sessions. I think you will find something to your taste. What kind of sessions to you prefer yourself?.<BR><BR>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com0tag:blogger.com,1999:blog-29135008.post-3185509585647334072008-08-29T23:12:00.000+02:002010-02-23T17:11:21.838+01:00 <h1 id="d:bl">Testing code or testing requirements?</h1>I have been in several projects where multiple attempts to classify tests into different categories has been attempted. Unit-tests, Web-tests, Behaviour-tests, Fitnesse-tests, Requirement-tests, Integration-tests, all of them written in Java in some ways or another. As you will see, the typical categories refers to different properties of a test. In some cases related to which layers of the code it touches. A typical unit test typically tests the contract of a given class, but will often test intentionally or unintentionally also test adjacent classes unless the rule is strictly enforced. A typical Web test could possibly be Selenium test that verifies various steps of a wizard with or without the back-end systems or databases to drive the data in place. <br id="iiio">Some definitions of tests refers to the layer of code it refers to and how many interconnected classes they may include such as a unit-test or an integration test. Others may be more technology specific like Fitnesse-tests or Seleniums test that refers to the technology being used when implementing the test. <br id="c_-q"><br id="c_-q0">I believe that the core property of any test should be to capture and verify the expectation you have related to how the class, module, layer or application should work. That is in most cases why you actually write a test to start with. This is a very code-centric endpoint of the spectrum of continuously transforming user expectations and needs into a running system that provides value. Actually verifying the user-requirements and expectations is in the other end of this spectrum. There are other (possibly subordinate) properties of the process of writing tests also. If you use the same language for both tests and running code or supportive libraries, you will also verify if a class, interface or module is easy to use, and as part of the process you may actually improve it while writing the test. That makes that process of writing the test itself into something that validates more subtle and less quantifiable properties of the code. If doing TDD, writing a test is a starting point for writing code.<br id="n9um"><br id="n9um0">There are some bits and pieces missing in this picture. Very often I read about or hear about developers doing various kinds of testing in their project while applying some kind of label to what they are doing. The label may vary but terms like Requirement driven tests are becoming more and more widespread. I believe that this is good, because verification of requirements is probably the most difficult and important thing we are dealing with as system developers. But I have also seen this urge to classify everything as requirement test lead us in the wrong direction. Requirements means different things depending on who you are talking to.<br id="s1db"><br id="ae2n">I will try to address that using a brief description taken from a User Story document in one of my previous engagements:<br id="ae2n0"><br id="ae2n1"><div id="kci:" style="margin-left: 40px;"><i id="kci:0">"It should be possible to search for customers by first-name, last-name and birth-date. If multiple customers are returned a list of customers with the current address of residence should be presented along with the result"<br id="kci:1"></i></div><br id="kci:3">We can discuss if this is a good definition of a requirement or not. This is not the point here. The point is, it captures a fragment of a user-expectation, a <i id="or4i">requirement</i>. We may think of multiple tests in many of the categories above. But when does a written test really capture a requirement? I will say that depends, because requirement means different things depending on who you talk to. For me, as a coder, currently developing a jsp-based solution, one requirement applicable to the actual code I am writing may be that the web-controller returns the customer from a search as an array-type rather than a Collection based type (even though we have generics) simply because there is no way to refer to such a type using the useBean directive in JSP 2.0. This will therefore be a non-functional requirement in my code. It does not mean that I will be writing a test for that requirement in particular, but the unit test of my controller will most definitely be aware of this property. <br id="q7pz">The part of the code I am writing may also need a utility that merges two arrays into one. The SDK does not provide a utility that does that for us, but if a create one myself, i will most certainly update ArrayUtilsTest to provide a test for the new merge method in ArayUtills. It this a test of a requirement? most definitely, if verifies my expectation. Is it a requirement of the application itself that the system provides such a function? not necessarily, the primary property of the system is to provide customer search by the means necessary as defined by lead-developers and programmers on the project.<br id="kci:5"> <div id="kci:6"><br id="hwe-">The primary conclusion put forward is that tests addresses the expectation of a whole spectrum of what we refer to as requirements. Quite a few of these requirements manifested as code in tests may not be easily translated into functional requirements owned and understood by the customers. Trying to be dogmatic about what kind of tests we write and to say that every line of code should be directly translated into a customer requirements may turn out to be a side-track. Very often when writing tests, the limitations of the test-framework and intrinsic properties of the interfaces or libraries you are using will force you to simplify and limit the number of assertions you apply to you test harness. It is important to understand that the requirement coverage provided by such tools will never be perfect. Strict tests will almost always end up being to brittle. <br id="yf:b"><br id="yf:b0">Getting your automated builds running the right set of tests is difficult. In my experience it ends up with a mix of unit tests, integration tests, web-tests and some flavor of requirement tests like fitnesse. These tests will test customer requirements and quite a bit of other properties. These tests tends to be something owned and maintained by developers more than by domain experts and customers, those that actually understand the problem domain.<br id="p:1i"><br id="p:1i0">What are your experiences?<br id="yf:b1"></div><br>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com2tag:blogger.com,1999:blog-29135008.post-4412202982156086072008-01-05T18:13:00.000+01:002008-05-01T19:38:46.209+02:00 <h2>Using Macintosh keyboard in Ubuntu</h2>I use various computers during a normal working day. I use a Macbook-pro as my laptop, a windows workstation running XP at the client-site where I am currently contracting, and at home I use (probably my favorite computer) an AMD workstation running Ubuntu Gutsy. Since I am primarily a Java developer, I use IntelliJ as my primary workspace, which is of course available on all platforms, the same goes with firefox and quite a few of the other applications I work with as well. One thing that has been annoying me lately, though is that I have not been able to find a really nice keyboard. The key bindings for shortcut keys in some of my favorite applications also varies slightly when using the different platforms. One thing i do know is that it is quite unlikely that I will change the keyboard on my Macbook, which i quite good anyway. I like way the keys both sounds and works.<br><br>Some years ago I used to really enjoy typing with those old IBM-style PC-keyboards when using OS/2 workstations at the university. They had really hard keys and made this really load "click" sound. Awfully noisy of course, but I really liked both the way they sounded and behaved. These are anyway not possible to get a hold of anymore. <br><br>I really like the looks of the new mac 105-keys keyboards in aluminum, so I got one ow those. The cool ting about this is that it will be much easier for me to switch between the macbook and my buntu workstation. I had a little trouble making the keyboard working as it is supposed to, but after some tweaking, I got it working.<br><br><h3>What I had to do</h3>Selecting the correct keyboard layout in Ubuntu is really simple. Just open the "Keyboard" application and you are all set to go. Select the appropriate keyboard layout, which in my case a PC-keyboard with the Norway Macintosh as the variant as shown in the figure.<br><div id="imto" style="padding: 1em 0pt; text-align: left;"><img style="width: 450px; height: 430px;" src="http://docs.google.com/File?id=dcs9tn98_42fcw2pjgt"></div>The next thing you will have to do is enabling the Command-key as a third level chooser (this is usually the windows key on a regular PC-keyboard). Just set it like this:<br><br><div id="d3d3" style="padding: 1em 0pt; text-align: left;"><img style="width: 495px; height: 572px;" src="http://docs.google.com/File?id=dcs9tn98_43gtzfnzc6"></div><br>Now I thought I was almost set to go, having the ()[]{} thing working for me, which is pretty damned important since I am a programmer, and I use these braces all the time. The only thing I discovered was that the keycode=49 was not mapped according to my keyboard. According to my layout it was supposed to be apostrophe bu it was bar. This does not correspond with my current layout, fortunately there are simple ways around this. I didn't know that the keykode was 49 for this key, so then I used <font face="Arial">"xev" to find it. <br>After finding the correct keykode, I just launched:<br><br><span style="font-family: Courier New;"><span style="font-family: Courier New;"> sudo xmodmap -e "keycode 49=apostrophe bar"</span><br><br>to change the mapping to get the apostrophe in the right place. Now I am all set to go. I am probably going to buy myself one of these keyboards for the windows-workstation I am using at the client-site as well. <br style="font-family: Courier New;"></span><br><br></font><br> Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com1tag:blogger.com,1999:blog-29135008.post-33226677567506445892007-09-13T17:20:00.000+02:002010-02-23T17:11:21.844+01:00 <h1>My tracks for the second day</h1><br>It is only two sessions left for day one at JavaZone and I have to make planning arrangements for day III lready. Hopefully, I will also be able to update my first blog entry with comments on my previous encounters at JavaZone 2007 as well.<br><br>Ok, we have a lot of nice sessions tomorrow as well, actually we are doing BOFS' until 21PM on Thursday, not bad!!<br>This is my schedule for September 13.<br><br><div><table id="xfa." border="0" cellpadding="3" cellspacing="0" width="100%"><tbody><tr><td width="33%"><b><i>Time<br></i></b></td><td width="33%"><b><i>Talk <br></i></b></td><td width="33%"><b><i>Comment <br></i></b></td></tr><tr><td width="33%">9.00-10:00<br></td><td width="33%"><a href="http://www4.java.no/web/show.do?page=92&articleid=5425"> Java Persistence 2.0 - What's New</a>, Linda DeMichiel</td><td width="33%"><br></td></tr><tr><td width="33%">10:15-11.15<br></td><td width="33%"><a href="http://www4.java.no/web/show.do?page=92&articleid=5251"> Open source Enterprise Integration with Mule</a>, <a href="http://www4.java.no/web/show.do?page=65&articleid=5252">Tijs Rademakers</a> og <a href="http://www4.java.no/web/show.do?page=65&articleid=5253">Jos Dirksen</a></td><td width="33%"><br></td></tr><tr><td width="33%">11:45-12:45<br></td><td width="33%"><a href="http://www4.java.no/web/show.do?page=92&articleid=5265"> Deploying Maven in the Enterprise</a>, Kristoffer Moum</td><td width="33%"><br></td></tr><tr><td width="33%">13:00-14:00<br></td><td width="33%">None<br></td><td width="33%"><br></td></tr><tr><td width="33%">14:15-15:15<br></td><td width="33%"><a title="How Do I Invoke a Method, and Yes I Am A Senior Developer, Ole Andre Ranvik, Bjørn Bjerkeli" href="http://www4.java.no/web/show.do?page=92&articleid=5473" id="hax7">How Do I Invoke a Method, and Yes I Am A Senior Developer, Ole Andre Ranvik, Bjørn Bjerkeli</a> </td><td width="33%">This is my own talk actually, I really recommend it, puts some things in perspective (I might be biased here :-)<br></td></tr><tr><td width="33%">15:45-16:45<br></td><td width="33%">Teaching computers How to Drive, Mary Poppendieck<br></td><td width="33%">Mind blowing<br></td></tr><tr><td width="33%">17:00-18:00<br></td><td width="33%">WS Duck Typing, Arjen Poutsma<br></td><td width="33%"><br></td></tr><tr><td width="33%"><br></td><td width="33%"><br></td><td width="33%"><br></td></tr><tr><td width="33%"><br></td><td width="33%"><br></td><td width="33%"><br></td></tr></tbody></table></div><br><br> Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com0tag:blogger.com,1999:blog-29135008.post-39675622235994532712007-09-12T15:18:00.000+02:002007-10-19T14:29:30.314+02:00<h2>Jim Coplien talking about "Agile Stuff"</h2><br>The Agile track is covered pretty well at JavaZone 2007, we have a lot of good speakers doing agile-talks. This is very much thanks to Jessica Hildrum that seems to be very well connected. Jim has been looking into agile issues for the past 12 years and works for a Danish company called Nordija.<br>Most of the projects that I have been working on lately has been organized in an Agile matter, Jim goes into the some details on explaining some common myths on agile processes and what works and whatnot. The five Myths discussed are:<br><br><ul><li>On-Site customer</li><li>User Stories</li><li>TDD</li><li>YAGNI</li><li>DLS's</li></ul><br>Before Jim starts to talk out, I will poin out the ones that I wold tend to focus on, from a developers perspective will be YAGNI and TDD. Jim tells us that it doesn't work, he's go me curious.<br>Jim clains that TDD will destroy your system, which is a pretty bald claim, nonetheless interesting. He claims that you will end-up building an unmaintainable and procedural architecture, which does not lend itself to refactoring. Well, he is getting my attention. I simply do not agree. I think what Jim thinks about here is that Unit testing at the JUnit level is not really testing of customer requirements, and he is perfectly right. It is tests testing parts of the system implemented using classes to build an object oriented system. This means requirements translated into something computionally feasible. Maybe I am not using TDD properly, but I do not expect that my JUnit tests maps one-to-one to functional-requirements. <br><br>What Jim misses out on here, especially with respect to saying that YAGNI will kill you is what Mary Poppendieck states about eliminating waste. I am a strong believer in up-front design, but I am not a strong beleiver in building anticipated structures, especially without tests. I think you should really eliminate waste. <br><br><br><br><br> Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com2tag:blogger.com,1999:blog-29135008.post-63374254291227339472007-09-12T12:46:00.000+02:002010-02-23T17:11:21.850+01:00<h2>My track for the first day at JavaZone 2007</h2>I have just came home from speakers dinner after talking to a lot of different people that are giving talks at javazone.no. I really didn't have time to figure out what tracks I will visit tomorrow, there are a lot of options, but I am trying to prepare i bit now. I finally was able to meet Tor Nordbye, Carl Quinn and Dick Wall from the JavaPosse, I am really looking forward to be present at the live podcast tomorrow evening.<br><br>Here are the shortlist of talks (selected from 7 parallell tracks) that I will probably attend the first day:<br><br><div><table id="m9wi" border="0" cellpadding="3" cellspacing="0" height="265"><tbody><tr><td width="50%"><b><i>Time</i></b><br></td><td width="50%"><b><i>Talk</i></b><br></td></tr><tr><td width="50%">9.00-10.0<br></td><td width="50%"><a title="Web 2.5 development with Java" href="http://www4.java.no/web/show.do?page=92&articleid=5337" id="v36p">Web 2.5 development with Java</a>, Stephan Janssen</td></tr><tr><td width="50%">10.15-11.15<br></td><td width="50%"><a title="The State of Ajax, Dion Almaer and Ben Galbraith" href="http://www4.java.no/web/show.do?page=92&articleid=5492" id="debm">The State of Ajax, Dion Almaer and Ben Galbraith</a> </td></tr><tr><td width="50%">13.00-14-00<br></td><td width="50%"><a title="Five practical solutions to Agile myths" href="http://www4.java.no/web/show.do?page=92&articleid=5397" id="twxt">Five practical solutions to Agile myths</a>, James Coplien</td></tr><tr><td width="50%">14.15-15.15<br></td><td width="50%"><a title="Latest in Java Technology From Sun Microsystems , Simon Ritter og Angela M. Caicedo" href="http://www4.java.no/web/show.do?page=92&articleid=5524" id="zh1e">Latest in Java Technology From Sun Microsystems , Simon Ritter og Angela M. Caicedo</a> </td></tr><tr><td width="50%">15.45-16.45<br></td><td width="50%">Have to think about this one not sure actually<br></td></tr><tr><td width="50%">17.00-18.00<br></td><td width="50%"><a title="Scripting in Java 6 , Per Mengshoel og Thomas Heiberg" href="http://www4.java.no/web/show.do?page=92&articleid=5263" id="lcye">Scripting in Java 6 , Per Mengshoel og Thomas Heiberg</a> </td></tr><tr><td width="50%">18.15-19.15<br></td><td width="50%">JavaPosse RoundUp, Live podcasting from Oslo (You would not want to miss this one)<br></td></tr><tr><td width="50%"><br></td><td width="50%"><br></td></tr><tr><td width="50%"><br></td><td width="50%"><br></td></tr></tbody></table></div><br><br> Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com0tag:blogger.com,1999:blog-29135008.post-54092881156148201492007-09-12T12:26:00.000+02:002010-02-23T17:11:21.855+01:00<h2> Kicking of JavaZone 2007 </h2> Finaly it has launched, JavaZone 2007 is running with more than 120 speakers from all over the world, and more than 2200 attendants, make this a pretty large conference, at least according to Scandinavian standards. I have been participating the program-commitee myself and it is very fun to see everything come to a start. The program this year is pretty well balanced, Enterprise, Web , Agile and Hard-Core Java speakers from all over the world is here in large numbers.<br><br>There are definitely a lot of focus on Agile this year. On other conferences I have been attending during the last couple of years, there is always one or two subjects that stands out, but I don't find it to be as clear this year. There are definitely bias do use less heavyweight infrastructure in web-like deployment-scenarios that it used to be. There is also a lot of focus on Maven. We actually had to reject as much as five talks on Maven, because it was already so well-covered. <br><br>I spoke with the <a title="Javaposse" href="http://javaosse.com" id="i1uk">Javaposse</a> crew-members yesterday, and my impression is that Maven has a strong position in Scandinavia, and Less in the US. <br><br>Regardless if you are interested in Maven or Ajax there should definitely be something for every taste in this years program, hope you will enjoy it, we enjoyed putting it together!<br><br><br> <br><br>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com1tag:blogger.com,1999:blog-29135008.post-61359578399810844472007-06-25T01:30:00.000+02:002007-07-15T22:05:26.704+02:00 <h1>Continuous integration infrastructure, which OS to use<br></h1>I have been on several projects lately where we have been using continuous integration-servers like <a title="CruiseControl" href="http://cruisecontrol.sourceforge.net/">CruiseControl</a> and <a title="Continuum" href="http://maven.apache.org/continuum/">Continuum</a>. This part of the development infrastructure is crucial, unless you are all by yourself (unlikely) you will need some server that will continuously integrate, build and deploy your code. This has been pretty much been a de-facto standard for quite a while now, and is not what I am trying to address here. What I am trying to address is, does the OS used for continuous integration-servers (CI servers) really matter? Yes it does and it should not run on Windows for reasons that should become obvious after reading this article.<br><br>It really matters, it is really not the question of which operating-system to use, but which operation system not to use. For some reason, it is not uncommon to configure and set-up CI-servers on Windows early in early development stages. I know several companies that only supports W2K/XP as part of their central operations, or Unix of course. But in case of Unix, the servers are often quite costly, cannot be dedicated for running CI, needs to be ordered and configured centrally and so on. Lately more and more companies are also supporting Linux as part of their infrastructure base, but it is not as widely supported as W2K/XP (I don't know anyone running Vista yet). <br><br>It is also quite common to use Windows as development desktop, even in environments that does not rely on windows-specific features. I am primarily developing in Java and for the most I use Windows desktops for development at client sites, not because I want to, but becose this is the company standard at most of my clients where I do contracting. At my home office I run Linux (Ubuntu) and Laptop runs Mac OSX. Given the fact that you will most likely end-up developing code using a Windows box when you are at work, it is also quite possible that it is easier to get access to a spare box for running one or several instances of your preferred CI-server if you go for Windows. <br><br>Well, so you go about and install CruiseControl, Continuum or whatever other software that you want to use, on Windows. Well, I have tried the same quite a few times now, and I can tell you, it simply doesn't work on Windows. Windows cannot and should not be used ever to run CI-server, because you will most certainly end up in a situation that some file is locked and that the CI server cannot run its goal because it cannot delete a file locked by some other process.<br>Another thing is long pathnames. Windows doesn't support pathnames that are longer than 255 characters, and I guarantee you, if you have a deep project structure you will almost certainly run into this problem. A third issue that may become a problem is access. When accessing a windows-box, people has this mental image that they will need to use explorer to actually view and edit contents of directories and files, which is just stupid. People will need to access the box when the test fails on the CI-sever and not locally, which is a quite common case (hard coded paths, locale-issues and network access in integration tests are common things). This means that developers will need to use RemoteDesktop to access the server. Well, only a limited amount on connections are available, and it is heavy on the server to support many simultaneous connections so this will quickly bring you into trouble as well. All these issues makes Windows an no-go for CI servers, it is simply not possible to maintain stable CI servers without file-locking, pathname-problems and locking because of simultaneous access. You will need a full time employee to do the maintenance or go with Unix or Linux.<br><br><h2>What should I do?</h2>Well, an option is to take any Unix/Linux box available and use that for continuous integration instead. It will make all the problems mentioned in the previous paragraph go away. File locking is not a problem, pathnames can be as long as you want (almost true) and since everyone is using ssh, you could support a high number of simultaneous users viewing the build-log files using terminal access (which is very lightweight) instead of RemoteDesktop. The short answer is go with Unix based system. But what if that is not possible?<br>That was the case at previous engagement. Going for Linux was a no-op. And if we wanted to go for Unix, Solaris was the way to go. But we would never get root-access to that box and they have to order it first....*sigh*. Well, first of all. <br><br>My experience is that configuring CI-servers are generally best left as a task to the development team, preferably someone that has done this a couple of times before. I don't think it is possible to put these kind of things on order at your system-administration department, those responsible for test and production environments. It is probably outsourced anyway, so you will have to fill out a form before you are even allowed to all them. So much for agile. <br>Well, so what did we do. We went for Virtualization using <a title="VMWare" href="http://maven.apache.org/continuum/">VMWare</a>. VMWare gives you the ability to run any number for operating systems, called the guest OS, by using a player. The OS running the player is referred to as the the host OS. Here we were able to use a Windows-box running Ubuntu-Linux (my choice of course :-) as a guest operating system. After the guest operating system has been started it behaves looks an performs like a full-blown standalone OS without all the quirks mentioned earlier. The Virtual image was created with <a title="VMWare Workstation" href="http://www.vmware.com/products/ws/">VMWare Workstation</a> and may be executed with either VMWare Workstation or <a title="VMWare Player" href="http://www.vmware.com/products/player/">VMWare Player</a> which is free. The process of installing the operation system (Ubuntu Feisty) is identical to what you would do when you install it from scratch. I will not cover the installation details here, but briefly reflect on some additional benefit that may be provided when using VMware when running CI-servers (these issues may also apply to running appliances in general). Note that this also makes Windows boxes a viable alternative as a host OS.<br><br><h2>Benefits of running a virtualized CI-server</h2>In my experience, CI servers are not treated as production-goods my most organizations, although they should, This often results in decisions like, hey we need to use that box we gave you last week, can't you just use this one instead? The point is, it should be really easy to change hardware. In VMWare your entire installation is basically just a couple of files in a directory. If you copy and transfer those files to a new box, you can start the guest-OS using the player there instead. The only thing you will have to install on the new box is the VMWare Player.<br><br>Staging or upgrading such environments are often also problematic. This is actually production software for your development team. If you want to upgrade the CI server with lets' say a new version of Continuum, you can do so my taking a snapshot of your current image. Copy that image and start it up on your desktop. Here you can do whatever changes that you want to the guest operating system, including upgrading to the newest version of Maven and Continuum. You can even dry test the build on your local machine. If it work, you are all set to offload an updated snapshot to the CI-production server. By using VMWare in this way, it really gives the term "staging" true meaning.<br>Based upon experience for several years running large projects with CI servers, this is really the best approach. Having a build CI-server going to a stop caused by reasons not related to code or test uncovering actual problems over and over a again will quickly render your CI infrastructure useless, people will stop to trust it, and this is not what you want. <br><br><br><br><br><br><br><br><br>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com2tag:blogger.com,1999:blog-29135008.post-7556116307919452132007-05-04T23:51:00.000+02:002010-02-23T17:11:21.861+01:00 <h1>Upgrading Ubuntu from Edgy to Feisty</h1><br>Last week I upgraded my my Ubuntu installation from Edgy to Feisty. I had been playing around quite a bit to get <a title="Compiz" href="http://compiz.org/">Compiz</a> and <a title="Beryl" href="http://www.beryl-project.org/">Beryl</a> to work whithout much luck on Edgy. Some time ago I also tried to install the beta of Feisty, but i could not get my Radeon X1800 card working properly, the desktop was a mess. Anyways, I am occasionally using the Synaptic package manager, and not to long ago it asked me if I wanted to upgrade from Edgy Eft, which is 6.10 to Feisty running on 7.0.4. Apart from a few new tools, more adequate support for restricted drivers, like my ATI -card and build-in support for Compiz and Beryl, I was tempted to give it a go.<br><br>I have had my Dual screen desktop running 2 x 22" screen monitors running with pristine colors for some time, but withould 3D effects. After upgrading however, I could just see that it was not working properly. It did not render fonts properly in the dual heda mode, but as working fine when using just one monitor. Disappointing, I was really looking forward to getting Compiz and Beryl up and running, instead I was actuallu set back to start. Now I am waiting for the system to download all updates after I reinstalled the entire system from scratch. <br><br>So if you are using an ATI Radon X1800/1900 card, do not upgrade to Feisty if you are using a dual-head configuration on you displays. Now I have been wise enough to configure a separate partition where I can engage myself in a feasibility study before I actually see if it is working.<br><br>Anyways, after switching from XP 64, which did not work at all!! I am very satisfied with my Ubuntu distro, I really want to recommend it.<br><br><br><br>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com3tag:blogger.com,1999:blog-29135008.post-68252138216137750062007-03-19T00:20:00.000+01:002007-04-14T00:21:58.548+02:00 <h2>Unit testing, a lot of developers don't get it</h2><br>As a developer I quite often stumble across code that I would like to rewrite. The reasons why I want to rewrite the piece of code, may differ from case to case, reduce coupling and remove duplication are well known reasons. Lately I have been doing a lot of refactoring and one thing that stands out is how much terrible test code it is out there. It seems as if developers think that if they just have written a test for it, and the code coverage if good, then everything is good. This is dead wrong. I have seen people backing away from changing bad code just because they were backed by brittle and hard to understand tests.<br><br>Doing refactoring requires that tests are present. In systems using code written less than two or maybe three years ago, it seems to be quite rare that the code is not been backed by tests to some extension. But the way tests are written varies greatly. Having tests is a necessary but not sufficient prerequisite to do effective refactoring. In the latter cases where I have been doing requirements it strikes me as if a lot of developers do not understand that the same principles that they apply when writing system-code, should also be applied when writing test-code. It is all code, and should be treated as such. I have seen by far too much duplication, lengthy pieces of code iterating over collections just to add a conditional and assert for the particular element they where looking for, and by far to much cut-copy paste, ecpecialy in test-fixtures.<br><br>I am am doing a <a title="Lightening Talk" href="http://events.ccc.de/congress/2006/Lightning_Talks">Lightening Talk</a> on how to simplify unit testing on <a title="Oslo XP Meetup" href="http://xp.meetup.com/13/calendar/5515448/">Oslo XP Meetup</a> on 26 March. I will discuss small things you can use to write more <span style="font-style: italic;">fluent </span>tests, tests that are easier to read and that requires less code. When I was reading up on different aspects on Unit testing, I came over <a title="this great article" href="http://www.cwi.nl/%7Eleon/papers/xp2001/xp2001.pdf">this great article</a> that was linked from unit.org. It really explains in sufficient details code smells in test-code and how to refactor them. Read it and distribute it to your peer developers.<br><br><br><br><br><br>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com2tag:blogger.com,1999:blog-29135008.post-68915890362282891022007-03-04T19:53:00.000+01:002008-09-07T13:31:11.116+02:00 <H1 id="j7pp"> Effective pagination using Hibernate </H1><P id="yh4q"> This article presents with an solution on how to page through large amounts of data effectively without taking down your database and without keeping it all in memory.<BR id="j7pp0"></P><H2 id="qdnf">Last major update 07.09.2008</H2><P id="qdnf0">I have now added references that describes how to retrieve the source-code for the examples. All source-code is released under the Creative Commons License as can be seen from the Licensing details, the source code can be retrieved from http://svitjod.rymdweb.com/repository/com/zenior/sandbox/ which contains the source-code in maven form. To include a dependency to the source code just include:</P><P id="i5jj"></P><P id="i5jj1"><repository><BR id="jo4m"></P> <FONT face="Courier New" id="i5jj2"> <id>internal</id><BR id="jo4m0"> <name>Svitjod</name><BR id="jo4m1"> <layout>default</layout><BR id="jo4m2"> <url>http://svitjod.rymdweb.com/repository</url><BR id="jo4m3"> <snapshots><BR id="jo4m4"> <enabled>false</enabled><BR id="jo4m5"> </snapshots><BR id="jo4m6"></FONT><P id="i5jj3"><FONT face="Courier New" id="i5jj4"> </repository></FONT></P><P id="i5jj5"></P><P id="i5jj7"><FONT face="Courier New" id="i5jj8">and </FONT><BR id="jo4m7"></P><P id="i5jj9"></P><P id="i5jj11"><FONT face="Courier New" id="i5jj12"> <dependency><BR id="sxkc"> <groupId>com.zenior.sandbox</groupId><BR id="sxkc0"> <artifactId>example-domain</artifactId><BR id="sxkc1"> <version>1.0-SNAPSHOT</version><BR id="sxkc2"> <scope>compile</scope><BR id="sxkc3"> </dependency></FONT></P><P id="sxkc4"></P><P id="sxkc6"></P><P id="sxkc8"><FONT face="Courier New" id="sxkc9"> <dependency><BR id="sxkc10"></FONT><FONT face="Courier New" id="sxkc11"> <groupId>com.zenior.sandbox</groupId><BR id="sxkc12"> <artifactId>hibernate-sandbox</artifactId><BR id="sxkc13"> <version>1.0-SNAPSHOT</version><BR id="sxkc14"> <scope>compile</scope><BR id="sxkc15"> </dependency><BR id="sxkc16"></FONT></P><P id="md.a"></P><P id="md.a0">To your project pom.xml. <BR id="jo4m8"></P><P id="ndif"></P><P id="ndif0">If do not use maven, you may just download the source code by looking for files ending with -sources in the maven repository mentioned above.</P><H1 id="j7pp1"> Abstract </H1> Dealing effectively with large resultsets is important. Batch applications may require to process millions of rows as part of a transaction. The brute force approach would be read everything up in memory before iterating over theelements. This approach will effectively kill performance and use far to much memory. One common approach when using Hibernate is to use options in the <SPAN style='font-family: "Courier New"' id="j7pp2">Criteria </SPAN>interface called <SPAN style='font-family: "Courier New"' id="j7pp3">setFirstResult</SPAN>/<SPAN style='font-family: "Courier New"' id="j7pp4">setMaxResult</SPAN>. This will generate SQL (at least for Oracle) where the database will actually have to read and throw away data before returning them to the client. Another approach is to use <SPAN style='font-family: "Courier New"' id="j7pp5">ScrollableResult</SPAN>s, but here you will have to keep the connection open during the entire pagination process. By retrieving a collection of all the primary keys for the matching object, you will need to perform an extra query before actually retrieving the data, but it is very easy to generate effective SQL to retrieve using this approach. This is by far the best solution in terms of database-load and memory footprint, and it is easy to implement in a portable manner.<BR id="j7pp6"><BR id="j7pp7"><H1 id="j7pp8"> The problem </H1> In order to have a rich domain model, we want relationships between domain objects to be implemented as relationships between the Java classes. If we are going to be able to do that without killing performance, we have be smart in how we deal with relationships having high cardinality.<BR id="j7pp9"><BR id="j7pp10"> Most importantly we must iterate through a large resultset without keeping all data in memory. We also want the approach to generate simple SQL, and avoid using esoteric options that make the SQL difficult to optimize or difficult to port. We might also need adjustments to the mapping strategy and relationships to retrieve data effectively.<BR id="j7pp11"><BR id="j7pp12"> It is assumed that the reader is familiar with Hibernate and with common ORM issues like n+1 selects.<BR id="j7pp13"><BR id="j7pp14"><H1 id="j7pp15"> The example </H1> An order application processing an order with more than 100.000 order lines.We will see how different solutions differ with respect to memory consumption, resource usage in general, effectiveness in terms of execution and differences in how the SQL is generated. The solution will be using Java 6, Hibernate3.2.0GA with annotations, the Spring framework and Oracle XE.<BR id="j7pp16"><BR style="background-color: #ff0000" id="j7pp17"> I will test three different approaches that don't use custom code and for each approach say something about execution time, memory consumption and explain the inner details.<BR id="j7pp18"> As a domain model for the test I have been using a domain-model representing a generic order-domain as shown in figure 1.<BR id="j7pp19"><IMG src="http://docs.google.com/File?id=dcs9tn98_11db4c97" style="height: 161px; width: 204px" title="Order Domain" id="j7pp20"><BR id="j7pp21"><B id="j7pp22">Figure 1</B><BR id="j7pp23"> The model is simplified but representative.<BR id="j7pp24"><H3 id="j7pp25"> Test fixture </H3> I have used Hibernate and Springs <SPAN style='font-family: "Courier New"' id="j7pp26">AbstractTransactionalSpringContextTests</SPAN>topopulate the test fixture that has been inserted into the database. Idon't want the unit test to include timing for actually setting up the data.Therefore I have executed the fixture-setup by adjusting the test-case slightly so that the fixture is actually committed, by using the following approach:<BR id="j7pp28"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp29"><SPAN style="color: #800000" id="j7pp30"> 1 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp31"><B id="j7pp32">protected</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp33"><B id="j7pp34">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp35"> onSetUpInTransaction() </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp36"><B id="j7pp37">throws</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp38"> Exception {<BR id="j7pp39"></SPAN><SPAN style="color: #800000" id="j7pp40"> 2 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp41"><B id="j7pp42">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp43"> (!isTestDataPresent()) {<BR id="j7pp44"></SPAN><SPAN style="color: #800000" id="j7pp45"> 3 </SPAN><SPAN style="background-color: #ffffff" id="j7pp46"> createOrderWithOrderLines(</SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp47">1000</SPAN><SPAN style="background-color: #ffffff" id="j7pp48"> * </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp49">1000</SPAN><SPAN style="background-color: #ffffff" id="j7pp50">);<BR id="j7pp51"></SPAN><SPAN style="color: #800000" id="j7pp52"> 4 </SPAN><SPAN style="background-color: #ffffff" id="j7pp53"> setComplete();<BR id="j7pp54"></SPAN><SPAN style="color: #800000" id="j7pp55"> 5 </SPAN><SPAN style="background-color: #ffffff" id="j7pp56"> endTransaction();<BR id="j7pp57"></SPAN><SPAN style="color: #800000" id="j7pp58"> 6 </SPAN><SPAN style="background-color: #ffffff" id="j7pp59"> }<BR id="j7pp60"></SPAN><SPAN style="color: #800000" id="j7pp61"> 7 </SPAN><SPAN style="background-color: #ffffff" id="j7pp62">}</SPAN></PRE><B id="j7pp63">Listing 1</B><BR id="j7pp64"> By using the<SPAN style='font-family: "Courier New"' id="j7pp65"> AbstractTransactionalSpringContextTests</SPAN> I can actually force the test itself to commit the data, which may sometimes be useful when inspecting persistent side-effects to data when executing tests. The methods<SPAN style='font-family: "Courier New"' id="j7pp66"> setComplete() </SPAN>and <SPAN style='font-family: "Courier New"' id="j7pp67">endTransaction()</SPAN> will force the execution to commit after the test is finished. To make it idempotent, I have added a method that checks f the test-data is already there.<BR id="j7pp68"><BR id="j7pp69"><P style="background-color: #ffffff" id="j7pp70"> The brute-force approach yields the following test-results on my workstation, which is a custom built AMD Athlon 64 X2 4600, 4GB Ram, Dual Raptor 150GB SATA in a Raid 0 setup. The tests have been launched from IntelliJ 6.0.4 and with the Oracle XE instance running on the same machine. The test runner is launched in a spawned process using a maximum of 1 GB RAM (-Xmx1G). </P><BR id="j7pp71"><H3 id="j7pp72"> Brute force </H3> In the first approach, we process the entire order without thinking about memory consumption when we retrieve OrderLine instances from Hibernate.<BR id="j7pp73"> This solution basically uses the one-to-many relational mapping and leaves it up to Hibernate to retrieve the data.<BR id="j7pp74"><BR id="j7pp75"> The mapping is defined as follows:<BR id="j7pp76"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp77"><SPAN style="color: #800000" id="j7pp78"> 1 </SPAN> <SPAN style="color: #808000; background-color: #ffffff" id="j7pp79">@OneToMany(</SPAN><SPAN style="background-color: #ffffff" id="j7pp80">mappedBy = </SPAN><SPAN style="color: #008000; background-color: #ffffff" id="j7pp81"><B id="j7pp82">"order"</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp83">, cascade = CascadeType.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp84"><B id="j7pp85"><I id="j7pp86">ALL,</I></B></SPAN><SPAN style="background-color: #ffffff" id="j7pp87"> fetch = FetchType.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp88"><B id="j7pp89"><I id="j7pp90">LAZY)<BR id="j7pp91"></I></B></SPAN><SPAN style="color: #800000" id="j7pp92"> 2 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp93"><B id="j7pp94">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp95"> Set getOrderLines() {<BR id="j7pp96"></SPAN><SPAN style="color: #800000" id="j7pp97"> 3 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp98"><B id="j7pp99">return</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp100"><B id="j7pp101">orderLines;<BR id="j7pp102"></B></SPAN><SPAN style="color: #800000" id="j7pp103"> 4 </SPAN><SPAN style="background-color: #ffffff" id="j7pp104"> }</SPAN> </PRE><B id="j7pp105">Listing 2</B><BR id="j7pp106">And on the OrderLine side of the bi-directional relationship, we have:<BR id="j7pp108"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp109"><SPAN style="color: #800000" id="j7pp110"> 1 </SPAN> <SPAN style="color: #808000; background-color: #ffffff" id="j7pp111">@ManyToOne(</SPAN><SPAN style="background-color: #ffffff" id="j7pp112">fetch = FetchType.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp113"><B id="j7pp114"><I id="j7pp115">EAGER)<BR id="j7pp116"></I></B></SPAN><SPAN style="color: #800000" id="j7pp117"> 2 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp118"><B id="j7pp119">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp120"> Order getOrder() {<BR id="j7pp121"></SPAN><SPAN style="color: #800000" id="j7pp122"> 3 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp123"><B id="j7pp124">return</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp125"><B id="j7pp126">order;<BR id="j7pp127"></B></SPAN><SPAN style="color: #800000" id="j7pp128"> 4 </SPAN><SPAN style="background-color: #ffffff" id="j7pp129"> }</SPAN></PRE><P id="j7pp130"><B id="j7pp131">Listing 3</B><BR id="j7pp132"></P><P id="j7pp133"> The test that gathers timing and resource consumption information is a simple JUnit-test method: </P><P id="j7pp134"> </P><PRE style="line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp135"><SPAN style="color: #800000" id="j7pp136"> 1 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp137"><B id="j7pp138">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp139"><B id="j7pp140">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp141"> testRetrieveOrderBruteForce() {<BR id="j7pp142"></SPAN><SPAN style="color: #800000" id="j7pp143"> 2 </SPAN><SPAN style="background-color: #ffffff" id="j7pp144"> Order order = (Order) </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp145"><B id="j7pp146">hibernateTemplate.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp147">get(Order.</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp148"><B id="j7pp149">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp150">, </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp151"><B id="j7pp152">orderId)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp153">;<BR id="j7pp154"></SPAN><SPAN style="color: #800000" id="j7pp155"> 3 </SPAN><SPAN style="background-color: #ffffff" id="j7pp156"> ResourceMonitor monitor = </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp157"><B id="j7pp158">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp159"> ResourceMonitor(</SPAN><SPAN style="color: #008000; background-color: #ffffff" id="j7pp160"><B id="j7pp161">"order.getOrderLines()"</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp162">);<BR id="j7pp163"></SPAN><SPAN style="color: #800000" id="j7pp164"> 4 </SPAN> <SPAN style="background-color: #ffffff" id="j7pp165"><I id="j7pp166">assertEquals(</I></SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp167">1000</SPAN><SPAN style="background-color: #ffffff" id="j7pp168">*</SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp169">1000</SPAN><SPAN style="background-color: #ffffff" id="j7pp170">,order.getOrderLines().size());<BR id="j7pp171"></SPAN><SPAN style="color: #800000" id="j7pp172"> 5 </SPAN><SPAN style="background-color: #ffffff" id="j7pp173"> System.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp174"><B id="j7pp175"><I id="j7pp176">out.</I></B></SPAN><SPAN style="background-color: #ffffff" id="j7pp177">println(monitor.stop());<BR id="j7pp178"></SPAN><SPAN style="color: #800000" id="j7pp179"> 6 </SPAN><SPAN style="background-color: #ffffff" id="j7pp180">}</SPAN></PRE><P id="j7pp181"><B id="j7pp182">Listing 4</B><BR id="j7pp183"></P><BR id="j7pp184"><DIV id="j7pp185"><TABLE style="width: 325px; height: 66px" border="1" cellpadding="3" cellspacing="0" id="j7pp186"><TBODY id="j7pp187"><TR id="j7pp188"><TD width="50%" id="j7pp189"><B id="j7pp190"> Time elapsed<BR id="j7pp191"></B></TD><TD width="50%" id="j7pp192"><B id="j7pp193">Memory usage delta</B><BR id="j7pp194"></TD></TR><TR id="j7pp195"><TD width="50%" id="j7pp196"> 79,5s<BR id="j7pp197"></TD><TD width="50%" id="j7pp198"> 501000kb<BR id="j7pp199"></TD></TR></TBODY></TABLE><B id="j7pp200">Table 1 </B>Test results brute-force approach<BR id="j7pp201"><BR id="j7pp202"> As we can see, it is quite fast to retrieve all the data in just a single select. We have retrieved 1000000 <SPAN style='font-family: "Courier New"' id="j7pp203">OrderLine</SPAN> instances in close to 80-seconds. The problem with this approach is that it is memory intensive. On most 32-bit systems, there is a practical upper limit of around 2GB heap, which will make it difficult to have more than three such queries running simultaneously <A href="View?docid=dcs9tn98_8hpc5kc#memory" title="java -heap limitations in 32 bit systems" id="j7pp204">[1]</A>.<BR id="j7pp205"> In addition to this, when using a <SPAN style='font-family: "Courier New"' id="j7pp206">StatefulSession </SPAN>in Hibernate to keep track of updated fields, keeping this much data in memory at the same time will eventually halt your system or make it very slow <A href="View?docid=dcs9tn98_8hpc5kc#hibernate_batch" title="Hibernate batch processing" id="j7pp207">[2]</A>. Note that making the relationship lazy (which is the default behavior in Hibernate) will not change that fact that everything is fetched using one single select.<BR id="j7pp208"></DIV><H3 id="j7pp209"> Using Criteria search limited by firstResult and maxResult </H3> In order to retrieve the <SPAN style='font-family: "Courier New"' id="j7pp210">OrderLine</SPAN> side of the relationship using a Criteria query, we clearly cannot have a Hibernate-managed relationship between <SPAN style='font-family: "Courier New"' id="j7pp211">Order </SPAN>and<SPAN style='font-family: "Courier New"' id="j7pp212"> OrderLine</SPAN>, we will have to manage this relationship ourselves. The most visible consequence of this will be that the <SPAN style='font-family: "Courier New"' id="j7pp213">Set<OrderLine></SPAN> property of <SPAN style='font-family: "Courier New"' id="j7pp214">Order </SPAN>will have to be removed.This is unfortunate because it removes an important aspect of the domain-model, which is the explicit composition that constitutes the relationship.<BR id="j7pp215"><P id="j7pp216"><BR id="j7pp217"></P> When dealing with cases like this, I would like to be explicit about the relationship also in the domain of the Order-class, so other than removing the<SPAN style='font-family: "Courier New"' id="j7pp218"> getOrderLines()</SPAN>method from the Order class, I would prefer changing it to something like this shown in listing 5.<BR id="j7pp219"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp220"><SPAN style="color: #800000" id="j7pp221"> 1 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp222"><B id="j7pp223">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp224"> Set<OrderLine> getOrderLines(HibernateTemplate template) {<BR id="j7pp225"></SPAN><SPAN style="color: #800000" id="j7pp226"> 2 </SPAN><SPAN style="background-color: #ffffff" id="j7pp227"> ....<BR id="j7pp228"></SPAN><SPAN style="color: #800000" id="j7pp229"> 3 </SPAN><SPAN style="background-color: #ffffff" id="j7pp230">}</SPAN></PRE><B id="j7pp231">Listing 5</B><BR id="j7pp232"><BR id="j7pp233"> Here it is still quite clear that <SPAN style='font-family: "Courier New"' id="j7pp234">Order</SPAN> has a relationship to<SPAN style='font-family: "Courier New"' id="j7pp235"> OrderLine</SPAN>. Still, however, we will have to implement the paging mechanism using a Colllection-implementation, which preserves a pretty decent domain-model with respect to an explicit relationship between <SPAN style='font-family: "Courier New"' id="j7pp236">Order </SPAN>and<SPAN style='font-family: "Courier New"' id="j7pp237"> OrderLine</SPAN>. This might turn out to be a good thing, because it will probably easier to refactor the<SPAN style='font-family: "Courier New"' id="j7pp238"> getOrderLines </SPAN>method to be extended to take a <SPAN style='font-family: "Courier New"' id="j7pp239">HibernateTemplate</SPAN> as an argument instead of in lining some other implementation whenever we need to retrieve <SPAN style='font-family: "Courier New"' id="j7pp240">OrderLine</SPAN> instances belonging to an<SPAN style='font-family: "Courier New"' id="j7pp241"> Order</SPAN>.<BR id="j7pp242"> An even better approach here would be to de-couple the dependency to Hibernate completely.<BR id="j7pp243"><BR id="j7pp244">I discovered this after implementing the<SPAN style='font-family: "Courier New"' id="j7pp245"> getOrderLines()</SPAN> - method, taking hibernateTemplate as a parameter. The example-domain module that contains the order-domain related classes, did not have a dependency to Hibernate, which I did not want to introduce because I wanted the example-domain to be as lean as possible. In order to compare multiple strategies for paging using the same domain-classes I had to introduce an interface that made plugging different strategies as in listing 6.<BR id="j7pp246"><PRE style="line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp247"><SPAN style="color: #800000" id="j7pp248"> 1 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp249"><B id="j7pp250">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp251"> Collection getOrderLines(CollectionBuilder collectionBuilder) {<BR id="j7pp252"></SPAN><SPAN style="color: #800000" id="j7pp253"> 2 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp254"><B id="j7pp255">return</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp256"> collectionBuilder.build(</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp257"><B id="j7pp258">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp259">);<BR id="j7pp260"></SPAN><SPAN style="color: #800000" id="j7pp261"> 3 </SPAN><SPAN style="background-color: #ffffff" id="j7pp262">}<BR id="j7pp263"><BR id="j7pp264"></SPAN><BR id="j7pp265"><SPAN style="color: #800000" id="j7pp266"> 1 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp267"><B id="j7pp268">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp269"><B id="j7pp270">interface</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp271"> CollectionBuilder {<BR id="j7pp272"></SPAN><SPAN style="color: #800000" id="j7pp273"> 2 </SPAN> <SPAN style="color: #808080; background-color: #ffffff" id="j7pp274"><I id="j7pp275">/**<BR id="j7pp276"></I></SPAN><SPAN style="color: #800000" id="j7pp277"> 3 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp278"><I id="j7pp279"> * Build the collection using information from the given instance.<BR id="j7pp280"></I></SPAN><SPAN style="color: #800000" id="j7pp281"> 4 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp282"><I id="j7pp283"> * </I></SPAN><SPAN style="color: #808080" id="j7pp284"><SPAN style="color: #808080; background-color: #ffffff" id="j7pp285"><B id="j7pp286"><I id="j7pp287"><U id="j7pp288">@param</U></I></B></SPAN></SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp289"><I id="j7pp290"> instance<BR id="j7pp291"></I></SPAN><SPAN style="color: #800000" id="j7pp292"> 5 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp293"><I id="j7pp294"> * </I></SPAN><SPAN style="color: #808080" id="j7pp295"><SPAN style="color: #808080; background-color: #ffffff" id="j7pp296"><B id="j7pp297"><I id="j7pp298"><U id="j7pp299">@return<BR id="j7pp300"></U></I></B></SPAN></SPAN><SPAN style="color: #800000" id="j7pp301"> 6 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp302"><I id="j7pp303"> */<BR id="j7pp304"></I></SPAN><SPAN style="color: #800000" id="j7pp305"> 7 </SPAN><SPAN style="background-color: #ffffff" id="j7pp306"> Collection build(Object owner);<BR id="j7pp307"></SPAN><SPAN style="color: #800000" id="j7pp308"> 8 </SPAN><SPAN style="background-color: #ffffff" id="j7pp309">}</SPAN> <BR id="j7pp310"><BR id="j7pp312"></PRE><B id="j7pp313">Listing 6<BR id="j7pp314"><BR id="j7pp315"></B> Using the Collection-builder interface, I could easily provide a Hibernate based implementation of the different strategies without introducing a Hibernate dependency into the domain-classes. Here it would be even more visible that the one-to-many collection is owned by an order instance, signified by the owner parameter of the build-method.<BR id="j7pp316"><BR id="j7pp317"> To support paging by restricting the underlying resultset Hibernate uses a mechanism by using the Dialect interface. This mechanism varies greatly between different RDBMS'es. The Orcale9Dialect uses a construct in oracle called rownum restrictions, which may be found in the <SPAN style='font-family: "Courier New"' id="j7pp318">getLimitString</SPAN>-method of the Dialect implementation given in listing 7 (listed only in part).<BR id="j7pp319"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp320"><SPAN style="color: #800000" id="j7pp321"> 1 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp322"><B id="j7pp323">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp324"> String getLimitString(String sql, </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp325"><B id="j7pp326">boolean</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp327"> hasOffset) {<BR id="j7pp328"></SPAN><SPAN style="color: #800000" id="j7pp329"> 2 </SPAN><SPAN style="background-color: #ffffff" id="j7pp330">....<BR id="j7pp331"></SPAN><SPAN style="color: #800000" id="j7pp332"> 10 </SPAN><SPAN style="background-color: #ffffff" id="j7pp333"> StringBuffer pagingSelect = </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp334"><B id="j7pp335">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp336"> StringBuffer( sql.length()+</SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp337">100</SPAN><SPAN style="background-color: #ffffff" id="j7pp338"> );<BR id="j7pp339"></SPAN><SPAN style="color: #800000" id="j7pp340"> 11 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp341"><B id="j7pp342">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp343"> (hasOffset) {<BR id="j7pp344"></SPAN><SPAN style="color: #800000" id="j7pp345"> 12 </SPAN><SPAN style="background-color: #ffffff" id="j7pp346"> pagingSelect.append(</SPAN><SPAN style="color: #008000; background-color: #ffffff" id="j7pp347"><B id="j7pp348">"select * from ( select row_.*, rownum rownum_ from ( "</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp349">);<BR id="j7pp350"></SPAN><SPAN style="color: #800000" id="j7pp351"> 13 </SPAN><SPAN style="background-color: #ffffff" id="j7pp352"> }<BR id="j7pp353"></SPAN><SPAN style="color: #800000" id="j7pp354"> 14 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp355"><B id="j7pp356">else</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp357"> {<BR id="j7pp358"></SPAN><SPAN style="color: #800000" id="j7pp359"> 15 </SPAN><SPAN style="background-color: #ffffff" id="j7pp360"> pagingSelect.append(</SPAN><SPAN style="color: #008000; background-color: #ffffff" id="j7pp361"><B id="j7pp362">"select * from ( "</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp363">);<BR id="j7pp364"></SPAN><SPAN style="color: #800000" id="j7pp365"> 16 </SPAN><SPAN style="background-color: #ffffff" id="j7pp366"> }<BR id="j7pp367"></SPAN><SPAN style="color: #800000" id="j7pp368"> 17 </SPAN><SPAN style="background-color: #ffffff" id="j7pp369"> pagingSelect.append(sql);<BR id="j7pp370"> ........<BR id="j7pp371"></SPAN><SPAN style="color: #800000" id="j7pp372"> 30 </SPAN><SPAN style="background-color: #ffffff" id="j7pp373">}<BR id="j7pp374"></SPAN><SPAN style="color: #800000" id="j7pp375"> 31 </SPAN></PRE><B id="j7pp376">Listing 7<BR id="j7pp377"><BR id="j7pp378"></B> Without careful indexing and dependent upon the underlying RDBMS you might end up with a situation that may force the RDBMS to scan all the data for the entire set of <SPAN style='font-family: "Courier New"' id="j7pp379">OrderLine </SPAN>items each time in order to return the subset limited by<SPAN style='font-family: "Courier New"' id="j7pp380"> setFirstResult </SPAN>and<SPAN style='font-family: "Courier New"' id="j7pp381"> setMaxResult</SPAN>.<BR id="j7pp382"> Here is an implementation of a<SPAN style='font-family: "Courier New"' id="j7pp383"> Collection </SPAN>implementation that may page the underlying data based upon limiting the page size in the way mentioned above:<BR id="j7pp384"><BR id="j7pp385"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp386"><SPAN style="color: #800000" id="j7pp387"> 1 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp388"><B id="j7pp389">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp390"><B id="j7pp391">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp392"> PagingCollection </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp393"><B id="j7pp394">extends</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp395"> AbstractCollection {<BR id="j7pp396"></SPAN><SPAN style="color: #800000" id="j7pp397"> 2 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp398"><B id="j7pp399">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp400"> HibernateTemplate </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp401"><B id="j7pp402">hibernateTemplate;<BR id="j7pp403"></B></SPAN><SPAN style="color: #800000" id="j7pp404"> 3 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp405"><B id="j7pp406">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp407"> HibernateCriteriaSpecification </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp408"><B id="j7pp409">specificationCriteria;<BR id="j7pp410"></B></SPAN><SPAN style="color: #800000" id="j7pp411"> 4 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp412"><B id="j7pp413">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp414"><B id="j7pp415">int</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp416"><B id="j7pp417">pageSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp418">= </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp419">2000</SPAN><SPAN style="background-color: #ffffff" id="j7pp420">;<BR id="j7pp421"></SPAN><SPAN style="color: #800000" id="j7pp422"> 5 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp423"><B id="j7pp424">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp425"> Integer </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp426"><B id="j7pp427">collectionSize;<BR id="j7pp428"></B></SPAN><SPAN style="color: #800000" id="j7pp429"> 6 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp430"><B id="j7pp431">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp432"> Criteria </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp433"><B id="j7pp434">queryCriteria;<BR id="j7pp435"></B></SPAN><SPAN style="color: #800000" id="j7pp436"> 7 <BR id="j7pp437"> 8 <BR id="j7pp438"> 9 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp439"><B id="j7pp440">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp441"> PagingCollection(HibernateTemplate hibernateTemplate, HibernateCriteriaSpecifiaa criteria, </SPAN><SPAN style="color: #000080" id="j7pp442"><B id="j7pp443">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp444"> pageSize)<BR id="j7pp445"></SPAN><SPAN style="color: #800000" id="j7pp446"> 10 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp447"><B id="j7pp448"> this</B></SPAN>.<SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp449"><B id="j7pp450">specificationCriteria </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp451">= criteria;<BR id="j7pp452"></SPAN><SPAN style="color: #800000" id="j7pp453"> 11 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp454"><B id="j7pp455">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp456">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp457"><B id="j7pp458">hibernateTemplate </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp459">= hibernateTemplate;<BR id="j7pp460"></SPAN><SPAN style="color: #800000" id="j7pp461"> 12 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp462"><B id="j7pp463">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp464">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp465"><B id="j7pp466">pageSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp467">= pageSize;<BR id="j7pp468"></SPAN><SPAN style="color: #800000" id="j7pp469"> 13 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp470"><B id="j7pp471">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp472">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp473"><B id="j7pp474">queryCriteria </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp475">= criteria.populate(createCriteria());<BR id="j7pp476"></SPAN><SPAN style="color: #800000" id="j7pp477"> 14 </SPAN><SPAN style="background-color: #ffffff" id="j7pp478"> }<BR id="j7pp479"></SPAN><SPAN style="color: #800000" id="j7pp480"> 15 <BR id="j7pp481"> 16 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp482"><B id="j7pp483">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp484"> Iterator iterator() {<BR id="j7pp485"></SPAN><SPAN style="color: #800000" id="j7pp486"> 17 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp487"><B id="j7pp488">return</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp489"><B id="j7pp490">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp491"> PagedIterator(size());<BR id="j7pp492"></SPAN><SPAN style="color: #800000" id="j7pp493"> 18 </SPAN><SPAN style="background-color: #ffffff" id="j7pp494"> }<BR id="j7pp495"></SPAN><SPAN style="color: #800000" id="j7pp496"> 19 <BR id="j7pp497"> 20 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp498"><B id="j7pp499">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp500"><B id="j7pp501">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp502"> size() {<BR id="j7pp503"></SPAN><SPAN style="color: #800000" id="j7pp504"> 21 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp505"><B id="j7pp506">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp507"> (</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp508"><B id="j7pp509">collectionSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp510">== </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp511"><B id="j7pp512">null</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp513">) {<BR id="j7pp514"></SPAN><SPAN style="color: #800000" id="j7pp515"> 22 </SPAN><SPAN style="background-color: #ffffff" id="j7pp516"> Criteria criteria = </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp517"><B id="j7pp518">specificationCriteria.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp519">populate(createCriteria());<BR id="j7pp520"></SPAN><SPAN style="color: #800000" id="j7pp521"> 23 </SPAN><SPAN style="background-color: #ffffff" id="j7pp522"> criteria.setProjection(Projections.</SPAN><SPAN style="background-color: #ffffff" id="j7pp523"><I id="j7pp524">countDistinct(</I></SPAN>"id"<SPAN style="background-color: #ffffff" id="j7pp525">));<BR id="j7pp526"></SPAN><SPAN style="color: #800000" id="j7pp527"> 24 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp528"><B id="j7pp529">collectionSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp530">= (Integer) criteria.uniqueResult();<BR id="j7pp531"></SPAN><SPAN style="color: #800000" id="j7pp532"> 25 </SPAN><SPAN style="background-color: #ffffff" id="j7pp533"> }<BR id="j7pp534"></SPAN><SPAN style="color: #800000" id="j7pp535"> 26 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp536"><B id="j7pp537">return</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp538"><B id="j7pp539">collectionSize;<BR id="j7pp540"></B></SPAN><SPAN style="color: #800000" id="j7pp541"> 27 </SPAN><SPAN style="background-color: #ffffff" id="j7pp542"> }<BR id="j7pp543"></SPAN><SPAN style="color: #800000" id="j7pp544"> 28 <BR id="j7pp545"> 29 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp546"><B id="j7pp547">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp548"> Criteria createCriteria() {<BR id="j7pp549"></SPAN><SPAN style="color: #800000" id="j7pp550"> 30 </SPAN><SPAN style="background-color: #ffffff" id="j7pp551"> Criteria criteria = (Criteria) </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp552"><B id="j7pp553">hibernateTemplate.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp554">execute(</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp555"><B id="j7pp556">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp557"> HibernateCallback() {<BR id="j7pp558"></SPAN><SPAN style="color: #800000" id="j7pp559"> 31 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp560"><B id="j7pp561">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp562"> Object doInHibernate(Session session) </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp563"><B id="j7pp564">throws</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp565"> HibernateException, SQLException {<BR id="j7pp566"></SPAN><SPAN style="color: #800000" id="j7pp567"> 32 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp568"><B id="j7pp569">return</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp570"> session.createCriteria(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp571"><B id="j7pp572">specificationCriteria.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp573">getPersistentClass());<BR id="j7pp574"></SPAN><SPAN style="color: #800000" id="j7pp575"> 33 </SPAN><SPAN style="background-color: #ffffff" id="j7pp576"> }<BR id="j7pp577"></SPAN><SPAN style="color: #800000" id="j7pp578"> 34 </SPAN><SPAN style="background-color: #ffffff" id="j7pp579"> });<BR id="j7pp580"></SPAN><SPAN style="color: #800000" id="j7pp581"> 35 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp582"><B id="j7pp583">return</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp584"> criteria;<BR id="j7pp585"></SPAN><SPAN style="color: #800000" id="j7pp586"> 36 </SPAN><SPAN style="background-color: #ffffff" id="j7pp587"> }<BR id="j7pp588"></SPAN><SPAN style="color: #800000" id="j7pp589"> 37 <BR id="j7pp590"> 38 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp591"><B id="j7pp592">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp593"><B id="j7pp594">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp595"> PagedIterator </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp596"><B id="j7pp597">implements</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp598"> Iterator {<BR id="j7pp599"></SPAN><SPAN style="color: #800000" id="j7pp600"> 39 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp601"><B id="j7pp602">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp603"><B id="j7pp604">boolean</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp605"><B id="j7pp606">lastPage </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp607">= </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp608"><B id="j7pp609">false</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp610">;<BR id="j7pp611"></SPAN><SPAN style="color: #800000" id="j7pp612"> 40 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp613"><B id="j7pp614">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp615"><B id="j7pp616">int</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp617"><B id="j7pp618">offset;<BR id="j7pp619"></B></SPAN><SPAN style="color: #800000" id="j7pp620"> 41 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp621"><B id="j7pp622">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp623"> List </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp624"><B id="j7pp625">currentCollection;<BR id="j7pp626"></B></SPAN><SPAN style="color: #800000" id="j7pp627"> 42 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp628"><B id="j7pp629">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp630"> Iterator </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp631"><B id="j7pp632">currentIterator;<BR id="j7pp633"></B></SPAN><SPAN style="color: #800000" id="j7pp634"> 43 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp635"><B id="j7pp636">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp637"><B id="j7pp638">int</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp639"><B id="j7pp640">size;<BR id="j7pp641"></B></SPAN><SPAN style="color: #800000" id="j7pp642"> 44 <BR id="j7pp643"> 45 <BR id="j7pp644"> 46 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp645"><B id="j7pp646">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp647"> PagedIterator(</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp648"><B id="j7pp649">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp650"> size) {<BR id="j7pp651"></SPAN><SPAN style="color: #800000" id="j7pp652"> 47 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp653"><B id="j7pp654">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp655">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp656"><B id="j7pp657">size </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp658">= size;<BR id="j7pp659"></SPAN><SPAN style="color: #800000" id="j7pp660"> 48 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp661"><B id="j7pp662">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp663">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp664"><B id="j7pp665">currentCollection </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp666">= loadPage(</SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp667">0</SPAN><SPAN style="background-color: #ffffff" id="j7pp668">);<BR id="j7pp669"></SPAN><SPAN style="color: #800000" id="j7pp670"> 49 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp671"><B id="j7pp672">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp673">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp674"><B id="j7pp675">currentIterator </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp676">= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp677"><B id="j7pp678">currentCollection.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp679">iterator();<BR id="j7pp680"></SPAN><SPAN style="color: #800000" id="j7pp681"> 50 </SPAN><SPAN style="background-color: #ffffff" id="j7pp682"> }<BR id="j7pp683"></SPAN><SPAN style="color: #800000" id="j7pp684"> 51 <BR id="j7pp685"> 52 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp686"><B id="j7pp687">protected</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp688"> List loadPage(</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp689"><B id="j7pp690">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp691"> offset) {<BR id="j7pp692"></SPAN><SPAN style="color: #800000" id="j7pp693"> 53 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp694"><B id="j7pp695">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp696"> (offset > </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp697"><B id="j7pp698">size)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp699"> {<BR id="j7pp700"></SPAN><SPAN style="color: #800000" id="j7pp701"> 54 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp702"><B id="j7pp703">throw</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp704"><B id="j7pp705">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp706"> NoSuchElementException();<BR id="j7pp707"></SPAN><SPAN style="color: #800000" id="j7pp708"> 55 </SPAN><SPAN style="background-color: #ffffff" id="j7pp709"> }<BR id="j7pp710"></SPAN><SPAN style="color: #800000" id="j7pp711"> 56 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp712"><B id="j7pp713">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp714">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp715"><B id="j7pp716">offset </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp717">= offset;<BR id="j7pp718"></SPAN><SPAN style="color: #800000" id="j7pp719"> 57 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp720"><B id="j7pp721">queryCriteria.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp722">setFirstResult(offset);<BR id="j7pp723"></SPAN><SPAN style="color: #800000" id="j7pp724"> 58 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp725"><B id="j7pp726">queryCriteria.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp727">setMaxResults(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp728"><B id="j7pp729">pageSize)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp730">;<BR id="j7pp731"></SPAN><SPAN style="color: #800000" id="j7pp732"> 59 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp733"><B id="j7pp734">currentCollection </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp735">= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp736"><B id="j7pp737">queryCriteria.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp738">list();<BR id="j7pp739"></SPAN><SPAN style="color: #800000" id="j7pp740"> 60 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp741"><B id="j7pp742">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp743"> ( (</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp744"><B id="j7pp745">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp746">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp747"><B id="j7pp748">offset </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp749">+ </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp750"><B id="j7pp751">pageSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp752">)>= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp753"><B id="j7pp754">size)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp755"> {<BR id="j7pp756"></SPAN><SPAN style="color: #800000" id="j7pp757"> 61 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp758"><B id="j7pp759">lastPage </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp760">= </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp761"><B id="j7pp762">true</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp763">;<BR id="j7pp764"></SPAN><SPAN style="color: #800000" id="j7pp765"> 62 </SPAN><SPAN style="background-color: #ffffff" id="j7pp766"> }<BR id="j7pp767"></SPAN><SPAN style="color: #800000" id="j7pp768"> 63 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp769"><B id="j7pp770">return</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp771"><B id="j7pp772">currentCollection;<BR id="j7pp773"></B></SPAN><SPAN style="color: #800000" id="j7pp774"> 64 </SPAN><SPAN style="background-color: #ffffff" id="j7pp775"> }<BR id="j7pp776"></SPAN><SPAN style="color: #800000" id="j7pp777"> 65 <BR id="j7pp778"> 66 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp779"><B id="j7pp780">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp781"><B id="j7pp782">boolean</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp783"> hasNext() {<BR id="j7pp784"></SPAN><SPAN style="color: #800000" id="j7pp785"> 67 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp786"><B id="j7pp787">return</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp788"> size() > </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp789">0</SPAN><SPAN style="background-color: #ffffff" id="j7pp790"> && (</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp791"><B id="j7pp792">currentIterator.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp793">hasNext() || !</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp794"><B id="j7pp795">lastPage)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp796">;<BR id="j7pp797"></SPAN><SPAN style="color: #800000" id="j7pp798"> 68 </SPAN><SPAN style="background-color: #ffffff" id="j7pp799"> }<BR id="j7pp800"></SPAN><SPAN style="color: #800000" id="j7pp801"> 69 <BR id="j7pp802"> 70 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp803"><B id="j7pp804">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp805"> Object next() {<BR id="j7pp806"></SPAN><SPAN style="color: #800000" id="j7pp807"> 71 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp808"><B id="j7pp809">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp810"> (!</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp811"><B id="j7pp812">currentIterator.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp813">hasNext()) {<BR id="j7pp814"></SPAN><SPAN style="color: #800000" id="j7pp815"> 72 </SPAN><SPAN style="background-color: #ffffff" id="j7pp816"> unloadPage(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp817"><B id="j7pp818">currentCollection)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp819">;<BR id="j7pp820"></SPAN><SPAN style="color: #800000" id="j7pp821"> 73 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp822"><B id="j7pp823">currentCollection </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp824">= loadPage(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp825"><B id="j7pp826">offset </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp827">+ </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp828"><B id="j7pp829">pageSize)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp830">;<BR id="j7pp831"></SPAN><SPAN style="color: #800000" id="j7pp832"> 74 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp833"><B id="j7pp834">currentIterator </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp835">= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp836"><B id="j7pp837">currentCollection.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp838">iterator();<BR id="j7pp839"></SPAN><SPAN style="color: #800000" id="j7pp840"> 75 </SPAN><SPAN style="background-color: #ffffff" id="j7pp841"> }<BR id="j7pp842"></SPAN><SPAN style="color: #800000" id="j7pp843"> 76 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp844"><B id="j7pp845">return</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp846"><B id="j7pp847">currentIterator.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp848">next();<BR id="j7pp849"></SPAN><SPAN style="color: #800000" id="j7pp850"> 77 </SPAN><SPAN style="background-color: #ffffff" id="j7pp851"> }<BR id="j7pp852"></SPAN><SPAN style="color: #800000" id="j7pp853"> 78 <BR id="j7pp854"> 79 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp855"><B id="j7pp856">protected</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp857"><B id="j7pp858">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp859"> unloadPage(List currentCollection) {<BR id="j7pp860"></SPAN><SPAN style="color: #800000" id="j7pp861"> 80 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp862"><B id="j7pp863">for</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp864"> (Object o : currentCollection) {<BR id="j7pp865"></SPAN><SPAN style="color: #800000" id="j7pp866"> 81 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp867"><B id="j7pp868">hibernateTemplate.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp869">evict(o);<BR id="j7pp870"></SPAN><SPAN style="color: #800000" id="j7pp871"> 82 </SPAN><SPAN style="background-color: #ffffff" id="j7pp872"> }<BR id="j7pp873"></SPAN><SPAN style="color: #800000" id="j7pp874"> 83 </SPAN><SPAN style="background-color: #ffffff" id="j7pp875"> }<BR id="j7pp876"></SPAN><SPAN style="color: #800000" id="j7pp877"> 84 <BR id="j7pp878"> 85 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp879"><B id="j7pp880">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp881"><B id="j7pp882">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp883"> remove() {<BR id="j7pp884"></SPAN><SPAN style="color: #800000" id="j7pp885"> 86 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp886"><B id="j7pp887">throw</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp888"><B id="j7pp889">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp890"> UnsupportedOperationException();<BR id="j7pp891"></SPAN><SPAN style="color: #800000" id="j7pp892"> 87 </SPAN><SPAN style="background-color: #ffffff" id="j7pp893"> }<BR id="j7pp894"></SPAN><SPAN style="color: #800000" id="j7pp895"> 88 </SPAN><SPAN style="background-color: #ffffff" id="j7pp896"> }<BR id="j7pp897"></SPAN><SPAN style="color: #800000" id="j7pp898"> 89 </SPAN><SPAN style="background-color: #ffffff" id="j7pp899">}</SPAN></PRE><B id="j7pp900">Listing 8<BR id="j7pp901"><BR id="j7pp902"></B> The test case looks as follows, note that we have to iterate the entire set if we want to poll everything out from the database. The<SPAN style='font-family: "Courier New"' id="j7pp903"> size() </SPAN>method just returns an aggregated value by issuing a count.<BR id="j7pp904"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp905"><SPAN style="color: #800000" id="j7pp906"> 1 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp907"><B id="j7pp908">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp909"><B id="j7pp910">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp911"> testRetrieveOrderLinesUsingPaging() {<BR id="j7pp912"></SPAN><SPAN style="color: #800000" id="j7pp913"> 2 </SPAN><SPAN style="background-color: #ffffff" id="j7pp914"> Order order = (Order) </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp915"><B id="j7pp916">hibernateTemplate.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp917">get(Order.</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp918"><B id="j7pp919">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp920">, </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp921"><B id="j7pp922">orderId)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp923">;<BR id="j7pp924"></SPAN><SPAN style="color: #800000" id="j7pp925"> 3 </SPAN><SPAN style="background-color: #ffffff" id="j7pp926"> Collection orderLines = order.getOrderLines(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp927"><B id="j7pp928">hibernateTemplate,</B></SPAN> <SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp929">50000</SPAN><SPAN style="background-color: #ffffff" id="j7pp930">);<BR id="j7pp931"></SPAN><SPAN style="color: #800000" id="j7pp932"> 4 <BR id="j7pp933"> 5 </SPAN><SPAN style="background-color: #ffffff" id="j7pp934"> ResourceMonitor monitor = </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp935"><B id="j7pp936">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp937"> ResourceMonitor(</SPAN><SPAN style="color: #008000; background-color: #ffffff" id="j7pp938"><B id="j7pp939">"order.getOrderLines()"</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp940">);<BR id="j7pp941"></SPAN><SPAN style="color: #800000" id="j7pp942"> 6 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp943"><B id="j7pp944">for</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp945"> (Object orderLine : orderLines) {<BR id="j7pp946"></SPAN><SPAN style="color: #800000" id="j7pp947"> 7 </SPAN> <SPAN style="color: #808080; background-color: #ffffff" id="j7pp948"><I id="j7pp949">//<BR id="j7pp950"></I></SPAN><SPAN style="color: #800000" id="j7pp951"> 8 </SPAN><SPAN style="background-color: #ffffff" id="j7pp952"> OrderLine line = (OrderLine) orderLine;<BR id="j7pp953"></SPAN><SPAN style="color: #800000" id="j7pp954"> 9 </SPAN><SPAN style="background-color: #ffffff" id="j7pp955"> }<BR id="j7pp956"></SPAN><SPAN style="color: #800000" id="j7pp957"> 10 </SPAN> <SPAN style="background-color: #ffffff" id="j7pp958"><I id="j7pp959">assertEquals(</I></SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp960">1000</SPAN><SPAN style="background-color: #ffffff" id="j7pp961"> * </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp962">1000</SPAN><SPAN style="background-color: #ffffff" id="j7pp963">, orderLines.size());<BR id="j7pp964"></SPAN><SPAN style="color: #800000" id="j7pp965"> 11 </SPAN><SPAN style="background-color: #ffffff" id="j7pp966"> monitor.stop();<BR id="j7pp967"></SPAN><SPAN style="color: #800000" id="j7pp968"> 12 </SPAN><SPAN style="background-color: #ffffff" id="j7pp969"> System.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp970"><B id="j7pp971"><I id="j7pp972">out.</I></B></SPAN><SPAN style="background-color: #ffffff" id="j7pp973">println(monitor);<BR id="j7pp974"></SPAN><SPAN style="color: #800000" id="j7pp975"> 13 <BR id="j7pp976"> 14 </SPAN><SPAN style="background-color: #ffffff" id="j7pp977"> }</SPAN></PRE><B id="j7pp978">Listing 9<BR id="j7pp979"><BR id="j7pp980"></B> Without tuning the underlying database with respect to query optimization, the test result looks like this:<BR id="j7pp981"><DIV id="j7pp982"><TABLE border="2" cellpadding="3" cellspacing="0" id="j7pp983"><TBODY id="j7pp984"><TR id="j7pp985"><TD width="50%" id="j7pp986"><B id="j7pp987">Time elapsed</B><BR id="j7pp988"></TD><TD width="50%" id="j7pp989"><B id="j7pp990">Memory usage delta</B><BR id="j7pp991"></TD></TR><TR id="j7pp992"><TD width="50%" id="j7pp993"> 381s<BR id="j7pp994"></TD><TD width="50%" id="j7pp995"> 29791kb<BR id="j7pp996"></TD></TR></TBODY></TABLE><B id="j7pp997">Table 2 Test result using setFirstResult/setMaxResult<BR id="j7pp998"><BR id="j7pp999"></B>Note that the footprint is reduced to below one tenth, but the response-time is not satisfactory. In this case a new query will be issued across each page boundary, in this case each page being 50.000 elements. It turns out that executing the SQL to retrieve one single page is almost as expensive as retrieving all rows in a single select. To understand why, we have to examine the SQL.<BR id="j7pp1000"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp1001"><SPAN style="color: #800000" id="j7pp1002"> 1 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1003">SELECT *<BR id="j7pp1004"></SPAN><SPAN style="color: #800000" id="j7pp1005"> 2 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1006">FROM<BR id="j7pp1007"></SPAN><SPAN style="color: #800000" id="j7pp1008"> 3 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1009"> (SELECT row_.*</SPAN><SPAN style="color: #000000; background-color: #ffffff" id="j7pp1010">,<BR id="j7pp1011"></SPAN><SPAN style="color: #800000" id="j7pp1012"> 4 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1013"> rownum rownum_<BR id="j7pp1014"></SPAN><SPAN style="color: #800000" id="j7pp1015"> 5 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1016"> FROM<BR id="j7pp1017"></SPAN><SPAN style="color: #800000" id="j7pp1018"> 6 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1019"> (SELECT * <BR id="j7pp1020"></SPAN><SPAN style="color: #800000" id="j7pp1021"> 7 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1022"> FROM orderline o<BR id="j7pp1023"></SPAN><SPAN style="color: #800000" id="j7pp1024"> 8 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1025"> WHERE o.order_id = order2_.id)<BR id="j7pp1026"></SPAN><SPAN style="color: #800000" id="j7pp1027"> 9 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1028"> FROM orderline this_ LEFT<BR id="j7pp1029"></SPAN><SPAN style="color: #800000" id="j7pp1030">10 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1031"> OUTER JOIN customer_order order2_ ON this_.order_id = order2_.id LEFT<BR id="j7pp1032"></SPAN><SPAN style="color: #800000" id="j7pp1033">11 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1034"> WHERE this_.order_id = </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp1035">10</SPAN><SPAN style="background-color: #ffffff" id="j7pp1036">)<BR id="j7pp1037"></SPAN><SPAN style="color: #800000" id="j7pp1038">12 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1039"> row_<BR id="j7pp1040"></SPAN><SPAN style="color: #800000" id="j7pp1041">13 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1042"> WHERE rownum <= </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp1043">100000</SPAN><SPAN style="background-color: #ffffff" id="j7pp1044">)<BR id="j7pp1045"></SPAN><SPAN style="color: #800000" id="j7pp1046">14 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1047">WHERE rownum_ > </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp1048">50000</SPAN><SPAN style="color: #000000; background-color: #ffffff" id="j7pp1049">;</SPAN></PRE><B id="j7pp1050">Listing 10<BR id="j7pp1051"></B><BR id="j7pp1052"> The SQL in listing 10 has been simplified from what Hibernate generates, but the most important attribute is the nested select with the rownum-restriction, which is shown. The query above will retrieve the second page in the select, the rows ranging from 50000 to 100000. Note the nested query where the first (innermost) select will return all rows with a rownum less than 100000. This is followed by a filter on the inner result, returning only the rows counting from 50000 and above. This means that the RDBMS will actually read and throw away most of the rows for each query. For this to be implemented consistently, we also need to make sure that the same select will return the same rows repeatedly. This can only be done if we add an order by clause to the select above (which is not included in this case). See <A href="View?docid=dcs9tn98_8hpc5kc#rownum" title="[3]" id="j7pp1053">[3]</A> for a discussion on how rownum works in Oracle.<BR id="j7pp1054"><BR id="j7pp1055"> Using this approach for large results will effectively use up all your database resources.<BR id="j7pp1056"></DIV><H2 id="j7pp1057"> Using ScrollableResults </H2> The approach that uses <SPAN style='font-family: "Courier New"' id="j7pp1058">ScrollableReults</SPAN> relies on the underlying JDBC-driver providing support for some kind of cursor that may allow you to retrieve data in an incremental manner without keeping everything in memory. A<SPAN style='font-family: "Courier New"' id="j7pp1059"> ScrollableResults </SPAN>can beretrieved from a Criteria implementation by using one of the <SPAN style='font-family: "Courier New"' id="j7pp1060">Criteria.scroll</SPAN>(..) methods.Support for this may vary. Old versions of the JDBC-drivers in Oracle has implemented this as a client side cache that keeps everything in memory.Whereas newer-versions implements this using server-side cursors.<BR id="j7pp1061"><BR id="j7pp1062"> The implementation that uses the<SPAN style='font-family: "Courier New"' id="j7pp1063"> ScrollableResult </SPAN>is straightforward. The <SPAN style='font-family: "Courier New"' id="j7pp1064">CollectionBuilder </SPAN>implementation is shown in Listing 11 and the actual Collection implementation in Listing 12.<BR id="j7pp1065"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp1066"><SPAN style="color: #800000" id="j7pp1067"> 1 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1068"><B id="j7pp1069">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1070"><B id="j7pp1071">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1072"> OrderLineScrolleableResultSetCollectionBuilder </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1073"><B id="j7pp1074">implements</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1075"> CollectionBuilder {<BR id="j7pp1076"></SPAN><SPAN style="color: #800000" id="j7pp1077"> 2 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1078"><B id="j7pp1079">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1080"> HibernateTemplate </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1081"><B id="j7pp1082">hibernateTemplate;<BR id="j7pp1083"></B></SPAN><SPAN style="color: #800000" id="j7pp1084"> 3 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1085"><B id="j7pp1086">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1087"><B id="j7pp1088">int</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1089"><B id="j7pp1090">pageSize;<BR id="j7pp1091"></B></SPAN><SPAN style="color: #800000" id="j7pp1092"> 4 <BR id="j7pp1093"> 5 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1094"><B id="j7pp1095">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1096"> OrderLineScrolleableResultSetCollectionBuilder(HibernateTemplate hibernateTemplate, </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1097"><B id="j7pp1098">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1099"> pageSize) {<BR id="j7pp1100"></SPAN><SPAN style="color: #800000" id="j7pp1101"> 6 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1102"><B id="j7pp1103">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1104">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1105"><B id="j7pp1106">hibernateTemplate </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1107">= hibernateTemplate;<BR id="j7pp1108"></SPAN><SPAN style="color: #800000" id="j7pp1109"> 7 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1110"><B id="j7pp1111">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1112">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1113"><B id="j7pp1114">pageSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1115">= pageSize;<BR id="j7pp1116"></SPAN><SPAN style="color: #800000" id="j7pp1117"> 8 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1118"> }<BR id="j7pp1119"></SPAN><SPAN style="color: #800000" id="j7pp1120"> 9 <BR id="j7pp1121">10 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1122"><B id="j7pp1123">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1124"> Collection build(Object instance) {<BR id="j7pp1125"></SPAN><SPAN style="color: #800000" id="j7pp1126">11 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1127"> Order order = (Order) instance;<BR id="j7pp1128"></SPAN><SPAN style="color: #800000" id="j7pp1129">12 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1130"><B id="j7pp1131">return</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1132"><B id="j7pp1133">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1134"> ScrollableResultsCollection(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1135"><B id="j7pp1136">hibernateTemplate,</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1137"><B id="j7pp1138">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1139"> HibernateCriteriaSpecification(OrderLine.</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1140"><B id="j7pp1141">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1142">, order, </SPAN><SPAN style="color: #008000; background-color: #ffffff" id="j7pp1143"><B id="j7pp1144">"order"</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1145">), </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1146"><B id="j7pp1147">pageSize)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1148">;<BR id="j7pp1149"></SPAN><SPAN style="color: #800000" id="j7pp1150">13 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1151"> }<BR id="j7pp1152"></SPAN><SPAN style="color: #800000" id="j7pp1153">14 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1154">}<BR id="j7pp1155"></SPAN><SPAN style="color: #800000" id="j7pp1156">15 </SPAN></PRE><B id="j7pp1157">Listing 11<BR id="j7pp1158"></B><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp1159"><SPAN style="color: #800000" id="j7pp1160"> 1 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1161"><B id="j7pp1162">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1163"><B id="j7pp1164">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1165"> ScrollableResultsCollection </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1166"><B id="j7pp1167">extends</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1168"> AbstractCollection {<BR id="j7pp1169"></SPAN><SPAN style="color: #800000" id="j7pp1170"> 2 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1171"><B id="j7pp1172">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1173"> HibernateTemplate </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1174"><B id="j7pp1175">hibernateTemplate;<BR id="j7pp1176"></B></SPAN><SPAN style="color: #800000" id="j7pp1177"> 3 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1178"><B id="j7pp1179">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1180"> HibernateCriteriaSpecification </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1181"><B id="j7pp1182">specificationCriteria;<BR id="j7pp1183"></B></SPAN><SPAN style="color: #800000" id="j7pp1184"> 4 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1185"><B id="j7pp1186">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1187"><B id="j7pp1188">int</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1189"><B id="j7pp1190">pageSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1191">= </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp1192">2000</SPAN><SPAN style="background-color: #ffffff" id="j7pp1193">;<BR id="j7pp1194"></SPAN><SPAN style="color: #800000" id="j7pp1195"> 5 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1196"><B id="j7pp1197">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1198"> Integer </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1199"><B id="j7pp1200">collectionSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1201">= </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1202"><B id="j7pp1203">null</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1204">;<BR id="j7pp1205"></SPAN><SPAN style="color: #800000" id="j7pp1206"> 6 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1207"><B id="j7pp1208">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1209"> Criteria </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1210"><B id="j7pp1211">queryCriteria;<BR id="j7pp1212"></B></SPAN><SPAN style="color: #800000" id="j7pp1213"> 7 <BR id="j7pp1214"> 8 <BR id="j7pp1215"> 9 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1216"><B id="j7pp1217">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1218"> ScrollableResultsCollection(HibernateTemplate hibernateTemplate, HibernateCriteriaSpecification criteria, </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1219"><B id="j7pp1220">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1221"> pageSize) {<BR id="j7pp1222"></SPAN><SPAN style="color: #800000" id="j7pp1223"> 10 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1224"><B id="j7pp1225">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1226">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1227"><B id="j7pp1228">specificationCriteria </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1229">= criteria;<BR id="j7pp1230"></SPAN><SPAN style="color: #800000" id="j7pp1231"> 11 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1232"><B id="j7pp1233">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1234">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1235"><B id="j7pp1236">hibernateTemplate </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1237">= hibernateTemplate;<BR id="j7pp1238"></SPAN><SPAN style="color: #800000" id="j7pp1239"> 12 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1240"><B id="j7pp1241">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1242">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1243"><B id="j7pp1244">pageSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1245">= pageSize;<BR id="j7pp1246"></SPAN><SPAN style="color: #800000" id="j7pp1247"> 13 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1248"><B id="j7pp1249">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1250">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1251"><B id="j7pp1252">queryCriteria </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1253">= criteria.populate(createCriteria());<BR id="j7pp1254"></SPAN><SPAN style="color: #800000" id="j7pp1255"> 14 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1256"> }<BR id="j7pp1257"></SPAN><SPAN style="color: #800000" id="j7pp1258"> 15 <BR id="j7pp1259"> 16 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1260"><B id="j7pp1261">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1262"> Iterator iterator() {<BR id="j7pp1263"></SPAN><SPAN style="color: #800000" id="j7pp1264"> 17 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1265"><B id="j7pp1266">return</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1267"><B id="j7pp1268">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1269"> PagedIterator(size());<BR id="j7pp1270"></SPAN><SPAN style="color: #800000" id="j7pp1271"> 18 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1272"> }<BR id="j7pp1273"></SPAN><SPAN style="color: #800000" id="j7pp1274"> 19 <BR id="j7pp1275"> 20 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1276"><B id="j7pp1277">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1278"><B id="j7pp1279">synchronized</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1280"><B id="j7pp1281">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1282"> size() {<BR id="j7pp1283"></SPAN><SPAN style="color: #800000" id="j7pp1284"> 21 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1285"><B id="j7pp1286">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1287"> (</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1288"><B id="j7pp1289">collectionSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1290">== </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1291"><B id="j7pp1292">null</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1293">) {<BR id="j7pp1294"></SPAN><SPAN style="color: #800000" id="j7pp1295"> 22 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1296"> Criteria criteria = </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1297"><B id="j7pp1298">specificationCriteria.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1299">populate(createCriteria());<BR id="j7pp1300"></SPAN><SPAN style="color: #800000" id="j7pp1301"> 23 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1302"> criteria.setProjection(Projections.</SPAN><SPAN style="background-color: #ffffff" id="j7pp1303"><I id="j7pp1304">countDistinct(</I></SPAN><SPAN style="color: #008000; background-color: #ffffff" id="j7pp1305"><B id="j7pp1306">"id"</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1307">));<BR id="j7pp1308"></SPAN><SPAN style="color: #800000" id="j7pp1309"> 24 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1310"><B id="j7pp1311">collectionSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1312">= (Integer) criteria.uniqueResult();<BR id="j7pp1313"></SPAN><SPAN style="color: #800000" id="j7pp1314"> 25 <BR id="j7pp1315"> 26 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1316"> }<BR id="j7pp1317"></SPAN><SPAN style="color: #800000" id="j7pp1318"> 27 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1319"><B id="j7pp1320">return</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1321"><B id="j7pp1322">collectionSize;<BR id="j7pp1323"></B></SPAN><SPAN style="color: #800000" id="j7pp1324"> 28 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1325"> }<BR id="j7pp1326"></SPAN><SPAN style="color: #800000" id="j7pp1327"> 29 <BR id="j7pp1328"> 30 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1329"><B id="j7pp1330">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1331"> Criteria createCriteria() {<BR id="j7pp1332"></SPAN><SPAN style="color: #800000" id="j7pp1333"> 31 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1334"> Criteria criteria = (Criteria) </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1335"><B id="j7pp1336">hibernateTemplate.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1337">execute(</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1338"><B id="j7pp1339">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1340"> HibernateCallback() {<BR id="j7pp1341"></SPAN><SPAN style="color: #800000" id="j7pp1342"> 32 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1343"><B id="j7pp1344">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1345"> Object doInHibernate(Session session) </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1346"><B id="j7pp1347">throws</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1348"> HibernateException, SQLException {<BR id="j7pp1349"></SPAN><SPAN style="color: #800000" id="j7pp1350"> 33 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1351"><B id="j7pp1352">return</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1353"> session.createCriteria(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1354"><B id="j7pp1355">specificationCriteria.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1356">getPersistentClass());<BR id="j7pp1357"></SPAN><SPAN style="color: #800000" id="j7pp1358"> 34 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1359"> }<BR id="j7pp1360"></SPAN><SPAN style="color: #800000" id="j7pp1361"> 35 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1362"> });<BR id="j7pp1363"></SPAN><SPAN style="color: #800000" id="j7pp1364"> 36 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1365"><B id="j7pp1366">return</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1367"> criteria;<BR id="j7pp1368"></SPAN><SPAN style="color: #800000" id="j7pp1369"> 37 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1370"> }<BR id="j7pp1371"></SPAN><SPAN style="color: #800000" id="j7pp1372"> 38 <BR id="j7pp1373"> 39 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1374"><B id="j7pp1375">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1376"><B id="j7pp1377">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1378"> PagedIterator </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1379"><B id="j7pp1380">implements</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1381"> Iterator {<BR id="j7pp1382"></SPAN><SPAN style="color: #800000" id="j7pp1383"> 40 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1384"><B id="j7pp1385">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1386"><B id="j7pp1387">boolean</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1388"><B id="j7pp1389">lastPage </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1390">= </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1391"><B id="j7pp1392">false</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1393">;<BR id="j7pp1394"></SPAN><SPAN style="color: #800000" id="j7pp1395"> 41 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1396"><B id="j7pp1397">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1398"><B id="j7pp1399">int</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1400"><B id="j7pp1401">offset;<BR id="j7pp1402"></B></SPAN><SPAN style="color: #800000" id="j7pp1403"> 42 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1404"><B id="j7pp1405">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1406"> List </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1407"><B id="j7pp1408">currentCollection;<BR id="j7pp1409"></B></SPAN><SPAN style="color: #800000" id="j7pp1410"> 43 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1411"><B id="j7pp1412">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1413"> Iterator </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1414"><B id="j7pp1415">currentIterator;<BR id="j7pp1416"></B></SPAN><SPAN style="color: #800000" id="j7pp1417"> 44 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1418"><B id="j7pp1419">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1420"><B id="j7pp1421">int</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1422"><B id="j7pp1423">size;<BR id="j7pp1424"></B></SPAN><SPAN style="color: #800000" id="j7pp1425"> 45 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1426"><B id="j7pp1427">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1428"> ScrollableResults </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1429"><B id="j7pp1430">scrollebleResults;<BR id="j7pp1431"></B></SPAN><SPAN style="color: #800000" id="j7pp1432"> 46 <BR id="j7pp1433"> 47 <BR id="j7pp1434"> 48 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1435"><B id="j7pp1436">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1437"> PagedIterator(</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1438"><B id="j7pp1439">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1440"> size) {<BR id="j7pp1441"></SPAN><SPAN style="color: #800000" id="j7pp1442"> 49 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1443"><B id="j7pp1444">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1445">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1446"><B id="j7pp1447">size </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1448">= size;<BR id="j7pp1449"></SPAN><SPAN style="color: #800000" id="j7pp1450"> 50 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1451"><B id="j7pp1452">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1453">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1454"><B id="j7pp1455">scrollebleResults </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1456">= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1457"><B id="j7pp1458">queryCriteria.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1459">scroll(ScrollMode.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1460"><B id="j7pp1461"><I id="j7pp1462">FORWARD_ONLY)</I></B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1463">;<BR id="j7pp1464"></SPAN><SPAN style="color: #800000" id="j7pp1465"> 51 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1466"><B id="j7pp1467">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1468">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1469"><B id="j7pp1470">currentCollection </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1471">= loadPage(</SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp1472">0</SPAN><SPAN style="background-color: #ffffff" id="j7pp1473">);<BR id="j7pp1474"></SPAN><SPAN style="color: #800000" id="j7pp1475"> 52 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1476"><B id="j7pp1477">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1478">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1479"><B id="j7pp1480">currentIterator </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1481">= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1482"><B id="j7pp1483">currentCollection.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1484">iterator();<BR id="j7pp1485"></SPAN><SPAN style="color: #800000" id="j7pp1486"> 53 <BR id="j7pp1487"> 54 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1488"> }<BR id="j7pp1489"></SPAN><SPAN style="color: #800000" id="j7pp1490"> 55 <BR id="j7pp1491"> 56 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1492"><B id="j7pp1493">protected</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1494"> List loadPage(</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1495"><B id="j7pp1496">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1497"> offset) {<BR id="j7pp1498"></SPAN><SPAN style="color: #800000" id="j7pp1499"> 57 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1500"><B id="j7pp1501">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1502"> (offset > </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1503"><B id="j7pp1504">size)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1505"> {<BR id="j7pp1506"></SPAN><SPAN style="color: #800000" id="j7pp1507"> 58 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1508"><B id="j7pp1509">throw</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1510"><B id="j7pp1511">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1512"> NoSuchElementException();<BR id="j7pp1513"></SPAN><SPAN style="color: #800000" id="j7pp1514"> 59 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1515"> }<BR id="j7pp1516"></SPAN><SPAN style="color: #800000" id="j7pp1517"> 60 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1518"><B id="j7pp1519">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1520">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1521"><B id="j7pp1522">offset </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1523">= offset;<BR id="j7pp1524"></SPAN><SPAN style="color: #800000" id="j7pp1525"> 61 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1526"><B id="j7pp1527">currentCollection </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1528">= </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1529"><B id="j7pp1530">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1531"> ArrayList(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1532"><B id="j7pp1533">pageSize)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1534">;<BR id="j7pp1535"></SPAN><SPAN style="color: #800000" id="j7pp1536"> 62 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1537"> System.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1538"><B id="j7pp1539"><I id="j7pp1540">out.</I></B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1541">println(</SPAN><SPAN style="color: #008000; background-color: #ffffff" id="j7pp1542"><B id="j7pp1543">"Loading offset ["</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1544">+offset+</SPAN><SPAN style="color: #008000; background-color: #ffffff" id="j7pp1545"><B id="j7pp1546">"]"</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1547">);<BR id="j7pp1548"></SPAN><SPAN style="color: #800000" id="j7pp1549"> 63 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1550"><B id="j7pp1551">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1552"> ((</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1553"><B id="j7pp1554">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1555">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1556"><B id="j7pp1557">offset </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1558">+ </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1559"><B id="j7pp1560">pageSize)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1561"> >= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1562"><B id="j7pp1563">size)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1564"> {<BR id="j7pp1565"></SPAN><SPAN style="color: #800000" id="j7pp1566"> 64 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1567"><B id="j7pp1568">lastPage </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1569">= </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1570"><B id="j7pp1571">true</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1572">;<BR id="j7pp1573"></SPAN><SPAN style="color: #800000" id="j7pp1574"> 65 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1575"> }<BR id="j7pp1576"></SPAN><SPAN style="color: #800000" id="j7pp1577"> 66 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1578"><B id="j7pp1579">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1580"> scrollSize = </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1581"><B id="j7pp1582">lastPage </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1583">? </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1584"><B id="j7pp1585">size </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1586">- offset: </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1587"><B id="j7pp1588">pageSize;<BR id="j7pp1589"></B></SPAN><SPAN style="color: #800000" id="j7pp1590"> 67 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1591"><B id="j7pp1592">for</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1593"> (</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1594"><B id="j7pp1595">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1596"> i = </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp1597">0</SPAN><SPAN style="background-color: #ffffff" id="j7pp1598">; i < scrollSize; i++) {<BR id="j7pp1599"></SPAN><SPAN style="color: #800000" id="j7pp1600"> 68 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1601"><B id="j7pp1602">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1603"> (!</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1604"><B id="j7pp1605">scrollebleResults.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1606">next()) {<BR id="j7pp1607"></SPAN><SPAN style="color: #800000" id="j7pp1608"> 69 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1609"><B id="j7pp1610">throw</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1611"><B id="j7pp1612">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1613"> NoSuchElementException();<BR id="j7pp1614"></SPAN><SPAN style="color: #800000" id="j7pp1615"> 70 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1616"> }<BR id="j7pp1617"></SPAN><SPAN style="color: #800000" id="j7pp1618"> 71 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1619"><B id="j7pp1620">currentCollection.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1621">add(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1622"><B id="j7pp1623">scrollebleResults.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1624">get(</SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp1625">0</SPAN><SPAN style="background-color: #ffffff" id="j7pp1626">));<BR id="j7pp1627"></SPAN><SPAN style="color: #800000" id="j7pp1628"> 72 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1629"> }<BR id="j7pp1630"></SPAN><SPAN style="color: #800000" id="j7pp1631"> 73 <BR id="j7pp1632"> 74 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1633"><B id="j7pp1634">currentIterator </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1635">= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1636"><B id="j7pp1637">currentCollection.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1638">iterator();<BR id="j7pp1639"></SPAN><SPAN style="color: #800000" id="j7pp1640"> 75 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1641"><B id="j7pp1642">return</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1643"><B id="j7pp1644">currentCollection;<BR id="j7pp1645"></B></SPAN><SPAN style="color: #800000" id="j7pp1646"> 76 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1647"> }<BR id="j7pp1648"></SPAN><SPAN style="color: #800000" id="j7pp1649"> 77 <BR id="j7pp1650"> 78 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1651"><B id="j7pp1652">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1653"><B id="j7pp1654">boolean</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1655"> hasNext() {<BR id="j7pp1656"></SPAN><SPAN style="color: #800000" id="j7pp1657"> 79 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1658"><B id="j7pp1659">return</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1660"> size() > </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp1661">0</SPAN><SPAN style="background-color: #ffffff" id="j7pp1662"> && (</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1663"><B id="j7pp1664">currentIterator.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1665">hasNext() || !</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1666"><B id="j7pp1667">lastPage)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1668">;<BR id="j7pp1669"></SPAN><SPAN style="color: #800000" id="j7pp1670"> 80 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1671"> }<BR id="j7pp1672"></SPAN><SPAN style="color: #800000" id="j7pp1673"> 81 <BR id="j7pp1674"> 82 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1675"><B id="j7pp1676">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1677"> Object next() {<BR id="j7pp1678"></SPAN><SPAN style="color: #800000" id="j7pp1679"> 83 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1680"><B id="j7pp1681">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1682"> (!</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1683"><B id="j7pp1684">currentIterator.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1685">hasNext()) {<BR id="j7pp1686"></SPAN><SPAN style="color: #800000" id="j7pp1687"> 84 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1688"> unloadPage(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1689"><B id="j7pp1690">currentCollection)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1691">;<BR id="j7pp1692"></SPAN><SPAN style="color: #800000" id="j7pp1693"> 85 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1694"><B id="j7pp1695">currentCollection </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1696">= loadPage(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1697"><B id="j7pp1698">offset </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1699">+ </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1700"><B id="j7pp1701">pageSize)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1702">;<BR id="j7pp1703"></SPAN><SPAN style="color: #800000" id="j7pp1704"> 86 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1705"><B id="j7pp1706">currentIterator </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1707">= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1708"><B id="j7pp1709">currentCollection.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1710">iterator();<BR id="j7pp1711"></SPAN><SPAN style="color: #800000" id="j7pp1712"> 87 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1713"> }<BR id="j7pp1714"></SPAN><SPAN style="color: #800000" id="j7pp1715"> 88 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1716"><B id="j7pp1717">return</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1718"><B id="j7pp1719">currentIterator.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1720">next();<BR id="j7pp1721"></SPAN><SPAN style="color: #800000" id="j7pp1722"> 89 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1723"> }<BR id="j7pp1724"></SPAN><SPAN style="color: #800000" id="j7pp1725"> 90 <BR id="j7pp1726"> 91 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1727"><B id="j7pp1728">protected</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1729"><B id="j7pp1730">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1731"> unloadPage(List currentCollection) {<BR id="j7pp1732"></SPAN><SPAN style="color: #800000" id="j7pp1733"> 92 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1734"><B id="j7pp1735">for</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1736"> (Object o : currentCollection) {<BR id="j7pp1737"></SPAN><SPAN style="color: #800000" id="j7pp1738"> 93 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1739"><B id="j7pp1740">hibernateTemplate.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1741">evict(o);<BR id="j7pp1742"></SPAN><SPAN style="color: #800000" id="j7pp1743"> 94 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1744"> }<BR id="j7pp1745"></SPAN><SPAN style="color: #800000" id="j7pp1746"> 95 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1747"> }<BR id="j7pp1748"></SPAN><SPAN style="color: #800000" id="j7pp1749"> 96 <BR id="j7pp1750"> 97 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1751"><B id="j7pp1752">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1753"><B id="j7pp1754">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1755"> remove() {<BR id="j7pp1756"></SPAN><SPAN style="color: #800000" id="j7pp1757"> 98 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1758"><B id="j7pp1759">throw</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1760"><B id="j7pp1761">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1762"> UnsupportedOperationException();<BR id="j7pp1763"></SPAN><SPAN style="color: #800000" id="j7pp1764"> 99 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1765"> }<BR id="j7pp1766"></SPAN><SPAN style="color: #800000" id="j7pp1767">100 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1768"> }<BR id="j7pp1769"></SPAN><SPAN style="color: #800000" id="j7pp1770">101 </SPAN><SPAN style="background-color: #ffffff" id="j7pp1771">}<BR id="j7pp1772"></SPAN><SPAN style="color: #800000" id="j7pp1773">102 </SPAN></PRE><B id="j7pp1774">Listing 12<BR id="j7pp1775"></B>The <SPAN style='font-family: "Courier New"' id="j7pp1776">ScrollableResults </SPAN>-interface is basically just a low-level approach in mapping row-based data into domain-objects. The instantiated and mapped objects are retrieved using the <SPAN style='font-family: "Courier New"' id="j7pp1777">ScrollableResult.get</SPAN>(..)method. The get-method retrieves objects index from 0. It may be possible to retrieve several objects from a result-set, because hibernate generates queries that provides data for several objects when using outer-join fetching to avoid multiple roundtrips to the database.<BR id="j7pp1778"><BR id="j7pp1779"> Let us say that we extend the model presented in Figure 1 with a one-to-many relation relation to <SPAN style='font-family: "Courier New"' id="j7pp1780">OrderLineDetail</SPAN> as shown in Figure 2.<BR id="j7pp1781"><IMG src="http://docs.google.com/File?id=dcs9tn98_12g6f8vb" style="height: 197px; width: 378px" id="j7pp1782"><BR id="j7pp1783"><B id="j7pp1784">Figure 2<BR id="j7pp1785"><BR id="j7pp1786"></B>In tis case, to get all the data from OrderDetail using one select and outer-join fetching, will make the returned select return four rows in total with the data for OrderLine repeated once for each instance caused by the outer-join with OrderDetail. This means that we lack a layer of abstraction here. We cannot implement this in a generic manner. We will actually have to alter the implementation of the strategy implemented to retrieve <SPAN style='font-family: "Courier New"' id="j7pp1787">OrderLine<SPAN style="font-family: Arial" id="j7pp1788"> instances just because we did a small change to the domain-model, adding the<SPAN style='font-family: "Courier New"' id="j7pp1789"> OrderDetail</SPAN> -relation.</SPAN></SPAN><BR id="j7pp1790"><BR id="j7pp1791"> The <SPAN style='font-family: "Courier New"' id="j7pp1792">ScrollableResults</SPAN> is backed by a ResultSet and needs the connection to be open during the iteration of the query. This will pose some challenges when implementing paging spanning multiple web-requests, typically paging in a web-page, because the ScrollableResult will need to be valid and usable across requests.<BR id="j7pp1793"><BR id="j7pp1794"> Even though the approach is fast and lean on memory as can be seen by looking at the test-results in table 3, these limitations will probably get you in to problems except from in the simplest cases.<BR id="j7pp1795"><BR id="j7pp1796"><DIV id="j7pp1797"><TABLE style="width: 329px; height: 66px" border="1" cellpadding="3" cellspacing="0" id="j7pp1798"><TBODY id="j7pp1799"><TR id="j7pp1800"><TD width="50%" id="j7pp1801"><B id="j7pp1802">Time elapsed</B><BR id="j7pp1803"></TD><TD width="50%" id="j7pp1804"><B id="j7pp1805">Memory usage delta</B><BR id="j7pp1806"></TD></TR><TR id="j7pp1807"><TD width="50%" id="j7pp1808"> 89s<BR id="j7pp1809"></TD><TD width="50%" id="j7pp1810"> 26009<BR id="j7pp1811"></TD></TR></TBODY></TABLE></DIV><BR id="j7pp1812"><B id="j7pp1813">Table 3</B><BR id="j7pp1814"><BR id="j7pp1815"><BR id="j7pp1816"><H2 id="j7pp1817"> The solution </H2> The most effective solution is to use the primary key as a paging criterion.This enables us to rely of first class constructs like a<I id="j7pp1818"> between</I> range query which is simple for the RDBMS to optimize, the primary key of the queried entity will most likely be indexed already.<BR id="j7pp1819"> Retrieving data using a range query on the primary key is a two-step process. First one have to retrieve the collection of primary-keys, followed by a step to generate the intervals to properly identify a proper subset of the data,followed by the actual queries against the data.<BR id="j7pp1820"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp1821"><SPAN style="color: #800000" id="j7pp1822"> 1 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1823"><B id="j7pp1824">package</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1825"> com.zenior.sandbox.hibernate.pagination;<BR id="j7pp1826"></SPAN><SPAN style="color: #800000" id="j7pp1827"> 2 <BR id="j7pp1828"> 3 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1829"><B id="j7pp1830">import</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1831"> no.zenior.domain.HibernateCriteriaSpecification;<BR id="j7pp1832"></SPAN><SPAN style="color: #800000" id="j7pp1833"> 4 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1834"><B id="j7pp1835">import</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1836"> org.springframework.orm.hibernate3.HibernateTemplate;<BR id="j7pp1837"></SPAN><SPAN style="color: #800000" id="j7pp1838"> 5 <BR id="j7pp1839"> 6 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1840"><B id="j7pp1841">import</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1842"> java.util.AbstractCollection;<BR id="j7pp1843"></SPAN><SPAN style="color: #800000" id="j7pp1844"> 7 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1845"><B id="j7pp1846">import</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1847"> java.util.ArrayList;<BR id="j7pp1848"></SPAN><SPAN style="color: #800000" id="j7pp1849"> 8 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1850"><B id="j7pp1851">import</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1852"> java.util.Collection;<BR id="j7pp1853"></SPAN><SPAN style="color: #800000" id="j7pp1854"> 9 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1855"><B id="j7pp1856">import</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1857"> java.util.Iterator;<BR id="j7pp1858"></SPAN><SPAN style="color: #800000" id="j7pp1859"> 10 <BR id="j7pp1860"> 11 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1861"><I id="j7pp1862">/**<BR id="j7pp1863"></I></SPAN><SPAN style="color: #800000" id="j7pp1864"> 12 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1865"><I id="j7pp1866"> * Collection implementation that iterates using a range query for available identifiers<BR id="j7pp1867"></I></SPAN><SPAN style="color: #800000" id="j7pp1868"> 13 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1869"><I id="j7pp1870"> * for the queried collection.<BR id="j7pp1871"></I></SPAN><SPAN style="color: #800000" id="j7pp1872"> 14 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1873"><I id="j7pp1874"> * </I></SPAN><SPAN style="color: #808080; background-color: #e2ffe2" id="j7pp1875"><I id="j7pp1876"></br><BR id="j7pp1877"></I></SPAN><SPAN style="color: #800000" id="j7pp1878"> 15 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1879"><I id="j7pp1880"> *<BR id="j7pp1881"></I></SPAN><SPAN style="color: #800000" id="j7pp1882"> 16 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1883"><I id="j7pp1884"> * </I></SPAN><SPAN style="color: #808080" id="j7pp1885"><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1886"><B id="j7pp1887"><I id="j7pp1888"><U id="j7pp1889">@author</U></I></B></SPAN></SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1890"><I id="j7pp1891"> Bjørn Bjerkeli<BR id="j7pp1892"></I></SPAN><SPAN style="color: #800000" id="j7pp1893"> 17 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1894"><I id="j7pp1895"> */<BR id="j7pp1896"></I></SPAN><SPAN style="color: #800000" id="j7pp1897"> 18 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1898"><B id="j7pp1899">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1900"><B id="j7pp1901">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1902"> IdIntervalCollection </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp1903"><B id="j7pp1904">extends</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1905"> AbstractCollection {<BR id="j7pp1906"></SPAN><SPAN style="color: #800000" id="j7pp1907"> 19 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1908"><B id="j7pp1909">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1910"><B id="j7pp1911">static</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1912"><B id="j7pp1913">final</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1914"><B id="j7pp1915">int</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1916"><B id="j7pp1917"><I id="j7pp1918">DEFAULT_PAGESIZE </I></B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1919">= </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp1920">2000</SPAN><SPAN style="background-color: #ffffff" id="j7pp1921">;<BR id="j7pp1922"></SPAN><SPAN style="color: #800000" id="j7pp1923"> 20 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1924"><B id="j7pp1925">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1926"> HibernateTemplate </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1927"><B id="j7pp1928">hibernateTemplate;<BR id="j7pp1929"></B></SPAN><SPAN style="color: #800000" id="j7pp1930"> 21 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1931"><B id="j7pp1932">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1933"> HibernateCriteriaSpecification </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1934"><B id="j7pp1935">finderSpecification;<BR id="j7pp1936"></B></SPAN><SPAN style="color: #800000" id="j7pp1937"> 22 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1938"><B id="j7pp1939">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1940"><B id="j7pp1941">int</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1942"><B id="j7pp1943">pageSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1944">= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1945"><B id="j7pp1946"><I id="j7pp1947">DEFAULT_PAGESIZE;<BR id="j7pp1948"></I></B></SPAN><SPAN style="color: #800000" id="j7pp1949"> 23 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1950"><B id="j7pp1951">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1952"> IdIntervalCollectionBuilder </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1953"><B id="j7pp1954">pager;<BR id="j7pp1955"></B></SPAN><SPAN style="color: #800000" id="j7pp1956"> 24 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1957"><B id="j7pp1958">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1959"><B id="j7pp1960">int</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp1961"><B id="j7pp1962">size;<BR id="j7pp1963"></B></SPAN><SPAN style="color: #800000" id="j7pp1964"> 25 <BR id="j7pp1965"> 26 </SPAN> <SPAN style="color: #808080; background-color: #ffffff" id="j7pp1966"><I id="j7pp1967">/**<BR id="j7pp1968"></I></SPAN><SPAN style="color: #800000" id="j7pp1969"> 27 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1970"><I id="j7pp1971"> * </I></SPAN><SPAN style="color: #808080" id="j7pp1972"><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1973"><B id="j7pp1974"><I id="j7pp1975"><U id="j7pp1976">@param</U></I></B></SPAN></SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1977"><I id="j7pp1978"> hibernateTemplate<BR id="j7pp1979"></I></SPAN><SPAN style="color: #800000" id="j7pp1980"> 28 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1981"><I id="j7pp1982"> * </I></SPAN><SPAN style="color: #808080" id="j7pp1983"><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1984"><B id="j7pp1985"><I id="j7pp1986"><U id="j7pp1987">@param</U></I></B></SPAN></SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1988"><I id="j7pp1989"> finderSpecification<BR id="j7pp1990"></I></SPAN><SPAN style="color: #800000" id="j7pp1991"> 29 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp1992"><I id="j7pp1993"> */<BR id="j7pp1994"></I></SPAN><SPAN style="color: #800000" id="j7pp1995"> 30 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp1996"><B id="j7pp1997">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp1998"> IdIntervalCollection(HibernateTemplate hibernateTemplate,<BR id="j7pp1999"></SPAN><SPAN style="color: #800000" id="j7pp2000"> 31 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2001"> HibernateCriteriaSpecification finderSpecification) {<BR id="j7pp2002"></SPAN><SPAN style="color: #800000" id="j7pp2003"> 32 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2004"><B id="j7pp2005">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2006">(hibernateTemplate, finderSpecification, </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2007"><B id="j7pp2008"><I id="j7pp2009">DEFAULT_PAGESIZE)</I></B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2010">;<BR id="j7pp2011"></SPAN><SPAN style="color: #800000" id="j7pp2012"> 33 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2013"> }<BR id="j7pp2014"></SPAN><SPAN style="color: #800000" id="j7pp2015"> 34 <BR id="j7pp2016"> 35 </SPAN> <SPAN style="color: #808080; background-color: #ffffff" id="j7pp2017"><I id="j7pp2018">/**<BR id="j7pp2019"></I></SPAN><SPAN style="color: #800000" id="j7pp2020"> 36 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2021"><I id="j7pp2022"> * </I></SPAN><SPAN style="color: #808080" id="j7pp2023"><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2024"><B id="j7pp2025"><I id="j7pp2026"><U id="j7pp2027">@param</U></I></B></SPAN></SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2028"><I id="j7pp2029"> hibernateTemplate<BR id="j7pp2030"></I></SPAN><SPAN style="color: #800000" id="j7pp2031"> 37 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2032"><I id="j7pp2033"> * </I></SPAN><SPAN style="color: #808080" id="j7pp2034"><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2035"><B id="j7pp2036"><I id="j7pp2037"><U id="j7pp2038">@param</U></I></B></SPAN></SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2039"><I id="j7pp2040"> finderSpecification<BR id="j7pp2041"></I></SPAN><SPAN style="color: #800000" id="j7pp2042"> 38 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2043"><I id="j7pp2044"> * </I></SPAN><SPAN style="color: #808080" id="j7pp2045"><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2046"><B id="j7pp2047"><I id="j7pp2048"><U id="j7pp2049">@param</U></I></B></SPAN></SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2050"><I id="j7pp2051"> pageSize<BR id="j7pp2052"></I></SPAN><SPAN style="color: #800000" id="j7pp2053"> 39 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2054"><I id="j7pp2055"> */<BR id="j7pp2056"></I></SPAN><SPAN style="color: #800000" id="j7pp2057"> 40 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2058"><B id="j7pp2059">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2060"> IdIntervalCollection(HibernateTemplate hibernateTemplate,<BR id="j7pp2061"></SPAN><SPAN style="color: #800000" id="j7pp2062"> 41 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2063"> HibernateCriteriaSpecification finderSpecification, </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp2064"><B id="j7pp2065">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2066"> pageSize) {<BR id="j7pp2067"></SPAN><SPAN style="color: #800000" id="j7pp2068"> 42 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2069"><B id="j7pp2070">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2071">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2072"><B id="j7pp2073">hibernateTemplate </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2074">= hibernateTemplate;<BR id="j7pp2075"></SPAN><SPAN style="color: #800000" id="j7pp2076"> 43 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2077"><B id="j7pp2078">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2079">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2080"><B id="j7pp2081">finderSpecification </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2082">= finderSpecification;<BR id="j7pp2083"></SPAN><SPAN style="color: #800000" id="j7pp2084"> 44 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2085"><B id="j7pp2086">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2087">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2088"><B id="j7pp2089">pageSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2090">= pageSize;<BR id="j7pp2091"></SPAN><SPAN style="color: #800000" id="j7pp2092"> 45 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2093"> initialize();<BR id="j7pp2094"></SPAN><SPAN style="color: #800000" id="j7pp2095"> 46 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2096"> }<BR id="j7pp2097"></SPAN><SPAN style="color: #800000" id="j7pp2098"> 47 <BR id="j7pp2099"> 48 </SPAN> <SPAN style="color: #808080; background-color: #ffffff" id="j7pp2100"><I id="j7pp2101">/**<BR id="j7pp2102"></I></SPAN><SPAN style="color: #800000" id="j7pp2103"> 49 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2104"><I id="j7pp2105"> * Initialize the instance of BucketIdIntervalPager.<BR id="j7pp2106"></I></SPAN><SPAN style="color: #800000" id="j7pp2107"> 50 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2108"><I id="j7pp2109"> */<BR id="j7pp2110"></I></SPAN><SPAN style="color: #800000" id="j7pp2111"> 51 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2112"><B id="j7pp2113">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2114"><B id="j7pp2115">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2116"> initialize() {<BR id="j7pp2117"></SPAN><SPAN style="color: #800000" id="j7pp2118"> 52 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2119"> Collection identifiers = HibernateRepositoryTool.</SPAN><SPAN style="background-color: #ffffff" id="j7pp2120"><I id="j7pp2121">idProjection(</I></SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2122"><B id="j7pp2123">hibernateTemplate,</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2124"><B id="j7pp2125">finderSpecification)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2126">;<BR id="j7pp2127"></SPAN><SPAN style="color: #800000" id="j7pp2128"> 53 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2129"><B id="j7pp2130">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2131">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2132"><B id="j7pp2133">pager </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2134">= </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp2135"><B id="j7pp2136">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2137"> IdIntervalCollectionBuilder(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2138"><B id="j7pp2139">pageSize)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2140">;<BR id="j7pp2141"></SPAN><SPAN style="color: #800000" id="j7pp2142"> 54 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2143"><B id="j7pp2144">for</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2145"> (Object identifier : identifiers) {<BR id="j7pp2146"></SPAN><SPAN style="color: #800000" id="j7pp2147"> 55 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2148"><B id="j7pp2149">pager.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2150">add((Long) identifier);<BR id="j7pp2151"></SPAN><SPAN style="color: #800000" id="j7pp2152"> 56 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2153"> }<BR id="j7pp2154"></SPAN><SPAN style="color: #800000" id="j7pp2155"> 57 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2156"><B id="j7pp2157">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2158">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2159"><B id="j7pp2160">size </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2161">= identifiers.size();<BR id="j7pp2162"></SPAN><SPAN style="color: #800000" id="j7pp2163"> 58 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2164"><B id="j7pp2165">hibernateTemplate.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2166">clear();<BR id="j7pp2167"></SPAN><SPAN style="color: #800000" id="j7pp2168"> 59 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2169"> }<BR id="j7pp2170"></SPAN><SPAN style="color: #800000" id="j7pp2171"> 60 <BR id="j7pp2172"> 61 <BR id="j7pp2173"> 62 <BR id="j7pp2174"> 63 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2175"><B id="j7pp2176">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2177"><B id="j7pp2178">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2179"> size() {<BR id="j7pp2180"></SPAN><SPAN style="color: #800000" id="j7pp2181"> 64 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2182"><B id="j7pp2183">return</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2184"><B id="j7pp2185">size;<BR id="j7pp2186"></B></SPAN><SPAN style="color: #800000" id="j7pp2187"> 65 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2188"> }<BR id="j7pp2189"></SPAN><SPAN style="color: #800000" id="j7pp2190"> 66 <BR id="j7pp2191"> 67 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2192"><B id="j7pp2193">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2194"> Iterator iterator() {<BR id="j7pp2195"></SPAN><SPAN style="color: #800000" id="j7pp2196"> 68 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2197"><B id="j7pp2198">return</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2199"><B id="j7pp2200">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2201"> Iterator() {<BR id="j7pp2202"></SPAN><SPAN style="color: #800000" id="j7pp2203"> 69 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2204"><B id="j7pp2205">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2206"> Collection </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2207"><B id="j7pp2208">currentPage </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2209">= </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp2210"><B id="j7pp2211">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2212"> ArrayList();<BR id="j7pp2213"></SPAN><SPAN style="color: #800000" id="j7pp2214"> 70 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2215"><B id="j7pp2216">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2217"> Iterator </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2218"><B id="j7pp2219">currentIterator </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2220">= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2221"><B id="j7pp2222">currentPage.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2223">iterator();<BR id="j7pp2224"></SPAN><SPAN style="color: #800000" id="j7pp2225"> 71 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2226"><B id="j7pp2227">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2228"> Iterator </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2229"><B id="j7pp2230">currentIdIntervalIterator </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2231">= </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp2232"><B id="j7pp2233">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2234"> ArrayList(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2235"><B id="j7pp2236">pager.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2237">buildIdIntervals()).iterator();<BR id="j7pp2238"></SPAN><SPAN style="color: #800000" id="j7pp2239"> 72 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2240"><B id="j7pp2241">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2242"> IdInterval </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2243"><B id="j7pp2244">currentIdInterval;<BR id="j7pp2245"></B></SPAN><SPAN style="color: #800000" id="j7pp2246"> 73 <BR id="j7pp2247"> 74 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2248"><B id="j7pp2249">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2250"><B id="j7pp2251">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2252"> remove() {<BR id="j7pp2253"></SPAN><SPAN style="color: #800000" id="j7pp2254"> 75 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2255"><B id="j7pp2256">throw</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2257"><B id="j7pp2258">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2259"> UnsupportedOperationException();<BR id="j7pp2260"></SPAN><SPAN style="color: #800000" id="j7pp2261"> 76 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2262"> }<BR id="j7pp2263"></SPAN><SPAN style="color: #800000" id="j7pp2264"> 77 <BR id="j7pp2265"> 78 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2266"><B id="j7pp2267">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2268"><B id="j7pp2269">boolean</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2270"> hasNext() {<BR id="j7pp2271"></SPAN><SPAN style="color: #800000" id="j7pp2272"> 79 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2273"><B id="j7pp2274">return</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2275"> ((</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2276"><B id="j7pp2277">size </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2278">> </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp2279">0</SPAN><SPAN style="background-color: #ffffff" id="j7pp2280">) && </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2281"><B id="j7pp2282">currentIdIntervalIterator.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2283">hasNext())<BR id="j7pp2284"></SPAN><SPAN style="color: #800000" id="j7pp2285"> 80 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2286"> || </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2287"><B id="j7pp2288">currentIterator.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2289">hasNext();<BR id="j7pp2290"></SPAN><SPAN style="color: #800000" id="j7pp2291"> 81 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2292"> }<BR id="j7pp2293"></SPAN><SPAN style="color: #800000" id="j7pp2294"> 82 <BR id="j7pp2295"> 83 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2296"><B id="j7pp2297">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2298"> Object next() {<BR id="j7pp2299"></SPAN><SPAN style="color: #800000" id="j7pp2300"> 84 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2301"><B id="j7pp2302">if</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2303"> (!</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2304"><B id="j7pp2305">currentIterator.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2306">hasNext()) {<BR id="j7pp2307"></SPAN><SPAN style="color: #800000" id="j7pp2308"> 85 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2309"> unloadPage(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2310"><B id="j7pp2311">currentPage)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2312">;<BR id="j7pp2313"></SPAN><SPAN style="color: #800000" id="j7pp2314"> 86 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2315"><B id="j7pp2316">currentIdInterval </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2317">= (IdInterval) </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2318"><B id="j7pp2319">currentIdIntervalIterator.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2320">next();<BR id="j7pp2321"></SPAN><SPAN style="color: #800000" id="j7pp2322"> 87 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2323"> loadPage(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2324"><B id="j7pp2325">currentIdInterval)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2326">;<BR id="j7pp2327"></SPAN><SPAN style="color: #800000" id="j7pp2328"> 88 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2329"> }<BR id="j7pp2330"></SPAN><SPAN style="color: #800000" id="j7pp2331"> 89 <BR id="j7pp2332"> 90 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2333"><B id="j7pp2334">return</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2335"><B id="j7pp2336">currentIterator.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2337">next();<BR id="j7pp2338"></SPAN><SPAN style="color: #800000" id="j7pp2339"> 91 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2340"> }<BR id="j7pp2341"></SPAN><SPAN style="color: #800000" id="j7pp2342"> 92 <BR id="j7pp2343"> 93 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2344"><B id="j7pp2345">protected</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2346"><B id="j7pp2347">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2348"> unloadPage(Collection currentPage) {<BR id="j7pp2349"></SPAN><SPAN style="color: #800000" id="j7pp2350"> 94 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2351"><B id="j7pp2352">for</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2353"> (Object o : currentPage) {<BR id="j7pp2354"></SPAN><SPAN style="color: #800000" id="j7pp2355"> 95 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2356"><B id="j7pp2357">hibernateTemplate.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2358">evict(o);<BR id="j7pp2359"></SPAN><SPAN style="color: #800000" id="j7pp2360"> 96 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2361"> }<BR id="j7pp2362"></SPAN><SPAN style="color: #800000" id="j7pp2363"> 97 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2364"> }<BR id="j7pp2365"></SPAN><SPAN style="color: #800000" id="j7pp2366"> 98 <BR id="j7pp2367"> 99 </SPAN> <SPAN style="color: #808080; background-color: #ffffff" id="j7pp2368"><I id="j7pp2369">/**<BR id="j7pp2370"></I></SPAN><SPAN style="color: #800000" id="j7pp2371">100 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2372"><I id="j7pp2373"> * Load the data corresponding to the idInterval.<BR id="j7pp2374"></I></SPAN><SPAN style="color: #800000" id="j7pp2375">101 </SPAN><SPAN style="color: #808080; background-color: #ffffff" id="j7pp2376"><I id="j7pp2377"> */<BR id="j7pp2378"></I></SPAN><SPAN style="color: #800000" id="j7pp2379">102 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2380"><B id="j7pp2381">protected</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2382"><B id="j7pp2383">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2384"> loadPage(IdInterval currentIdInterval) {<BR id="j7pp2385"></SPAN><SPAN style="color: #800000" id="j7pp2386">103 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2387"><B id="j7pp2388">finderSpecification.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2389">setIdInterval(currentIdInterval);<BR id="j7pp2390"></SPAN><SPAN style="color: #800000" id="j7pp2391">104 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2392"><B id="j7pp2393">currentPage </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2394">= HibernateRepositoryTool.</SPAN><SPAN style="background-color: #ffffff" id="j7pp2395"><I id="j7pp2396">find(</I></SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2397"><B id="j7pp2398">hibernateTemplate,</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2399"><B id="j7pp2400">finderSpecification)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2401">;<BR id="j7pp2402"></SPAN><SPAN style="color: #800000" id="j7pp2403">105 </SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2404"><B id="j7pp2405">currentIterator </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2406">= </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2407"><B id="j7pp2408">currentPage.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2409">iterator();<BR id="j7pp2410"></SPAN><SPAN style="color: #800000" id="j7pp2411">106 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2412"> }<BR id="j7pp2413"></SPAN><SPAN style="color: #800000" id="j7pp2414">107 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2415"> };<BR id="j7pp2416"></SPAN><SPAN style="color: #800000" id="j7pp2417">108 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2418"> }<BR id="j7pp2419"></SPAN><SPAN style="color: #800000" id="j7pp2420">109 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2421">}<BR id="j7pp2422"></SPAN><SPAN style="color: #800000" id="j7pp2423">110 <BR id="j7pp2424">111 </SPAN></PRE><B id="j7pp2425">Listing 13<BR id="j7pp2426"><BR id="j7pp2427"></B> The key here is basically to implement the iteration process in two steps, one to retrieve identifiers, and one to actually provide the iterator with an <I id="j7pp2428">id-interval </I>that is used tospecify a <I id="j7pp2429">between </I>range-query. Retrieving the set of identifiers is easy, the<SPAN style='font-family: "Courier New"' id="j7pp2430"> HibernateCriteriaSpecification</SPAN> that uses Criteria for search has a <SPAN style='font-family: "Courier New"' id="j7pp2431">Projections.id()</SPAN>factory that returns all identifiers for a given Criteria-query. Basedupon the entire set of identifiers we are able to construct buckets of identifiers each representing a logical and proper page of data.<BR id="j7pp2432"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp2433"><SPAN style="color: #800000" id="j7pp2434"> 1 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2435"><B id="j7pp2436">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2437"><B id="j7pp2438">void</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2439"> testRetrieveOrderLinesUsingPagingIdInterval() {<BR id="j7pp2440"></SPAN><SPAN style="color: #800000" id="j7pp2441"> 2 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2442"><B id="j7pp2443">final</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2444"> Order order = (Order) </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2445"><B id="j7pp2446">hibernateTemplate.</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2447">get(Order.</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp2448"><B id="j7pp2449">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2450">, </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2451"><B id="j7pp2452">orderId)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2453">;<BR id="j7pp2454"></SPAN><SPAN style="color: #800000" id="j7pp2455"> 3 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2456"> Collection orderLines = order.getOrderLines(</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp2457"><B id="j7pp2458">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2459"> IdIntervalPagedCollectionBuilder(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2460"><B id="j7pp2461">hibernateTemplate,</B></SPAN> <SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp2462">50000</SPAN><SPAN style="background-color: #ffffff" id="j7pp2463">));<BR id="j7pp2464"></SPAN><SPAN style="color: #800000" id="j7pp2465"> 4 <BR id="j7pp2466"> 5 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2467"> ResourceMonitor monitor = </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp2468"><B id="j7pp2469">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2470"> ResourceMonitor(</SPAN><SPAN style="color: #008000; background-color: #ffffff" id="j7pp2471"><B id="j7pp2472">"order.getOrderLines()"</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2473">);<BR id="j7pp2474"></SPAN><SPAN style="color: #800000" id="j7pp2475"> 6 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2476"><B id="j7pp2477">for</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2478"> (Object orderLine : orderLines) {<BR id="j7pp2479"></SPAN><SPAN style="color: #800000" id="j7pp2480"> 7 </SPAN> <SPAN style="color: #808080; background-color: #ffffff" id="j7pp2481"><I id="j7pp2482">//<BR id="j7pp2483"></I></SPAN><SPAN style="color: #800000" id="j7pp2484"> 8 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2485"> OrderLine line = (OrderLine) orderLine;<BR id="j7pp2486"></SPAN><SPAN style="color: #800000" id="j7pp2487"> 9 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2488"> }<BR id="j7pp2489"></SPAN><SPAN style="color: #800000" id="j7pp2490"> 10 </SPAN> <SPAN style="background-color: #ffffff" id="j7pp2491"><I id="j7pp2492">assertEquals(</I></SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp2493">1000</SPAN><SPAN style="background-color: #ffffff" id="j7pp2494"> * </SPAN><SPAN style="color: #0000ff; background-color: #ffffff" id="j7pp2495">1000</SPAN><SPAN style="background-color: #ffffff" id="j7pp2496">, orderLines.size());<BR id="j7pp2497"></SPAN><SPAN style="color: #800000" id="j7pp2498"> 11 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2499"> monitor.stop();<BR id="j7pp2500"></SPAN><SPAN style="color: #800000" id="j7pp2501"> 12 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2502"> System.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2503"><B id="j7pp2504"><I id="j7pp2505">out.</I></B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2506">println(monitor);<BR id="j7pp2507"></SPAN><SPAN style="color: #800000" id="j7pp2508"> 13 </SPAN> <BR id="j7pp2510"><SPAN style="color: #800000" id="j7pp2511"> 14 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2512">}</SPAN></PRE><B id="j7pp2513">Listing 14<BR id="j7pp2514"><BR id="j7pp2515"></B> The<SPAN style='font-family: "Courier New"' id="j7pp2516"> IdIntervalPagedCollectionBuilder</SPAN> is the pluggable implementation of the<SPAN style='font-family: "Courier New"' id="j7pp2517"> CollectionBuilder </SPAN>interface described in listing 6.<BR id="j7pp2518"><PRE style="padding-top: 4px; padding-right: 4px; padding-bottom: 4px; padding-left: 4px; line-height: 100%; font-family: monospace; background-color: #ffffff" id="j7pp2519"><SPAN style="color: #800000" id="j7pp2520"> 1 </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp2521"><B id="j7pp2522">public</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2523"><B id="j7pp2524">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2525"> IdIntervalPagedCollectionBuilder </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp2526"><B id="j7pp2527">implements</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2528"> CollectionBuilder {<BR id="j7pp2529"></SPAN><SPAN style="color: #800000" id="j7pp2530"> 2 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2531"><B id="j7pp2532">private</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2533"> HibernateTemplate </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2534"><B id="j7pp2535">hibernateTemplate;<BR id="j7pp2536"></B></SPAN><SPAN style="color: #800000" id="j7pp2537"> 3 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2538"><B id="j7pp2539">private</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2540"><B id="j7pp2541">int</B></SPAN> <SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2542"><B id="j7pp2543">pageSize;<BR id="j7pp2544"></B></SPAN><SPAN style="color: #800000" id="j7pp2545"> 4 <BR id="j7pp2546"> 5 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2547"><B id="j7pp2548">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2549"> IdIntervalPagedCollectionBuilder(HibernateTemplate hibernateTemplate, </SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp2550"><B id="j7pp2551">int</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2552"> pageSize) {<BR id="j7pp2553"></SPAN><SPAN style="color: #800000" id="j7pp2554"> 6 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2555"><B id="j7pp2556">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2557">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2558"><B id="j7pp2559">hibernateTemplate </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2560">= hibernateTemplate;<BR id="j7pp2561"></SPAN><SPAN style="color: #800000" id="j7pp2562"> 7 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2563"><B id="j7pp2564">this</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2565">.</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2566"><B id="j7pp2567">pageSize </B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2568">= pageSize;<BR id="j7pp2569"></SPAN><SPAN style="color: #800000" id="j7pp2570"> 8 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2571"> }<BR id="j7pp2572"></SPAN><SPAN style="color: #800000" id="j7pp2573"> 9 <BR id="j7pp2574">10 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2575"><B id="j7pp2576">public</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2577"> Collection build(Object instance) {<BR id="j7pp2578"></SPAN><SPAN style="color: #800000" id="j7pp2579">11 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2580"><B id="j7pp2581">return</B></SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2582"><B id="j7pp2583">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2584"> IdIntervalCollection(</SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2585"><B id="j7pp2586">hibernateTemplate,</B></SPAN> <BR id="j7pp2588"><SPAN style="color: #800000" id="j7pp2589">12 </SPAN> <SPAN style="color: #000080; background-color: #ffffff" id="j7pp2590"><B id="j7pp2591">new</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2592"> HibernateCriteriaSpecification(OrderLine.</SPAN><SPAN style="color: #000080; background-color: #ffffff" id="j7pp2593"><B id="j7pp2594">class</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2595">, instance, </SPAN><SPAN style="color: #008000; background-color: #ffffff" id="j7pp2596"><B id="j7pp2597">"order"</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2598">), </SPAN><SPAN style="color: #660e7a; background-color: #ffffff" id="j7pp2599"><B id="j7pp2600">pageSize)</B></SPAN><SPAN style="background-color: #ffffff" id="j7pp2601">;<BR id="j7pp2602"></SPAN><SPAN style="color: #800000" id="j7pp2603">13 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2604"> }<BR id="j7pp2605"></SPAN><SPAN style="color: #800000" id="j7pp2606">14 </SPAN><SPAN style="background-color: #ffffff" id="j7pp2607">}</SPAN></PRE><BR id="j7pp2608"><BR id="j7pp2610"><B id="j7pp2611">Listing 15<BR id="j7pp2612"><BR id="j7pp2613"></B> The three examples have almost the same amount of code, but rely onquite different approaches. The test-result for the last test is remarkable.<BR id="j7pp2614"><DIV id="j7pp2615"><TABLE style="width: 327px; height: 66px" border="2" cellpadding="3" cellspacing="0" id="j7pp2616"><TBODY id="j7pp2617"><TR id="j7pp2618"><TD width="50%" id="j7pp2619"><B id="j7pp2620">Time elapsed</B><BR id="j7pp2621"></TD><TD width="50%" id="j7pp2622"><B id="j7pp2623"> Memory Usage Delta<BR id="j7pp2624"></B></TD></TR><TR id="j7pp2625"><TD width="50%" id="j7pp2626"><B id="j7pp2627"> 99,5s<BR id="j7pp2628"></B></TD><TD width="50%" id="j7pp2629"><B id="j7pp2630"> 29402<BR id="j7pp2631"></B></TD></TR></TBODY></TABLE></DIV> This approach is almost as fast as the brute-force version. The memory consumption is about one tenth. By selecting the appropriate page-size for this implementation, you may alter the ratio between execution time and memory consumption. This version is also stateless, it does not keep references to resources like the ScrollableResult version does, nor does it strain the database like the version using setFirstResult/setMaxResult.<BR id="j7pp2632"><H2 id="j7pp2633"> Limitations </H2> We need a primary key, preferably a surrogate key, that has a natural ordering so that we can implement the paging concept by using a between search for the identifiers. Another limitation is the need to actually retrieve all the identifiers before performing the search, which means two select-statements instead of possibly only one.<BR id="j7pp2634"><BR id="j7pp2635"><H1 style="background-color: #ffffff; color: #000000" id="j7pp2636"> The Author </H1><P id="qdnf1"><SPAN style="background-color: #ffffff; color: #000000" id="j7pp2637"> The Author is working as a senior consultant in a Norwegian consulting company, Zenior AS, and is an active member of the Norwegian JUG, javaBin.</SPAN><BR id="j7pp2638"></P><H1 id="hpgp"><SPAN style="background-color: #ffffff; color: #000000" id="qdnf5">Licensing</SPAN></H1><P id="hpgp0"> <A rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/no/" id="adlk"><IMG alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/no/88x31.png" id="adlk0"></A><BR id="adlk1"> Hibernate paging using id-intervals by <A href="http://devperspective.blogspot.com/" rel="cc:attributionURL" id="adlk3">Bjørn Bjerkeli</A> is licensed under a <A rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/no/" id="adlk4">Creative Commons Attribution-Share Alike 3.0 Norway License</A>.<BR id="adlk5"> Based on a work at <A href="http://svitjod.rymdweb.com/repository/com/zenior/sandbox/" rel="dc:source" id="adlk6">svitjod.rymdweb.com</A>. </P><H2 id="j7pp2639"> References </H2><A name="memory" id="j7pp2640">[1] Memory limitation on 32 bit systems</A>, http://www.theserverside.com/discussions/thread.tss?thread_id=19442<BR id="j7pp2641"><A name="hibernate_batch" id="j7pp2642">[2] Hibernate batch processing</A> http://www.hibernate.org/hib_docs/v3/reference/en/html/batch.html<BR id="j7pp2643"><A name="rownum" id="j7pp2644">[3] Oracle rownum</A> http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html<BR id="j7pp2645"><A name="rownum" id="j7pp2646"><BR id="j7pp2647"></A><BR id="ty_-"> Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com11tag:blogger.com,1999:blog-29135008.post-15851362370612766552006-10-22T13:00:00.000+02:002006-10-22T13:10:14.869+02:00Sourceforge download problemsJust wanted to download the updated version of <a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a> which I like a lot better than the command-.line svn tool when importing projects from different folders. The only problem was that for some reason, the only available download site was a server in kent, that for some reason was down.<br />I inspected the download url, that is on the form http://prdownloads.sourceforge.net/tortoisesvn/TortoiseSVN-1.4.0.7501-x64-svn-1.4.0.msi?use_mirror=kent<br />Well i assumed that the request parameter use_mirror =<alias> could probably be replaced by something else. I tried google to see if I could get at list of all these alternate servers, without luck. I saw that the download-server had a dns-name on the form http://kent.dl.sourceforge.net/, then i turned to netcraft.com and entered *.dl.sourceforge.net and it immediately gave me back a list of servers matching the dns-query. Voila, i replaced use_mirror=kent with use_mirror=belnet and there my binary dumped down on disk :-)<br /></alias>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com3tag:blogger.com,1999:blog-29135008.post-61721729465406055692006-10-21T13:42:00.000+02:002006-10-22T13:00:25.273+02:00Saturday night inIt's Saturday night and I think I will spend most of it at home together with my computer.<br /><a href="http://blogger.com/">blogger.com</a> has gone live with a new version of blogging software, so I have just downloaded the new <a href="http://www.mozilla.com/en-US/firefox/2.0/releasenotes/">Firefox 2.0 RC3</a> bowser and will give both the face lifted browser and the new blogger a try.<br /><br />The first thing I noticed was that my <a href="http://del.icio.us/">del.icio.us</a> plugin doesn't work anymore. I have really been used to adding sites and bookmarks to del.icio.us using the extension, especially since I am using multiple computers, and being able to centralize the management of my bookmarks is really a good thing. Fortunately, I found a replacement, <a href="https://addons.mozilla.org/firefox/527/">del.icio.us post</a> that works fine with 2.0.<br />The 2.0 browser now comes with a built-in spell-checker, which is nice. Text that you enter in form field can be validated on the client side, and does not rely on external services. I have used it already.<br /><br />Other things that I have been using and spending my time on lately is:<br />* <a href="http://www.jetbrains.com/idea/">IDEA IntelliJ 6.0</a> that was released last week<br />* <a href="http://code.google.com/webtoolkit/">Google Web Toolkit, GWT</a><br />* <a href="http://www.gpsoft.com.au/Intro.html">Directory Opus</a> a commercial alternative to Total Commander<br /><br />And if you haven't moved to the new beta-version on blogger.com, do it, its better than before, I guess that the Google-guys has been busy lately.<br /><br /><span style="text-decoration: underline;"></span>Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com2tag:blogger.com,1999:blog-29135008.post-1158272192144847672006-09-14T23:58:00.000+02:002006-10-21T13:55:14.097+02:00JavaZone closeup and end-commentsThe last day of JavaZone has been just as exiting as the first one. I tried to add a nice mix of high level process-oriented stuff with hard-core technical sessions to keep me from falling asleep today. Didn't have much sleep tonight, huh.<br />Mary Poppendieck had a great session on Lean SW-development. I am a great fan of the Poppendiecks and especially their first book on <a href="http://www.amazon.com/gp/explorer/0321150783/2/ref=pd_lpo_ase/102-4122036-6556943?ie=UTF8">Lean Software Development:An Agile Toolkit. </a><br />Conventiently she announced that her <a href="http://www.amazon.com/gp/explorer/0321437381/2/ref=pd_lpo_ase/102-4122036-6556943?ie=UTF8">new book</a> is shipping as we speak. I am also in the process of entering my credit card number on amazon to get a copy.<br />Thereafter I dived into a session on <a href="http://www.sun.com/bigadmin/content/dtrace/">DTrace</a>, a feature of Solaris systems that enables full tracing of the entire software stack from a thread in the java-vm and down to system calls in the kernel. This approach to tracing will make searching for bottlenecks in the system much easier. The speach was accompanied with some nice live demos.<br />Simon Ritter another speaker that made JavaZone 2006 worth visiting. He has been experimenting with <a href="http://research.sun.com/projects/dashboard.php?id=145">SPOT</a> and robots, talking about <a href="https://rtsj.dev.java.net/">RTSJ</a> and esoteric VM-options on the Solaris VM. Did you know that there are more than 400 different -XXoptions available in the Solaris VM as from java 6? Well , now you do. A I am currently back to work (in the middle of the night) because we are going in to production with a system for a client. Suddenly I realized that it is actually a year until next time I can spend two great days@JavaZone.<br /><br />Have something on your mind? post-it!Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com1tag:blogger.com,1999:blog-29135008.post-1158223436885179392006-09-14T10:35:00.000+02:002006-10-21T13:41:05.835+02:00What is new at JavaZone 2006I am currently attending a session at JavaZone 2006 called Are you a plumber? <a href="http://www2.java.no/web/show.do?page=92&articleid=4583">How to avoid plumbing for business-enriched remote clients.</a> It is a co-talk by Ole Andre Ranvik which is a co-worker of mine and Bjlørn Nordmoen from Western Gecko. The are basically speaking about a project they have been doing together for the last year and of they solved some of the issues they encountered.<br /><br />The thing about the program this year as far as I can tell is that we do not have to much stunning news, new technology, new releases and all new specs. Much more of the material this year is based upon how we actually use our technology in day-to day work. Agile tracks and and technology driven tracks share a common property with respect to this, they cover what developers have been working with, not what someone think they should work with. With some exceptions, EJB 3.0 being one of them.Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com1tag:blogger.com,1999:blog-29135008.post-1158164012845873412006-09-13T18:08:00.000+02:002006-10-21T13:41:05.769+02:00Backwards compatibility, why?This is quite an interesting topic. I am currently attending a session on EJB 3.0 and JPA given by Patrick Linskey which has been participating in the spec work. An issue related to backwards compatibility related to some things introduced in JPA (global named queries). And I asked if Patrick sees it as much of a problem to break backwards compatibility. And he said, "we did it with EJB 3.0 and we do not want to do it again". Well I have never ever heard of anyone actually complain about this compatibility break. In my opinion in many cases the effort spent not to break backwards compatibility is just a waste. We would be much better of getting new specs and implementations that improves faster as opposed to versions that does not break backwards compatibility.Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com1tag:blogger.com,1999:blog-29135008.post-1158155994568007012006-09-13T15:54:00.000+02:002006-10-21T13:41:05.706+02:00Meeting the speakers and authorsI am currently staffing the javaBin stand at <a href="http://javazone.no">JavaZone 2006</a> so I cannot attend any sessions as of now. However staffing the stand gives me a perfect oppurtunuty to talk to attendees, partners and speakers. Seems like if everybody is having a good time. Some of the sessions has been so popular that we had to schedule them twice, like Patrick Linskeys <a href="http://www2.java.no/web/show.do?page=92&articleid=4573">EJB3 Java Persistence API: The Good, The Bad, and The Ugly.</a><br /><br />So far the conference has been running smoothly. I am soon of the the next one when releaved off duty. Think I will head along to a REST vs. Soap smackdown to see what all the fuzz is about :-).Bjørn Bjerkelihttp://www.blogger.com/profile/01117393474329689344noreply@blogger.com1