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

Last change on this file since 4537 was 4537, checked in by Nicklas Nordborg, 14 years ago

Merged patch release 2.8.2 to the trunk

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