source: trunk/doc/src/docbook/developerdoc/core_ref.xml @ 5656

Last change on this file since 5656 was 5656, checked in by Nicklas Nordborg, 12 years ago

References #1590: Documentation cleanup

Fixed "Core developer reference: Building BASE". The old documentation has now been moved to the wiki instead.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 63.8 KB
Line 
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE chapter PUBLIC
3    "-//Dawid Weiss//DTD DocBook V3.1-Based Extension for XML and graphics inclusion//EN"
4    "../../../../lib/docbook/preprocess/dweiss-docbook-extensions.dtd">
5<!--
6  $Id: core_ref.xml 5656 2011-06-15 10:11:52Z nicklas $
7
8  Copyright (C) 2007 Peter Johansson, Nicklas Nordborg, Martin Svensson
9
10  This file is part of BASE - BioArray Software Environment.
11  Available at http://base.thep.lu.se/
12
13  BASE is free software; you can redistribute it and/or
14  modify it under the terms of the GNU General Public License
15  as published by the Free Software Foundation; either version 3
16  of the License, or (at your option) any later version.
17
18  BASE is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  GNU General Public License for more details.
22
23  You should have received a copy of the GNU General Public License
24  along with BASE. If not, see <http://www.gnu.org/licenses/>.
25-->
26
27<chapter id="core_ref">
28  <?dbhtml dir="core_ref"?>
29  <title>Core developer reference</title>
30
31  <sect1 id="core_ref.release">
32    <title>Publishing a new release</title>
33    <para>
34      This documentation is available on the <ulink url="http://base.thep.lu.se/wiki/ReleaseProcedure">BASE wiki</ulink>.
35    </para>
36  </sect1>
37 
38  <sect1 id="core_ref.build">
39    <title>Subversion / building BASE</title>
40    <para>
41      This documentation is available on the <ulink url="http://base.thep.lu.se/wiki/BuildingBase">BASE wiki</ulink>.
42    </para>
43  </sect1>
44
45  <sect1 id="core_ref.rules" chunked="1">
46    <title>Coding rules and guidelines</title>
47   
48    <sect2 id="core_ref.rules.devprocess">
49      <title>Development process and other important procedures</title>
50      <para>
51         This section describes the development process we try to use in the BASE project.
52         It is not carved in stone and deviations may occur. For every new feature
53         or enhancement the procure below should be followed.
54         If you encounter any problems, arrange a group meeting. Someone else
55         may have the solution! The text is biased towards adding new
56         items to BASE, but it should be possible to use the general outline
57         even for other types of features.
58      </para>
59     
60      <bridgehead>1. Group meeting</bridgehead>
61      <itemizedlist>
62      <listitem>
63        <para>
64        The group should have a short meeting and discuss the new or changed
65        feature. Problem areas should be identified, not solved!
66        </para>
67      </listitem>
68      <listitem>
69        <para>
70        The person who is going to make the analysis, design and development is
71        responsible for taking notes. They should be kept until the analysis
72        and design phase has been finished.     
73        </para>
74      </listitem>
75      <listitem>
76        <para>
77        A follow-up meeting should be held at the end of the analysis phase. 
78        </para>
79      </listitem>
80      <listitem>
81        <para>
82        A single meeting may of course discuss more than one feature.
83        </para>
84      </listitem>
85      </itemizedlist>
86     
87      <bridgehead>2. Analysis and design</bridgehead>
88      <itemizedlist>
89      <listitem>
90        <para>
91        Create an diagram of the classes including their properties, links and associations.
92        Use the already existing diagrams and code as a template.
93        The diagram should have information about cache and proxy settings.
94        </para>
95      </listitem>
96      <listitem>
97        <para>
98        Write a short document about the diagram, especially things that are not obvious
99        and explain any deviations from the recommendations in the coding guidelines.
100        </para>
101      </listitem>
102      <listitem>
103        <para>
104        Identify things that may affect backwards compatibility. For more
105        information about such things read <xref linkend="api_overview.public_api" />
106        and <xref linkend="core_ref.rules.compatibility" />.
107        </para>
108      </listitem>
109      <listitem>
110        <para>
111        Identify what parts of the documentation that needs to changed or added
112        to describe the new feature. This includes, but is not limited to:
113        <itemizedlist>
114        <listitem>
115          <para>
116          User and administrator documentation, how to use the feature, screenshots,
117          etc.
118          </para> 
119        </listitem>
120        <listitem>
121          <para>
122          Plug-in and core developer documentation, code examples, database schema changes,
123          etc.
124          </para> 
125        </listitem>
126        </itemizedlist>
127        </para>
128      </listitem>
129      <listitem>
130        <para>
131        If there are any problems with the existing code, these should be solved at
132        this stage. Write some prototype code for testing if necessary.
133        </para>
134      </listitem>
135      <listitem>
136        <para>
137        Group meeting to verify that the specified solution is ok, and to make sure
138        everybody has enough knowledge of the solution.
139        </para>
140      </listitem>
141      </itemizedlist>
142     
143      <bridgehead>3. Create the classes for the data layer</bridgehead>
144      <itemizedlist>
145      <listitem>
146        <para>
147        If step 2 is properly done, this should not take long.
148        </para>
149      </listitem>
150      <listitem>
151        <para>
152        Follow the coding guidelines in <xref linkend="core_ref.rules.datalayer" />.
153        </para>
154      </listitem>
155      <listitem>
156        <para>
157        At the end of this step, go back and have a lock at the diagram/documentation
158        from the analysis and design phase and make sure everything is still correct.
159        </para>
160      </listitem>
161      </itemizedlist>
162     
163      <bridgehead>4. Create the corresponding classes in the core layer</bridgehead>
164      <itemizedlist>
165      <listitem>
166        <para>
167        For simple cases this is also easy. Other cases may require more effort.
168        </para>
169      </listitem>
170      <listitem>
171        <para>
172        If needed, go back to the analysis and design phase and do some more investigations.
173        Make sure the documentation is updated if there are changes.
174        </para>
175      </listitem>
176      </itemizedlist>
177     
178      <bridgehead>5. Create test code</bridgehead>
179      <itemizedlist>
180      <listitem>
181        <para>
182        Build on and use the existing test as much as possible.
183        </para>
184      </listitem>
185      </itemizedlist>
186     
187      <bridgehead>6. Write code to update existing installations</bridgehead>
188      <important>
189      <itemizedlist>
190      <listitem>
191        <para>
192        If the database schema is changed or if there for some reason is need to update
193        existing data in the database, the <constant>Install.SCHEMA_VERSION</constant>
194        counter must be increased.
195        </para>
196      </listitem>
197      <listitem>
198        <para>
199        Add code to the <classname docapi="net.sf.basedb.core">net.sf.basedb.core.Update</classname> class
200        to increase the schema version and modify data in existing installations.
201        </para>
202      </listitem>
203      </itemizedlist>
204      </important>
205     
206      <bridgehead>7. Write new and update existing user documentation</bridgehead>
207      <itemizedlist>
208      <listitem>
209        <para>
210        Most likely, users and plug-in developers wants to know about the feature.
211        </para>
212      </listitem>
213      </itemizedlist>
214
215      <important>
216      <para>
217      Do not forget to update the <xref linkend="appendix.incompatible" /> document
218      if you have introduced any incomaptible changes.
219      </para>
220      </important>
221     
222    </sect2>
223    <sect2 id="core_ref.rules.style">
224      <title>General coding style guidelines</title>
225      <para>
226        This documentation is only available in the old format.
227        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/coding/generic.html"
228          >http://base.thep.lu.se/chrome/site/doc/historical/development/coding/generic.html</ulink>
229      </para>
230    </sect2>
231 
232    <sect2 id="core_ref.rules.compatibility">
233      <title>API changes and backwards compatibility</title>
234      <para>
235        The main rule is to do not introduce any changes that are
236        backwards incompatible. That is, existing client applications
237        and plug-ins should continue to run in the next release of BASE,
238        without the need to change them. It may sound easy but there are
239        many things to watch out for.
240      </para>
241     
242      <important>
243        <title>Do not forget to log changes!</title>
244        <para>
245        Any change that may affect backwards compatibility must be logged in
246        <xref linkend="appendix.incompatible" />.
247        </para>
248      </important>
249     
250      <para>
251        There is a great article about this subject on <ulink 
252        url="http://wiki.eclipse.org/index.php/Evolving_Java-based_APIs"
253          >http://wiki.eclipse.org/index.php/Evolving_Java-based_APIs</ulink>.
254        This is what we will try to comply with.
255      </para>
256     
257      <sect3 id="core_ref.rules.compatibility.public_api">
258        <title>Does the changes affect the Public API?</title>
259       
260        <para>
261          See <xref linkend="api_overview.public_api" /> and
262          <ulink url="http://base.thep.lu.se/chrome/site/doc/api/index.html"
263          >the javadoc</ulink>for information
264          about the public API.
265        </para>
266       
267        <para>
268          Changes made to the non-public API does not have to follow the
269          same rules.
270        </para>
271      </sect3>
272     
273      <sect3 id="core_ref.rules.compatibility.contract">
274        <title>Contract compatibility</title>
275       
276        <para>
277          TODO
278        </para>
279       
280      </sect3>
281     
282      <sect3 id="core_ref.rules.compatibility.binary">
283        <title>Binary compatibility</title>
284       
285        <para>
286          TODO
287        </para>
288       
289      </sect3>
290     
291      <sect3 id="core_ref.rules.compatibility.data">
292        <title>Internal data structure compatibility</title>
293       
294        <para>
295          TODO
296        </para>
297       
298      </sect3>
299     
300      <sect3 id="core_ref.rules.compatibility.source">
301        <title>Source code compatibility</title>
302       
303        <para>
304          TODO
305        </para>
306       
307      </sect3>
308     
309    </sect2>
310   
311    <sect2 id="core_ref.rules.datalayer">
312      <title>Data-layer rules</title>
313
314      <para>
315        The coding guidelines for this package has been slightly modified from the
316        the general coding guidelines. Here is a short list with the changes.
317      </para>
318     
319      <sect3 id="core_ref.rules.datalayer.methodorder">
320        <title>Attributes and methods order</title>
321        <para>
322          Inside a class, attributes and methods should be organised in related groups,
323          ie. the private attribute is together with the getter and setter methods that uses
324          that attribute. This makes it easy to re-use existing code with copy-and-paste
325          operations.
326        </para>
327         
328        <programlisting language="java">
329public static int long MAX_ADDRESS_LENGTH = 255;
330private String address;
331/**
332   @hibernate.property column="`address`" type="string" length="255" not-null="false"
333*/
334public String getAddress()
335{
336   return address;
337}
338public void setAddress(String address)
339{
340   this.address = address;
341}
342
343private int row;
344/**
345   @hibernate.property column="`row`" type="int"
346*/
347public int getRow()
348{
349   return row;
350}
351public void setRow(int row)
352{
353   this.row = row;
354}       
355</programlisting>
356        </sect3>
357       
358        <sect3 id="core_ref.rules.datalayer.classnames">
359          <title>Class and interface names</title>
360        <para>
361          Class names should follow the general guidelines, but should in most
362          cases end with <classname>Data</classname>.
363        </para>
364        <programlisting language="java">
365public class SampleData
366   extends CommonData
367   implements DiskConsumableData
368{
369   ...
370}
371</programlisting>
372      </sect3>
373      <sect3 id="core_ref.rules.datalayer.basicclasses">
374        <title>Extend/implement the basic classes and interfaces</title>
375        <para>
376          Each data-class must inherit from one of the already existing abstract base classes.
377          They contain code that is common to all classes, for example implementations of
378          the <methodname>equals()</methodname> and <methodname>hashCode()</methodname>
379          methods or how to link with the owner of an item. For information about
380          which classes/interfaces that can be used see <xref linkend="data_api.basic" />.
381        </para>
382      </sect3>
383
384      <sect3 id="core_ref.rules.datalayer.constructor">
385        <title>Define a public no-argument constructor</title>
386        <para>
387          Always define a public a no-argument constructor. No other constructors are needed.
388          If we want to use other persistence mechanisms or serializability in the future
389          this type of constructor is probably the most compatible. The constructor should
390          be empty and not contain any code. Do not initialise properties or create new objects
391          for internal use. Most of the time the object is loaded by
392          Hibernate and Hibernate will ensure that it is properly initialised by calling
393          all setter methods.
394        </para>
395
396        <para>
397          For example, a many-to-many relation usually has a <interfacename>Set</interfacename>
398          or a <interfacename>Map</interfacename> to hold the links to the other objects. Do not
399          create a new <classname>HashSet</classname> or <classname>HashMap</classname>
400          in the constructor. Wait until the get method is called and only create a new
401          object if Hibernate hasn't already called the setter method with it's own object.
402          See the code example below. There is also more information about this in
403          <xref linkend="core_ref.rules.datalayer.manytomany" />.
404        </para>
405       
406        <programlisting language="java">
407// From GroupData.java
408public GroupData()
409{}
410
411private Set&lt;UserData&gt; users;
412public Set&lt;UserData&gt; getUsers()
413{
414   if (users == null) users = new HashSet&lt;UserData&gt;();
415   return users;
416}
417</programlisting>
418
419        <para>
420        See also:
421        </para>
422       
423        <itemizedlist>
424        <listitem>
425          <para>
426          "Hibernate in action", chapter 3.2.3 "Writing POJOs", page 67-69
427          </para>
428        </listitem>
429        <listitem>
430          <para>
431          Hibernate user documentation: <ulink 
432            url="http://www.hibernate.org/hib_docs/reference/en/html/persistent-classes.html#persistent-classes-pojo-constructor">4.1.1.
433            Implement a no-argument constructor</ulink>
434          </para>
435        </listitem>
436        </itemizedlist>
437
438      </sect3>
439
440      <sect3 id="core_ref.rules.datalayer.identity">
441        <title>Object identity</title>
442        <para>
443          We use database identity to compare objects, ie. two objects are considered
444          equal if they are of the same class and have the same id, thus representing the
445          same database row. All this stuff is implemented by the BasicData class. Therefore
446          it is required that all classes are subclasses of this class. It is recommended
447          that the <methodname>equals()</methodname> or <methodname>hashCode()</methodname>
448          methods are not overridden by any of the subclasses. We would have liked to make
449          them final, but then the proxy feature of Hibernate would not work.
450        </para>
451       
452        <warning>
453          <title>Avoid mixing saved and unsaved objects</title>
454          <para>
455            The approch used for object identity may give us a problem if we mix objects
456            which hasn't been saved to the database, with objects loaded from the database.
457            Our recommendation is to avoid that, and save any objects to the database before
458            adding them to sets, maps or any other structure that uses the
459            <methodname>equals()</methodname> and <methodname>hashCode()</methodname> methods.
460          </para>
461          <para>
462            To be more specific, the problem arises because the following two rules for
463            hascodes are contradicting when the hashcode is based on the database id:
464          </para>
465          <orderedlist>
466          <listitem>
467            <para>
468            The hash code of an object mustn't change
469            </para>
470          </listitem>
471          <listitem>
472            <para>
473            Equal objects must have equal hash code
474            </para>
475          </listitem>
476          </orderedlist>
477          <para>
478            For objects in the database, the hash code is based on the id. For new objects,
479            which doesn't have an id yet, we fall back to the system hash code. But, what
480            happens when we save the new object to the database? If nobody has asked for
481            the hash code it is safe to use the id, otherwise we must stick with the system
482            hash code. Now, imagine that we load the same object from the database in
483            another Hibernate session. What will now happen? The loaded object will have
484            it's hash code based on the id but the original object is still using the
485            system hash code, which most likely is not the same as the id. Yet, the
486            <methodname>equals()</methodname> method returns true. This is a violation
487            of the contract for the equals method. If these two objects are used in a set
488            it may cause unexpected behaviour. Therefore, do not put new objects in a
489            set, or other collection, that calls the <methodname>hashCode()</methodname> 
490            method before the object is saved to the database.         
491          </para>
492        </warning>
493       
494        <para>
495        See also:
496        </para>
497        <itemizedlist>
498        <listitem>
499          <para>
500          "Hibernate in action", chapter 3.4 "Understanding object identity", page 87-90
501          </para>
502        </listitem>
503        <listitem>
504          <para>
505          "Hibernate in action", chapter 4.1.4 "The scope of object identity", page 119-121
506          </para>
507        </listitem>
508        <listitem>
509          <para>
510          "Hibernate in action", chapter 4.1.6 "Implementing equals() and hashCode(), page 122-126
511          </para>
512        </listitem>
513        <listitem>
514          <para>
515          Hibernate user documentation: <ulink 
516            url="http://www.hibernate.org/hib_docs/reference/en/html/persistent-classes.html#persistent-classes-equalshashcode">4.3. Implementing equals() and hashCode()</ulink>
517          </para>
518        </listitem>
519        </itemizedlist>
520      </sect3>
521
522      <sect3 id="core_ref.rules.datalayer.nofinal">
523        <title>No final methods</title>
524        <para>
525          No methods should be tagged with the <constant>final</constant> keyword. This is a
526          requirement to be able to use the proxy feature of Hibernate, which we need for
527          performance reasons.
528        </para>
529
530        <para>
531        See also:
532        </para>
533        <itemizedlist>
534        <listitem>
535          <para>
536          Hibernate user documentation: <ulink 
537            url="http://www.hibernate.org/hib_docs/reference/en/html/persistent-classes.html#persistent-classes-pojo-final">4.1.3. Prefer non-final classes</ulink>
538          </para>
539        </listitem>
540        <listitem>
541          <para>
542          Hibernate user documentation: <ulink 
543            url="http://www.hibernate.org/hib_docs/reference/en/html/performance.html#performance-fetching-proxies">19.1.3. Single-ended association proxies</ulink>
544          </para>
545        </listitem>
546        </itemizedlist>
547
548      </sect3>
549
550      <sect3 id="core_ref.rules.datalayer.cache">
551        <title>Second-level cache</title>
552        <para>
553          To gain performance we use the second-level cache of Hibernate. It is a transparent
554          feature that doesn't affect the code in any way. The second-level cache is configured
555          in the <filename>hibernate.cfg.xml</filename> and <filename>ehcache.xml</filename> 
556          files and not in the individual class mapping files. BASE is shipped with a standard
557          configuration, but different deployment scenarios may have to fine-tune the cache
558          settings for that particular hardware/software setup. It is beyond the scope of
559          this document to discuss this issue.
560        </para>
561       
562        <para>
563          The second-level cache is suitable for objects that are rarely modified but
564          are often needed. For example, we do not expect the user information represented
565          by the <classname docapi="net.sf.basedb.core.data">UserData</classname> object to change very often, but it is
566          displayed all the time as the owner of various items.
567        </para>
568       
569        <para>
570          It is required that one thinks a bit of the usage of a class before coming
571          up with a good caching strategy. We have to answer the following questions:
572        </para>
573       
574        <orderedlist>
575        <listitem>
576          <para>
577          Should objects of this class be cached at all?
578          </para>
579        </listitem>
580        <listitem>
581          <para>
582          How long timeout should we use?
583          </para>
584        </listitem>
585        <listitem>
586          <para>
587          How many objects should we keep in memory or on disk?
588          </para>
589        </listitem>
590        </orderedlist>
591       
592        <para>
593          The first question is the most important. Good candidates are classes with few
594          objects that change rarely, but are read often. Also, objects which are linked
595          to by many other objects are good candidates. The <classname docapi="net.sf.basedb.core.data">UserData</classname>
596          class is an example which matches all three requirements. The <classname docapi="net.sf.basedb.core.data">LabelData</classname>
597          class is an example which fulfils the first two. The <classname docapi="net.sf.basedb.core.data">BioMaterialEventData</classname>
598          class is on the other hand a bad cache candidate, since it is not linked to any
599          other object than a <classname docapi="net.sf.basedb.core.data">BioMaterialData</classname> object.
600        </para>
601       
602        <para>
603          The answer to the second question depends on how often an object is modified.
604          For most objects this time is probably several days or months, but we would
605          not gain much by keeping objects in the cache for so long. Suddenly, the
606          information has changed and we won't risk that old information is kept that
607          long. We have set the timeout to 1 hour for all classes so far, and we don't
608          recommend a longer timeout. The only exception is for immutable objects, that
609          cannot be changed at all, which may have an infinite timeout.
610        </para>
611       
612        <para>
613          The answer to the third question depends a lot on the hardware (available memory).
614          With lots of memory we can afford to cache more objects. Caching to disk is not
615          really necessary if the database is on the same machine as the web server, but
616          if it is on another machine we have to consider the network delay to connect
617          to the database versus the disk access time. The default configuration does not
618          use disk cache.
619        </para>
620
621        <para>
622        See also:
623        </para>
624        <itemizedlist>
625        <listitem>
626          <para>
627          "Hibernate in action", chapter 5.3 "Caching theory and practice", page 175-194.
628          </para>
629        </listitem>
630        <listitem>
631          <para>
632          Hibernate user documentation: <ulink 
633            url="http://www.hibernate.org/hib_docs/reference/en/html/performance.html#performance-cache">19.2. The Second Level Cache</ulink>
634          </para>
635        </listitem>
636        </itemizedlist>
637
638      </sect3>
639
640      <sect3 id="core_ref.rules.datalayer.proxies">
641        <title>Proxies</title>
642       
643        <para>
644          Proxies are also used to gain performance, and they may have some impact on
645          the code. Proxies are created at runtime (by Hibernate) as a subclass of the
646          actual class but are not populated with data until some method of the object
647          is called. The data is loaded from the database the first time a method other
648          than <methodname>getId()</methodname> is called. Thus, we can avoid loading
649          data that is not needed at a particular time.
650        </para>
651       
652        <para>
653          There can be a problem with using the <code>instanceof</code> operator with proxies
654          and the table-per-class-hierarchy mapping. For example, if we have the abstract
655          class <classname>Animal</classname> and subclasses <classname>Cat</classname>
656          and <classname>Dog</classname>. The proxy of an <classname>Animal</classname> is a
657          runtime generated subclass of <classname>Animal</classname>, since we do not know if it
658          is a <classname>Cat</classname> or <classname>Dog</classname>. So,
659          <code>x instanceof Dog</code> and <code>x instanceof Cat</code> would both return
660          false. If we hadn't used a proxy, at least one of them would always be true.
661        </para>
662       
663        <para>
664          Proxies are only used when a not-null object is linked with many-to-one or
665          one-to-one from another object. If we ask for a specific object by id, or by a
666          query, we will never get a proxy. Therefore, it only makes sense to enable
667          proxies for classes that can be linked from other classes. One-to-one links on
668          the primary key where null is allowed silently disables the proxy feature,
669          since Hibernate doesn't know if there is an object or not without querying
670          the database.
671        </para>
672       
673        <bridgehead>Proxy vs. cache</bridgehead>
674        <para>
675          The goal of a proxy and the second-level cache are the same: to avoid hitting the
676          database. It is perfectly possible to enable both proxies and the cache for a
677          class. Then we would start with a proxy and as soon as a method is called Hibernate
678          would look in the second-level cache. Only if it is not there it would be loaded
679          from the database. But, do we really need a proxy in the first place? Well, I think
680          it might be better to use only the cache or only proxies. But, this also makes it
681          even more important that the cache is configured correctly so there is a high
682          probability that the object is already in the cache.
683        </para>
684       
685        <para>
686          If a class has been configured to use the second-level cache, we recommend
687          that proxies are disabled. For child objects in a parent-child relationship proxies
688          should be disabled, since they have no other links to them than from the parent.
689          If a class can be linked as many-to-one from several other classes it makes sense
690          to enable proxies. If we have a long chain of many-to-one relations it may also make
691          sense to enable proxies at some level, even if the second-level cache is used.
692          In that case we only need to create one proxy instead of looking up several objects
693          in the cache. Also, think about how a particular class most commonly will be used
694          in a client application. For example, it is very common to display the name of the
695          owner of an item, but we are probably not interested in displaying quota
696          information for that user. So, it makes sense to put users in the second-level
697          cache and use proxies for quota information.
698        </para>
699       
700        <warning>
701          <title>Batchable classes and stateless sessions</title>
702          <para>
703            Starting with Hibernate 3.1 there is a new stateless session feature. A
704            stateless session has no first-level cache and doesn't use the second-level
705            cache either. This means that if we load an item with a stateless session
706            Hibernate will always traverse many-to-one and one-to-one associations and
707            load those objects as well, unless they are configured to use proxies.
708          </para>
709         
710          <para>
711            Stateless sessions are used by batchable items (reporters, raw data and features)
712            since they are many and we want to use as little memory as possible. Here it
713            is required that proxies are enabled for all items that are linked from any of
714            the batchable items, ie. <classname docapi="net.sf.basedb.core">RawBioAssay</classname>,
715            <classname docapi="net.sf.basedb.core">ReporterType</classname>,
716            <classname docapi="net.sf.basedb.core">ArrayDesignBlock</classname>, etc.
717            If we don't do this Hibernate will generate multiple additional select
718            statements for the same parent item which will affect performance
719            in a bad way.
720          </para>
721         
722          <para>
723            On the other hand, the proxies created from a stateless session cannot later
724            be initialised. We have to get the ID from the proxy and the load the object
725            using the regular session. But this can also results in lots of additional select
726            statements so if it is known before that we need some information it is recommended
727            that a FETCH JOIN is used so that we get fully initialized objects instead of
728            proxies to begin with.
729          </para>
730        </warning>
731       
732        <para>
733          Here is a table which summarises different settings for the second-level cache,
734          proxies, batch fetching and many-to-one links. Batch fetching and many-to-one links
735          are discussed later in this document.
736        </para>
737       
738        <para>
739          First, decide if the second-level cache should be enabled or not. Then, if
740          proxies should be enabled or not. The table then gives a reasonable setting for
741          the batch size and many-to-one mappings. NOTE! The many-to-one mappings are
742          the links from other classes to this one, not links from this class.
743        </para>
744       
745        <para>
746          The settings in this table are not absolute rules. In some cases there might
747          be a good reason for another combination. Please, write a comment about why
748          the recommendations were not followed.
749        </para>
750       
751        <table id="core_ref.rules.datalayer.cacheproxysettings">
752          <title>Choosing cache and proxy settings</title>
753          <tgroup cols="4">
754            <colspec colname="cache" />
755            <colspec colname="proxy" />
756            <colspec colname="batchsize" />
757            <colspec colname="outerjoin" />
758           
759            <thead>
760              <row>
761                <entry>Global configuration</entry>
762                <entry namest="proxy" nameend="batchsize">Class mapping</entry>
763                <entry>Many-to-one mapping</entry>
764              </row>
765              <row>
766                <entry>Cache</entry>
767                <entry>Proxy</entry>
768                <entry>Batch-size</entry>
769                <entry>Outer-join</entry>
770              </row>
771            </thead>
772            <tbody>
773              <row>
774                <entry>no</entry>
775                <entry>no*</entry>
776                <entry>yes</entry>
777                <entry>true</entry>
778              </row>
779              <row>
780                <entry>yes</entry>
781                <entry>no*</entry>
782                <entry>no</entry>
783                <entry>false</entry>
784              </row>
785              <row>
786                <entry>no</entry>
787                <entry>yes</entry>
788                <entry>yes</entry>
789                <entry>false</entry>
790              </row>
791              <row>
792                <entry>yes</entry>
793                <entry>yes</entry>
794                <entry>no</entry>
795                <entry>false</entry>
796              </row>
797            </tbody>
798          </tgroup>
799        </table>
800       
801        <para>
802          * = Do not use this setting for classes which are many-to-one linked from a batchable
803          class.
804        </para>
805       
806        <para>
807        See also:
808        </para>
809        <itemizedlist>
810        <listitem>
811          <para>
812          "Hibernate in action", chapter 4.4.6 "Selecting a fetching strategy in mappings", page 146-147
813          </para>
814        </listitem>
815        <listitem>
816          <para>
817          "Hibernate in action", chapter 6.4.1 "Polymorphic many-to-one associations", page 234-236
818          </para>
819        </listitem>
820        <listitem>
821          <para>
822          Hibernate user documentation: <ulink 
823            url="http://www.hibernate.org/hib_docs/reference/en/html/performance.html#performance-fetching-proxies">19.1.3. Single-ended association proxies</ulink>
824          </para>
825        </listitem>
826        </itemizedlist>
827       
828      </sect3>
829     
830      <sect3 id="core_ref.rules.datalayer.hibernate">
831        <title>Hibernate mappings</title>
832       
833        <para>
834          We use Javadoc tags to specify the database mapping needed by Hibernate.
835          The tags are processed by XDoclet at build time which generates the XML-based
836          Hibernate mapping files.
837        </para>
838       
839        <note>
840          <title>XDoclet doesn't support all mappings</title>
841          <para>
842          The XDoclet that we use was developed to generate mapping files for
843          Hibernate 2.x. Since then, Hibernate has released several 3.x versions,
844          and the mapping file structure has changed. Some changes can be handled by
845          generating a corresponding 2.x mapping and then converting it to a 3.x
846          mapping at build time using simple search-and-replace operations.
847          One such case is to update the DTD reference to the 3.0 version instead of
848          the 2.0 version. Other changes can't use this approach. Instead we have to
849          provide extra mappings inside an XML files. This is also needed if we need
850          to use some of the new 3.x features that has no 2.x counterpart.
851          </para>
852        </note>
853       
854        <simplesect id="core_ref.rules.datalayer.class">
855          <title>Class mapping</title>
856         
857          <programlisting language="java">
858/**
859   This class holds information about any data...
860   @author Your name
861   @version 2.0
862   @hibernate.class table="`Anys`" lazy="false" batch-size="10"
863   @base.modified $Date: 2007-08-17 09:18:29 +0200 (Fri, 17 Aug 2007) $
864*/
865public class AnyData
866   extends CommonData
867{
868   // Rest of class code...
869}
870</programlisting>
871         
872          <para>
873            The class declaration must contain a <code>@hibernate.class</code> Javadoc entry
874            where Hibernate can find the name of the table where items of this type are stored.
875            The table name should generally be the same as the class name, without the ending
876            <code>Data</code> and in a plural form. For example <classname docapi="net.sf.basedb.core.data">UserData</classname>
877            --&gt; <code>Users</code>. The back-ticks (`) around the table name tells Hibernate
878            to enclose the name in whatever the actual database manager uses for such things
879            (back-ticks in MySQL, quotes for an ANSI-compatible database).
880          </para>
881         
882          <important>
883            <title>Specify a value for the lazy attribute</title>
884            <para>
885              The lazy attribute enables/disables proxies for the class. Do not forget
886              to specify this attribute since the default value is true. If proxies are
887              enabled, it may also make sense to specify a batch-size attribute. Then
888              Hibernate will load the specified number of items in each SELECT statement
889              instead of loading them one by one. It may also make sense to specify a
890              batch size when proxies are disabled, but then it would probably be even
891              better to use eager fetching by setting <code>outer-join="true"</code>
892              (see many-to-one mapping).
893            </para>
894
895            <para>
896              Classes that are linked with a many-to-one association from a batchable
897              class must specify <code>lazy="true"</code>. Otherwise the stateless session
898              feature of Hibernate may result in a large number of SELECT:s for the same
899              item, or even circular loops if two or more items references each other.
900            </para>
901          </important>
902         
903          <important>
904            <title>Remember to enable the second-level cache</title>
905            <para>
906              Do not forget to configure settings for the second-level cache if this
907              should be enabled. This is done in the <filename>hibernate.cfg.xml</filename>
908              and <filename>ehcache.xml</filename>.
909            </para>
910          </important>
911       
912          <para>
913          See also:
914          </para>
915         
916          <itemizedlist>
917          <listitem>
918            <para>
919            "Hibernate in action", chapter 3.3 "Defining the mapping metadata", page 75-87
920            </para>
921          </listitem>
922          <listitem>
923            <para>
924            Hibernate user documentation: <ulink 
925              url="http://www.hibernate.org/hib_docs/reference/en/html/mapping.html#mapping-declaration-class">5.1.3. class</ulink>
926            </para>
927          </listitem>
928          </itemizedlist>
929         
930        </simplesect>
931       
932        <simplesect id="core_ref.rules.datalayer.property">
933          <title>Property mappings</title>
934         
935          <para>
936            Properties such as strings, integers, dates, etc. are mapped with
937            the <code>@hibernate.property</code> Javadoc tag. The main purpose
938            is to define the database column name. The column names should
939            generally be the same as the get/set method name without the get/set prefix,
940            and with upper-case letters converted to lower-case and an underscore inserted.
941            Examples:
942          </para>
943         
944          <itemizedlist>
945          <listitem>
946            <para>
947              <methodname>getAddress()</methodname>
948              --&gt; <code>column="`address`"</code>
949            </para>
950          </listitem>
951          <listitem>
952            <para>
953              <methodname>getLoginComment()</methodname>
954              --&gt; <code>column="`login_comment`"</code>
955            </para>
956          </listitem>
957          </itemizedlist>
958         
959          <para>
960            The back-ticks (`) around the column name tells Hibernate to enclose
961            the name in whatever the actual database manager uses for such things
962            (back-ticks in MySQL, quotes for an ANSI-compatible database).
963          </para>
964         
965          <bridgehead>String properties</bridgehead>
966         
967          <programlisting language="java">
968public static int long MAX_STRINGPROPERTY_LENGTH = 255;
969private String stringProperty;
970/**
971   Get the string property.
972   @hibernate.property column="`string_property`" type="string"
973      length="255" not-null="true"
974*/
975public String getStringProperty()
976{
977   return stringProperty;
978}
979public void setStringProperty(String stringProperty)
980{
981   this.stringProperty = stringProperty;
982}
983</programlisting>
984
985          <para>
986            Do not use a greater value than 255 for the length attribute. Some databases
987            has that as the maximum length for character columns (ie. MySQL). If you need
988            to store longer texts use <code>type="text"</code> instead. You can then skip
989            the length attribute. Most databases will allow up to 65535 characters or more
990            in a text field. Do not forget to specify the <code>not-null</code> attribute.
991          </para>
992         
993          <para>
994            You should also define a public constant <constant>MAX_STRINGPROPERTY_LENGTH</constant>
995            containing the maximum allowed length of the string.
996          </para>
997         
998          <bridgehead>Numerical properties</bridgehead>
999         
1000          <programlisting language="java">
1001private int intProperty;
1002/**
1003   Get the int property.
1004   @hibernate.property column="`int_property`" type="int" not-null="true"
1005*/
1006public int getIntProperty()
1007{
1008   return intProperty;
1009}
1010public void setIntProperty(int intProperty)
1011{
1012   this.intProperty = intProperty;
1013}
1014</programlisting>
1015
1016          <para>
1017            It is also possible to use <classname>Integer</classname>, <classname>Long</classname>
1018            or <classname>Float</classname> objects instead of <classname>int</classname>,
1019            <classname>long</classname> and <classname>float</classname>. We have only used it
1020            if null values have some meaning.
1021          </para>
1022
1023        <bridgehead>Boolean properties</bridgehead>
1024        <programlisting language="java">
1025private boolean booleanProperty;
1026/**
1027   Get the boolean property.
1028   @hibernate.property column="`boolean_property`"
1029      type="boolean" not-null="true"
1030*/
1031public boolean isBooleanProperty()
1032{
1033   return booleanProperty;
1034}
1035public void setBooleanProperty(boolean booleanProperty)
1036{
1037   this.booleanProperty = booleanProperty;
1038}
1039</programlisting>
1040        <para>
1041          It is also possible to use a <classname>Boolean</classname> object instead of
1042          <classname>boolean</classname>. It is only required if you absolutely need
1043          null values to handle special cases.
1044        </para>
1045       
1046        <bridgehead>Date values</bridgehead>
1047       
1048        <programlisting language="java">
1049private Date dateProperty;
1050/**
1051   Get the date property. Null is allowed.
1052   @hibernate.property column="`date_property`" type="date" not-null="false"
1053*/
1054public Date getDateProperty()
1055{
1056   return dateProperty;
1057}
1058public void setDateProperty(Date dateProperty)
1059{
1060   this.dateProperty = dateProperty;
1061}
1062</programlisting>
1063       
1064        <para>
1065          Hibernate defines several other date and time types. We have decided to use
1066          the <code>type="date"</code> type when we are only interested in the date and
1067          the <code>type="timestamp"</code> when we are interested in both the date
1068          and time.
1069        </para>
1070       
1071        <para>
1072        See also:
1073        </para>
1074       
1075        <itemizedlist>
1076          <listitem>
1077            <para>
1078            "Hibernate in action", chapter 3.3.2 "Basic property and class mappings", page 78-84
1079            </para>
1080          </listitem>
1081          <listitem>
1082            <para>
1083            "Hibernate in action", chapter 6.1.1 "Built-in mapping types", page 198-200
1084            </para>
1085          </listitem>
1086          <listitem>
1087            <para>
1088            Hibernate user documentation: <ulink 
1089              url="http://www.hibernate.org/hib_docs/reference/en/html/mapping.html#mapping-declaration-property">5.1.9. property</ulink>
1090            </para>
1091          </listitem>
1092          <listitem>
1093            <para>
1094            Hibernate user documentation: <ulink 
1095              url="http://www.hibernate.org/hib_docs/reference/en/html/mapping.html#mapping-types-basictypes">5.2.2. Basic value types</ulink>
1096            </para>
1097          </listitem>
1098          </itemizedlist>
1099         
1100        </simplesect>
1101       
1102        <simplesect id="core_ref.rules.datalayer.manytoone">
1103          <title>Many-to-one mappings</title>
1104         
1105          <programlisting language="java">
1106private OtherData other;
1107/**
1108   Get the other object.
1109   @hibernate.many-to-one column="`other_id`" not-null="true" outer-join="false"
1110*/
1111public OtherData getOther()
1112{
1113   return other;
1114}
1115public void setOther(OtherData other)
1116{
1117   this.other = other;
1118}
1119</programlisting>
1120         
1121        <para>
1122          We create a many-to-one mapping with the <code>@hibernate.many-to-one</code> tag.
1123          The most important attribute is the <code>column</code> attribute which specifies the name of
1124          the database column to use for the id of the other item. The back-ticks (`)
1125          around the column name tells Hibernate to enclose the name in whatever the
1126          actual database manager uses for such things (back-ticks in MySQL, quotes for
1127          an ANSI-compatible database).
1128        </para>
1129       
1130        <para>
1131          We also recommend that the <code>not-null</code> attribute is specified. Hibernate
1132          will not check for null values, but it will generate table columns that allow
1133          or disallow null values. See it as en extra safety feature while debugging.
1134          It is also used to determine if Hibernate uses <code>LEFT JOIN</code> or
1135          <code>INNER JOIN</code> in SQL statements.
1136        </para>
1137       
1138        <para>
1139          The <code>outer-join</code> attribute is important and affects how the
1140          cache and proxies are used. It can take three values: <constant>auto</constant>,
1141          <constant>true</constant> or <constant>false</constant>. If the value is
1142          <constant>true</constant> Hibernate will always use a join to load the linked
1143          object in a single select statement, overriding the cache and proxy settings.
1144          This value should only be used if the class being linked has disabled both
1145          proxies and the second-level cache, or if it is a link between a child
1146          and parent in a parent-child relationship. A false value is best when
1147          we expect the associated object to be in the second-level cache or proxying
1148          is enabled. This is probably the most common case. The auto setting uses a
1149          join if proxying is disabled otherwise it uses a proxy. Since we always
1150          know if proxying is enabled or not, this setting is not very useful. See
1151          <xref linkend="core_ref.rules.datalayer.cacheproxysettings" /> for the
1152          recommended settings.
1153        </para>
1154       
1155        <para>
1156          See also:
1157        </para>
1158         
1159        <itemizedlist>
1160          <listitem>
1161            <para>
1162            "Hibernate in action", chapter 3.7 "Introducing associations", page 105-112
1163            </para>
1164          </listitem>
1165          <listitem>
1166            <para>
1167            "Hibernate in action", chapter 4.4.5-4.4.6 "Fetching strategies", page 143-151
1168            </para>
1169          </listitem>
1170          <listitem>
1171            <para>
1172            "Hibernate in action", chapter 6.4.1 "Polymorphic many-to-one associations", page 234-236
1173            </para>
1174          </listitem>
1175          <listitem>
1176            <para>
1177            Hibernate user documentation: <ulink 
1178              url="http://www.hibernate.org/hib_docs/reference/en/html/mapping.html#mapping-declaration-manytoone">5.1.10. many-to-one</ulink>
1179            </para>
1180          </listitem>
1181          </itemizedlist>
1182         
1183        </simplesect>
1184       
1185        <simplesect id="core_ref.rules.datalayer.manytomany">
1186          <title>Many-to-many and one-to-many mappings</title>
1187         
1188          <para>
1189            There are many variants of mapping many-to-many or one-to-many, and it is
1190            not possible to give examples of all of them. In the code these mappings
1191            are represented by <classname>Set</classname>:s, <classname>Map</classname>:s,
1192            <classname>List</classname>:s, or some other collection object. The most
1193            important thing to remember is that (in our application) the collections
1194            are only used to maintain the links between objects. They are not used
1195            for returning objects to client applications, as is the case with the
1196            many-to-one mapping.
1197          </para>
1198         
1199          <para>
1200            For example, if we want to find all members of a group we do not use the
1201            <code>GroupData.getUsers()</code> method, instead we will execute a database query
1202            to retrieve them. The reason for this design is that the logged in user may
1203            not have access to all users and we must add a permission checking filter
1204            before returning the user objects to the client application. Using a query
1205            will also allow client applications to specify sorting and filtering options
1206            for the users that are returned.
1207          </para>
1208         
1209          <programlisting language="java">
1210// RoleData.java
1211private Set&lt;UserData&gt; users;
1212/**
1213   Many-to-many from roles to users
1214   @hibernate.set table="`UserRoles`" lazy="true"
1215   @hibernate.collection-key column="`role_id`"
1216   @hibernate.collection-many-to-many column="`user_id`"
1217      class="net.sf.basedb.core.data.UserData"
1218*/
1219public Set&lt;UserData&gt; getUsers()
1220{
1221   if (users == null) users = new HashSet&lt;UserData&gt;();
1222   return users;
1223}
1224void setUsers(Set&lt;UserData&gt; users)
1225{
1226   this.users = users;
1227}
1228</programlisting>
1229         
1230          <para>
1231            As you can see this mapping is a lot more complicated than what we have
1232            seen before. The most important thing is the <code>lazy</code> attribute.
1233            It tells Hibernate to delay the loading of the related objects until the set
1234            is accessed. If the value is false or missing, Hibernate will load all objects
1235            immediately. There is almost never a good reason to specify something other
1236            than <code>lazy="true"</code>.
1237          </para>
1238         
1239          <para>
1240            Another important thing to remember is that the get method must always return
1241            the same object that Hibernate passed to the set method. Otherwise, Hibernate
1242            will not be able to detect changes made to the collection and as a result
1243            will have to delete and then recreate all links. To ensure that the collection
1244            object is not changed we have made the <methodname>setUsers()</methodname> method
1245            package private, and the <methodname>getUsers()</methodname> will create a
1246            new <classname>HashSet</classname> for us only if Hibernate didn't pass one
1247            in the first place.
1248          </para>
1249         
1250          <para>
1251            Let's also have a look at the reverse mapping:
1252          </para>
1253         
1254          <programlisting language="java">
1255// UserData.java
1256private Set&lt;RoleData&gt; roles;
1257/**
1258   Many-to-many from users to roles
1259   @hibernate.set table="`UserRoles`" lazy="true"
1260   @hibernate.collection-key column="`user_id`"
1261   @hibernate.collection-many-to-many column="`role_id`"
1262      class="net.sf.basedb.core.data.RoleData"
1263*/
1264Set&lt;RoleData&gt; getRoles()
1265{
1266   return roles;
1267}
1268void setRoles(Set&lt;RoleData&gt; roles)
1269{
1270   this.roles = roles;
1271}
1272</programlisting>
1273
1274          <para>
1275            The only real difference here is that both the setter and the getter methods
1276            are package private. This is required because Hibernate will get confused if
1277            we modify both ends. Thus, we are forced to always add/remove users to/from
1278            the set in the <classname docapi="net.sf.basedb.core.data">GroupData</classname> object. The methods in the
1279            <classname docapi="net.sf.basedb.core.data">RoleData</classname> class are never used by us.
1280            Note that we do not have to check for null and create a new set since Hibernate
1281            will handle null values as an empty set.
1282          </para>
1283         
1284          <para>
1285            So, why do we need the second collection at all? It is never accessed
1286            except by Hibernate, and since it is lazy it will always be "empty".
1287            The answer is that we want to use the relation in HQL statements.
1288            For example:
1289          </para>
1290         
1291          <programlisting language="sql">
1292SELECT ... FROM GroupData grp WHERE grp.users ...
1293SELECT ... FROM UserData usr WHERE usr.groups ...
1294</programlisting>
1295         
1296          <para>
1297            Without the inverse mapping, it would not have been possible to execute
1298            the second HQL statement. The inverse mapping is also important in
1299            parent-child relationships, where it is used to cascade delete the children
1300            if a parent is deleted.
1301          </para>
1302
1303          <warning>
1304            <title>Do not use the inverse="true" setting</title>
1305            <para>
1306              Hibernate defines an <code>inverse="true"</code> setting that can be used with
1307              the <code>@hibernate.set</code> tag. If specified, Hibernate will ignore
1308              changes made to that collection. However, there is one problem with specifying
1309              this attribute. Hibernate doesn't delete entries in the association table,
1310              leading to foreign key violations if we try to delete a user. The only
1311              solutions are to skip the <code>inverse="true"</code> attribute or to
1312              manually delete the object from all collections on the non-inverse end.
1313              The first alternative is the most efficient since it only requires a
1314              single SQL statement. The second alternative must first load all associated
1315              objects and then issue a single delete statement for each association.
1316            </para>
1317           
1318            <para>
1319              In the "Hibernate in action" book they have a very different design
1320              where they recommend that changes are made in both collections. We don't
1321              have to do this since we are only interested in maintaining the links,
1322              which is always done in one of the collections.
1323            </para>
1324          </warning>
1325
1326          <bridgehead>Parent-child relationships</bridgehead>
1327
1328          <para>
1329            When one or more objects are tightly linked to some other object we talk
1330            about a parent-child relationship. This kind of relationship becomes important
1331            when we are about to delete a parent object. The children cannot exist
1332            without the parent so they must also be deleted. Luckily, Hibernate can
1333            do this for us if we specify a <code>cascade="delete"</code> option for the link.
1334            This example is a one-to-many link between client and help texts.
1335          </para>
1336
1337          <programlisting language="java">
1338// ClientData.java
1339private Set&lt;HelpData&gt; helpTexts;
1340/**
1341   This is the inverse end.
1342   @see HelpData#getClient()
1343   @hibernate.set lazy="true" inverse="true" cascade="delete"
1344   @hibernate.collection-key column="`client_id`"
1345   @hibernate.collection-one-to-many class="net.sf.basedb.core.data.HelpData"
1346*/
1347Set&lt;HelpData&gt; getHelpTexts()
1348{
1349   return helpTexts;
1350}
1351
1352void setHelpTexts(Set&lt;HelpData&gt; helpTexts)
1353{
1354   this.helpTexts = helpTexts;
1355}
1356
1357// HelpData.java
1358private ClientData client;
1359/**
1360   Get the client for this help text.
1361   @hibernate.many-to-one column="`client_id`" not-null="true"
1362      update="false" outer-join="false" unique-key="uniquehelp"
1363*/
1364public ClientData getClient()
1365{
1366   return client;
1367}
1368public void setClient(ClientData client)
1369{
1370   this.client = client;
1371}
1372</programlisting>
1373
1374          <para>
1375            This show both sides of the one-to-many mapping between parent and children.
1376            As you can see the <code>@hibernate.set</code> doesn't specify a table,
1377            since it is given by the <code>class</code> attribute of the
1378            <code>@hibernate.collection-one-to-many</code> tag.
1379          </para>
1380         
1381          <para>
1382            In a one-to-many mapping, it is always the "one" side that handles the
1383            link so the "many" side should always be mapped with <code>inverse="true"</code>.
1384          </para>
1385
1386          <bridgehead>Maps</bridgehead>
1387         
1388          <para>
1389            Another type of many-to-many mapping uses a <interfacename>Map</interfacename>
1390            for the collection. This kind of mapping is needed when the association between
1391            two objects needs additional data to be kept as part of the association.
1392            For example, the permission (stored as an integer value) given to users that
1393            are members of a project. Note that you should use a <interfacename>Set</interfacename>
1394            for mapping the inverse end.
1395          </para>
1396         
1397          <programlisting language="java">
1398// ProjectData.java
1399private Map&lt;UserData, Integer&gt; users;
1400/**
1401   Many-to-many mapping between projects and users including permission values.
1402   @hibernate.map table="`UserProjects`" lazy="true"
1403   @hibernate.collection-key column="`project_id`"
1404   @hibernate.index-many-to-many column="`user_id`"
1405      class="net.sf.basedb.core.data.UserData"
1406   @hibernate.collection-element column="`permission`" type="int" not-null="true"
1407*/
1408public Map&lt;UserData, Integer&gt; getUsers()
1409{
1410   if (users == null) users = new HashMap&lt;UserData, Integer&gt;();
1411   return users;
1412}
1413void setUsers(Map&lt;UserData, Integer&gt; users)
1414{
1415   this.users = users;
1416}
1417
1418// UserData.java
1419private Set&lt;ProjectData&gt; projects;
1420/**
1421   This is the inverse end.
1422   @see ProjectData#getUsers()
1423   @hibernate.set table="`UserProjects`" lazy="true"
1424   @hibernate.collection-key column="`user_id`"
1425   @hibernate.collection-many-to-many column="`project_id`"
1426      class="net.sf.basedb.core.data.ProjectData"
1427*/
1428Set&lt;ProjectData&gt; getProjects()
1429{
1430   return projects;
1431}
1432void setProjects(Set&lt;ProjectData&gt; projects)
1433{
1434   this.projects = projects;
1435}
1436</programlisting>
1437       
1438        <para>
1439          See also:
1440        </para>
1441       
1442        <itemizedlist>
1443          <listitem>
1444            <para>
1445            "Hibernate in action", chapter 3.7 "Introducing associations", page 105-112
1446            </para>
1447          </listitem>
1448          <listitem>
1449            <para>
1450            "Hibernate in action", chapter 6.2 "Mapping collections of value types", page 211-220
1451            </para>
1452          </listitem>
1453          <listitem>
1454            <para>
1455            "Hibernate in action", chapter 6.3.2 "Many-to-many associations", page 225-233
1456            </para>
1457          </listitem>
1458          <listitem>
1459            <para>
1460            Hibernate user documentation: <ulink 
1461              url="http://www.hibernate.org/hib_docs/reference/en/html/collections.html">Chapter 6. Collection Mapping</ulink>
1462            </para>
1463          </listitem>
1464          <listitem>
1465            <para>
1466            Hibernate user documentation: <ulink 
1467              url="http://www.hibernate.org/hib_docs/reference/en/html/example-parentchild.html">Chapter 21. Example: Parent/Child</ulink>
1468            </para>
1469          </listitem>
1470          </itemizedlist>
1471       
1472
1473        </simplesect>
1474       
1475        <simplesect id="core_ref.rules.datalayer.onetoone">
1476          <title>One-to-one mappings</title>
1477         
1478          <para>
1479            A one-to-one mapping can come in two different forms, depending on if both
1480            objects should have the same id or not. We start with the case were the objects
1481            can have different id:s and the link is done with an extra column in one of
1482            the tables. The example is from the mapping between hybridizations and
1483            arrayslides.
1484          </para>
1485         
1486          <programlisting language="java">
1487// HybridizationData.java
1488private ArraySlideData arrayslide;
1489/**
1490   Get the array slide
1491   @hibernate.many-to-one column="`arrayslide_id`" not-null="false" unique="true"
1492*/
1493public ArraySlideData getArraySlide()
1494{
1495   return arrayslide;
1496}
1497public void setArraySlide(ArraySlideData arrayslide)
1498{
1499   arrayslide.setHybridization(this);
1500   this.arrayslide = arrayslide;
1501}
1502
1503// ArraySlideData.java
1504private HybridizationData hybridization;
1505/**
1506   Get the hybridization
1507   @hibernate.one-to-one property-ref="arraySlide"
1508*/
1509public HybridizationData getHybridization()
1510{
1511   return hybridization;
1512}
1513void setHybridization(HybridizationData hybridization)
1514{
1515   this.hybridization = hybridization;
1516}         
1517</programlisting>
1518         
1519          <para>
1520            As you can see, we use the many-to-one mapping on with a <code>unique="true"</code>
1521            option for the hybridization. This will force the database to only allow the
1522            same array slide to be linked once. Also note that since, <code>not-null="false"</code>,
1523            null values are allowed and it doesn't matter which end of the relation that
1524            is inserted first into the database.
1525          </para>
1526          <para>
1527            For the array slide end we use a <code>@hibernate.one-to-one</code>
1528            mapping and specify the name of the property on the other end that we are
1529            linking to. Also, note that the we can only change the link with the
1530            <methodname>HybridizationData.setArraySlide()</methodname> method, and that
1531            this method also updates the other end.
1532          </para>
1533
1534          <para>
1535            The second form of a one-to-one mapping is used when both objects must
1536            have the same id (primary key). The example is from the mapping between users
1537            and passwords.
1538          </para>
1539         
1540          <programlisting language="java">
1541// UserData.java
1542/**
1543   @hibernate.id column="`id`" generator-class="foreign"
1544   @hibernate.generator-param name="property" value="password"
1545*/
1546public int getId()
1547{
1548   return super.getId();
1549}
1550private PasswordData password;
1551/**
1552   Get the password.
1553   @hibernate.one-to-one class="net.sf.basedb.core.data.PasswordData"
1554      cascade="all" outer-join="false" constrained="true"
1555*/
1556public PasswordData getPassword()
1557{
1558   if (password == null)
1559   {
1560      password = new PasswordData();
1561      password.setUser(this);
1562   }
1563   return password;
1564}
1565void setPassword(PasswordData user)
1566{
1567   this.password = password;
1568}
1569
1570// PasswordData.java
1571private UserData user;
1572/**
1573   Get the user.
1574   @hibernate.one-to-one class="net.sf.basedb.core.data.UserData"
1575*/
1576public UserData getUser()
1577{
1578   return user;
1579}
1580void setUser(UserData user)
1581{
1582   this.user = user;
1583}
1584</programlisting>
1585         
1586          <para>
1587            In this case, we use the <code>@hibernate.one-to-one</code> mapping
1588            in both classes. The <code>constrained="true"</code> tag in <classname docapi="net.sf.basedb.core.data">UserData</classname>
1589            tells Hibernate to always insert the password first, and then the user. The makes it
1590            possible to use the (auto-generated) id for the password as the id
1591            for the user. This is controlled by the mapping for the <methodname>UserData.getId()</methodname>
1592            method, which uses the <code>foreign</code> id generator. This generator will look
1593            at the password property, ie. call <methodname>getPassword().getId()</methodname>
1594            to find the id for the user. Also note the initialisation code and <code>cascade="all"</code>
1595            tag in the <methodname>UserData.getPassword()</methodname> method. This is need
1596            to avoid <classname>NullPointerException</classname>:s and to make sure everything
1597            is created and deleted properly.
1598          </para>
1599         
1600          <para>
1601            See also:
1602          </para>
1603         
1604        <itemizedlist>
1605          <listitem>
1606            <para>
1607            "Hibernate in action", chapter 6.3.1 "One-to-one association", page 220-225
1608            </para>
1609          </listitem>
1610          <listitem>
1611            <para>
1612            Hibernate user documentation: <ulink 
1613              url="http://www.hibernate.org/hib_docs/reference/en/html/mapping.html#mapping-declaration-onetoone">5.1.11. one-to-one</ulink>
1614            </para>
1615          </listitem>
1616          </itemizedlist>
1617         
1618        </simplesect>
1619       
1620      </sect3>
1621
1622      <sect3 id="core_ref.rules.datalayer.documentation">
1623        <title>Documentation</title>
1624
1625        <para>
1626          The data layer code needs documentation. A simple approach is used for
1627          Javadoc documentation
1628        </para>
1629       
1630        <simplesect id="core_ref.rules.datalayer.documentation.class">
1631          <title>Class documentation</title>
1632          <para>
1633            The documentation for the class doesn't have to be very lengthy. A single
1634            sentence is usually enough. Provide tags for the author, version, last modification date
1635            and a reference to the corresponding class in the <package>net.sf.basedb.core</package>
1636            package.
1637          </para>
1638         
1639          <programlisting language="java">
1640/**
1641   This class holds information about any items.
1642
1643   @author Your name
1644   @version 2.0
1645   @see net.sf.basedb.core.AnyItem
1646   @base.modified $Date: 2007-08-17 09:18:29 +0200 (Fri, 17 Aug 2007) $
1647   @hibernate.class table="`Anys`" lazy="false"
1648*/
1649public class AnyData
1650   extends CommonData
1651{
1652...
1653}
1654</programlisting>
1655         
1656        </simplesect>
1657       
1658        <simplesect id="core_ref.rules.datalayer.documentation.method">
1659          <title>Method documentation</title>
1660         
1661          <para>
1662          Write a short one-sentence description for all public getter methods. You do not
1663          have document the parameters or the setter methods, since it would just be a
1664          repetition. Methods defined by interfaces are documented in the interface class.
1665          You should not have to write any documentation for those methods.
1666          </para>
1667         
1668          <para>
1669            For the inverse end of an association, which has only package private methods,
1670            write a notice about this and provide a link to to non-inverse end.
1671          </para>
1672         
1673          <programlisting language="java">
1674// UserData.java
1675private String address;
1676/**
1677   Get the address for the user.
1678   @hibernate.property column="`address`" type="string" length="255"
1679*/
1680public String getAddress()
1681{
1682   return address;
1683}
1684public void setAddress(String address)
1685{
1686   this.address = address;
1687}
1688
1689private Set&lt;GroupData&gt; groups;
1690/**
1691   This is the inverse end.
1692   @see GroupData#getUsers()
1693   @hibernate.set table="`UserGroups`" lazy="true" inverse="true"
1694   @hibernate.collection-key column="`user_id`"
1695   @hibernate.collection-many-to-many column="`group_id`"
1696      class="net.sf.basedb.core.data.GroupData"
1697*/
1698Set&lt;GroupData&gt; getGroups()
1699{
1700   return groups;
1701}
1702void setGroups(Set&lt;GroupData&gt; groups)
1703{
1704   this.groups = groups;
1705}
1706</programlisting>
1707         
1708        </simplesect>
1709       
1710        <simplesect id="core_ref.rules.datalayer.documentation.field">
1711          <title>Field documentation</title>
1712          <para>
1713            Write a short one-sentence description for <code>public static final</code>
1714            fields. Private fields does not have to be documented.
1715          </para>
1716         
1717          <programlisting language="java">
1718/**
1719   The maximum length of the name of an item that can be
1720   stored in the database.
1721   @see #setName(String)
1722*/
1723public static int MAX_NAME_LENGTH = 255;
1724</programlisting>
1725
1726        </simplesect>
1727       
1728        <simplesect id="core_ref.rules.datalayer.documentation.uml">
1729          <title>UML diagram</title>
1730         
1731          <para>
1732            Groups of related classes should be included in an UML-like
1733            diagram to show how they are connected and work together.
1734            For example we group together users, groups, roles, etc. into an
1735            authentication UML diagram. It is also possible that a single class
1736            may appear in more than one diagram. For more information about
1737            how to create UML diagrams see
1738            <xref linkend="documentation.magicdraw" />.
1739          </para>
1740        </simplesect>
1741
1742       
1743      </sect3>
1744
1745    </sect2>
1746    <sect2 id="core_ref.rules.itemclass">
1747      <title>Item-class rules</title>
1748      <para>
1749        This documentation is only available in the old format.
1750        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/coding/item/index.html"
1751          >http://base.thep.lu.se/chrome/site/doc/historical/development/coding/item/index.html</ulink>
1752      </para>
1753    </sect2>   
1754    <sect2 id="core_ref.rules.batchclass">
1755      <title>Batch-class rules</title>
1756      <para>
1757        TODO
1758      </para>
1759    </sect2>   
1760    <sect2 id="core_ref.rules.testclass">
1761      <title>Test-class rules</title>
1762      <para>
1763        TODO
1764      </para>
1765    </sect2>   
1766  </sect1>
1767 
1768  <sect1 id="core_ref.coreinternals">
1769    <title>Internals of the Core API</title>
1770    <para>
1771      This documentation is only available in the old format.
1772      See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/index.html"
1773        >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/index.html</ulink>
1774    </para>
1775    <sect2 id="core_ref.authentication">
1776      <title>Authentication and sessions</title>
1777      <para>
1778        This documentation is only available in the old format.
1779        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/authentication.html"
1780          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/authentication.html</ulink>
1781      </para>
1782    </sect2>   
1783    <sect2 id="core_ref.accesspermissions">
1784      <title>Access permissions</title>
1785      <para>
1786        This documentation is only available in the old format.
1787        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/accesspermissions.html"
1788          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/accesspermissions.html</ulink>
1789      </para>
1790    </sect2>   
1791    <sect2 id="core_ref.datavalidation">
1792      <title>Data validation</title>
1793      <para>
1794        TODO
1795      </para>
1796    </sect2>   
1797    <sect2 id="core_ref.transactions">
1798      <title>Transaction handling</title>
1799      <para>
1800        TODO
1801      </para>
1802    </sect2>   
1803    <sect2 id="core_ref.crwd">
1804      <title>Create/read/write/delete operations</title>
1805      <para>
1806        This documentation is only available in the old format.
1807        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/itemhandling.html"
1808          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/itemhandling.html</ulink>
1809      </para>
1810    </sect2>   
1811    <sect2 id="core_ref.batch">
1812      <title>Batch operations</title>
1813      <para>
1814        This documentation is only available in the old format.
1815        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/batchprocessing.html"
1816          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/batchprocessing.html</ulink>
1817      </para>
1818    </sect2>   
1819    <sect2 id="core_ref.quota">
1820      <title>Quota</title>
1821      <para>
1822        TODO
1823      </para>
1824    </sect2>   
1825    <sect2 id="core_ref.pluginexecution">
1826      <title>Plugin execution / job queue</title>
1827      <para>
1828        This documentation is only available in the old format.
1829        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/plugins.html"
1830          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/plugins.html</ulink>
1831      </para>
1832    </sect2>   
1833  </sect1>
1834
1835</chapter>
Note: See TracBrowser for help on using the repository browser.