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

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

Fixes #1350: Update to Hibernate 3.3.2

Updated documentation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 64.0 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 5027 2009-07-28 09:29:51Z 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>,
718            <classname docapi="net.sf.basedb.core">ArrayDesignBlock</classname>, etc.
719            If we don't do this Hibernate will generate multiple additional select
720            statements for the same parent item which will affect performance
721            in a bad way.
722          </para>
723         
724          <para>
725            On the other hand, the proxies created from a stateless session cannot later
726            be initialised. We have to get the ID from the proxy and the load the object
727            using the regular session. But this can also results in lots of additional select
728            statements so if it is known before that we need some information it is recommended
729            that a FETCH JOIN is used so that we get fully initialized objects instead of
730            proxies to begin with.
731          </para>
732        </warning>
733       
734        <para>
735          Here is a table which summarises different settings for the second-level cache,
736          proxies, batch fetching and many-to-one links. Batch fetching and many-to-one links
737          are discussed later in this document.
738        </para>
739       
740        <para>
741          First, decide if the second-level cache should be enabled or not. Then, if
742          proxies should be enabled or not. The table then gives a reasonable setting for
743          the batch size and many-to-one mappings. NOTE! The many-to-one mappings are
744          the links from other classes to this one, not links from this class.
745        </para>
746       
747        <para>
748          The settings in this table are not absolute rules. In some cases there might
749          be a good reason for another combination. Please, write a comment about why
750          the recommendations were not followed.
751        </para>
752       
753        <table id="core_ref.rules.datalayer.cacheproxysettings">
754          <title>Choosing cache and proxy settings</title>
755          <tgroup cols="4">
756            <colspec colname="cache" />
757            <colspec colname="proxy" />
758            <colspec colname="batchsize" />
759            <colspec colname="outerjoin" />
760           
761            <thead>
762              <row>
763                <entry>Global configuration</entry>
764                <entry namest="proxy" nameend="batchsize">Class mapping</entry>
765                <entry>Many-to-one mapping</entry>
766              </row>
767              <row>
768                <entry>Cache</entry>
769                <entry>Proxy</entry>
770                <entry>Batch-size</entry>
771                <entry>Outer-join</entry>
772              </row>
773            </thead>
774            <tbody>
775              <row>
776                <entry>no</entry>
777                <entry>no*</entry>
778                <entry>yes</entry>
779                <entry>true</entry>
780              </row>
781              <row>
782                <entry>yes</entry>
783                <entry>no*</entry>
784                <entry>no</entry>
785                <entry>false</entry>
786              </row>
787              <row>
788                <entry>no</entry>
789                <entry>yes</entry>
790                <entry>yes</entry>
791                <entry>false</entry>
792              </row>
793              <row>
794                <entry>yes</entry>
795                <entry>yes</entry>
796                <entry>no</entry>
797                <entry>false</entry>
798              </row>
799            </tbody>
800          </tgroup>
801        </table>
802       
803        <para>
804          * = Do not use this setting for classes which are many-to-one linked from a batchable
805          class.
806        </para>
807       
808        <para>
809        See also:
810        </para>
811        <itemizedlist>
812        <listitem>
813          <para>
814          "Hibernate in action", chapter 4.4.6 "Selecting a fetching strategy in mappings", page 146-147
815          </para>
816        </listitem>
817        <listitem>
818          <para>
819          "Hibernate in action", chapter 6.4.1 "Polymorphic many-to-one associations", page 234-236
820          </para>
821        </listitem>
822        <listitem>
823          <para>
824          Hibernate user documentation: <ulink 
825            url="http://www.hibernate.org/hib_docs/reference/en/html/performance.html#performance-fetching-proxies">19.1.3. Single-ended association proxies</ulink>
826          </para>
827        </listitem>
828        </itemizedlist>
829       
830      </sect3>
831     
832      <sect3 id="core_ref.rules.datalayer.hibernate">
833        <title>Hibernate mappings</title>
834       
835        <para>
836          We use Javadoc tags to specify the database mapping needed by Hibernate.
837          The tags are processed by XDoclet at build time which generates the XML-based
838          Hibernate mapping files.
839        </para>
840       
841        <note>
842          <title>XDoclet doesn't support all mappings</title>
843          <para>
844          The XDoclet that we use was developed to generate mapping files for
845          Hibernate 2.x. Since then, Hibernate has released several 3.x versions,
846          and the mapping file structure has changed. Some changes can be handled by
847          generating a corresponding 2.x mapping and then converting it to a 3.x
848          mapping at build time using simple search-and-replace operations.
849          One such case is to update the DTD reference to the 3.0 version instead of
850          the 2.0 version. Other changes can't use this approach. Instead we have to
851          provide extra mappings inside an XML files. This is also needed if we need
852          to use some of the new 3.x features that has no 2.x counterpart.
853          </para>
854        </note>
855       
856        <simplesect id="core_ref.rules.datalayer.class">
857          <title>Class mapping</title>
858         
859          <programlisting language="java">
860/**
861   This class holds information about any data...
862   @author Your name
863   @version 2.0
864   @hibernate.class table="`Anys`" lazy="false" batch-size="10"
865   @base.modified $Date: 2007-08-17 09:18:29 +0200 (Fri, 17 Aug 2007) $
866*/
867public class AnyData
868   extends CommonData
869{
870   // Rest of class code...
871}
872</programlisting>
873         
874          <para>
875            The class declaration must contain a <code>@hibernate.class</code> Javadoc entry
876            where Hibernate can find the name of the table where items of this type are stored.
877            The table name should generally be the same as the class name, without the ending
878            <code>Data</code> and in a plural form. For example <classname docapi="net.sf.basedb.core.data">UserData</classname>
879            --&gt; <code>Users</code>. The back-ticks (`) around the table name tells Hibernate
880            to enclose the name in whatever the actual database manager uses for such things
881            (back-ticks in MySQL, quotes for an ANSI-compatible database).
882          </para>
883         
884          <important>
885            <title>Specify a value for the lazy attribute</title>
886            <para>
887              The lazy attribute enables/disables proxies for the class. Do not forget
888              to specify this attribute since the default value is true. If proxies are
889              enabled, it may also make sense to specify a batch-size attribute. Then
890              Hibernate will load the specified number of items in each SELECT statement
891              instead of loading them one by one. It may also make sense to specify a
892              batch size when proxies are disabled, but then it would probably be even
893              better to use eager fetching by setting <code>outer-join="true"</code>
894              (see many-to-one mapping).
895            </para>
896
897            <para>
898              Classes that are linked with a many-to-one association from a batchable
899              class must specify <code>lazy="true"</code>. Otherwise the stateless session
900              feature of Hibernate may result in a large number of SELECT:s for the same
901              item, or even circular loops if two or more items references each other.
902            </para>
903          </important>
904         
905          <important>
906            <title>Remember to enable the second-level cache</title>
907            <para>
908              Do not forget to configure settings for the second-level cache if this
909              should be enabled. This is done in the <filename>hibernate.cfg.xml</filename>
910              and <filename>ehcache.xml</filename>.
911            </para>
912          </important>
913       
914          <para>
915          See also:
916          </para>
917         
918          <itemizedlist>
919          <listitem>
920            <para>
921            "Hibernate in action", chapter 3.3 "Defining the mapping metadata", page 75-87
922            </para>
923          </listitem>
924          <listitem>
925            <para>
926            Hibernate user documentation: <ulink 
927              url="http://www.hibernate.org/hib_docs/reference/en/html/mapping.html#mapping-declaration-class">5.1.3. class</ulink>
928            </para>
929          </listitem>
930          </itemizedlist>
931         
932        </simplesect>
933       
934        <simplesect id="core_ref.rules.datalayer.property">
935          <title>Property mappings</title>
936         
937          <para>
938            Properties such as strings, integers, dates, etc. are mapped with
939            the <code>@hibernate.property</code> Javadoc tag. The main purpose
940            is to define the database column name. The column names should
941            generally be the same as the get/set method name without the get/set prefix,
942            and with upper-case letters converted to lower-case and an underscore inserted.
943            Examples:
944          </para>
945         
946          <itemizedlist>
947          <listitem>
948            <para>
949              <methodname>getAddress()</methodname>
950              --&gt; <code>column="`address`"</code>
951            </para>
952          </listitem>
953          <listitem>
954            <para>
955              <methodname>getLoginComment()</methodname>
956              --&gt; <code>column="`login_comment`"</code>
957            </para>
958          </listitem>
959          </itemizedlist>
960         
961          <para>
962            The back-ticks (`) around the column name tells Hibernate to enclose
963            the name in whatever the actual database manager uses for such things
964            (back-ticks in MySQL, quotes for an ANSI-compatible database).
965          </para>
966         
967          <bridgehead>String properties</bridgehead>
968         
969          <programlisting language="java">
970public static int long MAX_STRINGPROPERTY_LENGTH = 255;
971private String stringProperty;
972/**
973   Get the string property.
974   @hibernate.property column="`string_property`" type="string"
975      length="255" not-null="true"
976*/
977public String getStringProperty()
978{
979   return stringProperty;
980}
981public void setStringProperty(String stringProperty)
982{
983   this.stringProperty = stringProperty;
984}
985</programlisting>
986
987          <para>
988            Do not use a greater value than 255 for the length attribute. Some databases
989            has that as the maximum length for character columns (ie. MySQL). If you need
990            to store longer texts use <code>type="text"</code> instead. You can then skip
991            the length attribute. Most databases will allow up to 65535 characters or more
992            in a text field. Do not forget to specify the <code>not-null</code> attribute.
993          </para>
994         
995          <para>
996            You should also define a public constant <constant>MAX_STRINGPROPERTY_LENGTH</constant>
997            containing the maximum allowed length of the string.
998          </para>
999         
1000          <bridgehead>Numerical properties</bridgehead>
1001         
1002          <programlisting language="java">
1003private int intProperty;
1004/**
1005   Get the int property.
1006   @hibernate.property column="`int_property`" type="int" not-null="true"
1007*/
1008public int getIntProperty()
1009{
1010   return intProperty;
1011}
1012public void setIntProperty(int intProperty)
1013{
1014   this.intProperty = intProperty;
1015}
1016</programlisting>
1017
1018          <para>
1019            It is also possible to use <classname>Integer</classname>, <classname>Long</classname>
1020            or <classname>Float</classname> objects instead of <classname>int</classname>,
1021            <classname>long</classname> and <classname>float</classname>. We have only used it
1022            if null values have some meaning.
1023          </para>
1024
1025        <bridgehead>Boolean properties</bridgehead>
1026        <programlisting language="java">
1027private boolean booleanProperty;
1028/**
1029   Get the boolean property.
1030   @hibernate.property column="`boolean_property`"
1031      type="boolean" not-null="true"
1032*/
1033public boolean isBooleanProperty()
1034{
1035   return booleanProperty;
1036}
1037public void setBooleanProperty(boolean booleanProperty)
1038{
1039   this.booleanProperty = booleanProperty;
1040}
1041</programlisting>
1042        <para>
1043          It is also possible to use a <classname>Boolean</classname> object instead of
1044          <classname>boolean</classname>. It is only required if you absolutely need
1045          null values to handle special cases.
1046        </para>
1047       
1048        <bridgehead>Date values</bridgehead>
1049       
1050        <programlisting language="java">
1051private Date dateProperty;
1052/**
1053   Get the date property. Null is allowed.
1054   @hibernate.property column="`date_property`" type="date" not-null="false"
1055*/
1056public Date getDateProperty()
1057{
1058   return dateProperty;
1059}
1060public void setDateProperty(Date dateProperty)
1061{
1062   this.dateProperty = dateProperty;
1063}
1064</programlisting>
1065       
1066        <para>
1067          Hibernate defines several other date and time types. We have decided to use
1068          the <code>type="date"</code> type when we are only interested in the date and
1069          the <code>type="timestamp"</code> when we are interested in both the date
1070          and time.
1071        </para>
1072       
1073        <para>
1074        See also:
1075        </para>
1076       
1077        <itemizedlist>
1078          <listitem>
1079            <para>
1080            "Hibernate in action", chapter 3.3.2 "Basic property and class mappings", page 78-84
1081            </para>
1082          </listitem>
1083          <listitem>
1084            <para>
1085            "Hibernate in action", chapter 6.1.1 "Built-in mapping types", page 198-200
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-declaration-property">5.1.9. property</ulink>
1092            </para>
1093          </listitem>
1094          <listitem>
1095            <para>
1096            Hibernate user documentation: <ulink 
1097              url="http://www.hibernate.org/hib_docs/reference/en/html/mapping.html#mapping-types-basictypes">5.2.2. Basic value types</ulink>
1098            </para>
1099          </listitem>
1100          </itemizedlist>
1101         
1102        </simplesect>
1103       
1104        <simplesect id="core_ref.rules.datalayer.manytoone">
1105          <title>Many-to-one mappings</title>
1106         
1107          <programlisting language="java">
1108private OtherData other;
1109/**
1110   Get the other object.
1111   @hibernate.many-to-one column="`other_id`" not-null="true" outer-join="false"
1112*/
1113public OtherData getOther()
1114{
1115   return other;
1116}
1117public void setOther(OtherData other)
1118{
1119   this.other = other;
1120}
1121</programlisting>
1122         
1123        <para>
1124          We create a many-to-one mapping with the <code>@hibernate.many-to-one</code> tag.
1125          The most important attribute is the <code>column</code> attribute which specifies the name of
1126          the database column to use for the id of the other item. The back-ticks (`)
1127          around the column name tells Hibernate to enclose the name in whatever the
1128          actual database manager uses for such things (back-ticks in MySQL, quotes for
1129          an ANSI-compatible database).
1130        </para>
1131       
1132        <para>
1133          We also recommend that the <code>not-null</code> attribute is specified. Hibernate
1134          will not check for null values, but it will generate table columns that allow
1135          or disallow null values. See it as en extra safety feature while debugging.
1136          It is also used to determine if Hibernate uses <code>LEFT JOIN</code> or
1137          <code>INNER JOIN</code> in SQL statements.
1138        </para>
1139       
1140        <para>
1141          The <code>outer-join</code> attribute is important and affects how the
1142          cache and proxies are used. It can take three values: <constant>auto</constant>,
1143          <constant>true</constant> or <constant>false</constant>. If the value is
1144          <constant>true</constant> Hibernate will always use a join to load the linked
1145          object in a single select statement, overriding the cache and proxy settings.
1146          This value should only be used if the class being linked has disabled both
1147          proxies and the second-level cache, or if it is a link between a child
1148          and parent in a parent-child relationship. A false value is best when
1149          we expect the associated object to be in the second-level cache or proxying
1150          is enabled. This is probably the most common case. The auto setting uses a
1151          join if proxying is disabled otherwise it uses a proxy. Since we always
1152          know if proxying is enabled or not, this setting is not very useful. See
1153          <xref linkend="core_ref.rules.datalayer.cacheproxysettings" /> for the
1154          recommended settings.
1155        </para>
1156       
1157        <para>
1158          See also:
1159        </para>
1160         
1161        <itemizedlist>
1162          <listitem>
1163            <para>
1164            "Hibernate in action", chapter 3.7 "Introducing associations", page 105-112
1165            </para>
1166          </listitem>
1167          <listitem>
1168            <para>
1169            "Hibernate in action", chapter 4.4.5-4.4.6 "Fetching strategies", page 143-151
1170            </para>
1171          </listitem>
1172          <listitem>
1173            <para>
1174            "Hibernate in action", chapter 6.4.1 "Polymorphic many-to-one associations", page 234-236
1175            </para>
1176          </listitem>
1177          <listitem>
1178            <para>
1179            Hibernate user documentation: <ulink 
1180              url="http://www.hibernate.org/hib_docs/reference/en/html/mapping.html#mapping-declaration-manytoone">5.1.10. many-to-one</ulink>
1181            </para>
1182          </listitem>
1183          </itemizedlist>
1184         
1185        </simplesect>
1186       
1187        <simplesect id="core_ref.rules.datalayer.manytomany">
1188          <title>Many-to-many and one-to-many mappings</title>
1189         
1190          <para>
1191            There are many variants of mapping many-to-many or one-to-many, and it is
1192            not possible to give examples of all of them. In the code these mappings
1193            are represented by <classname>Set</classname>:s, <classname>Map</classname>:s,
1194            <classname>List</classname>:s, or some other collection object. The most
1195            important thing to remember is that (in our application) the collections
1196            are only used to maintain the links between objects. They are not used
1197            for returning objects to client applications, as is the case with the
1198            many-to-one mapping.
1199          </para>
1200         
1201          <para>
1202            For example, if we want to find all members of a group we do not use the
1203            <code>GroupData.getUsers()</code> method, instead we will execute a database query
1204            to retrieve them. The reason for this design is that the logged in user may
1205            not have access to all users and we must add a permission checking filter
1206            before returning the user objects to the client application. Using a query
1207            will also allow client applications to specify sorting and filtering options
1208            for the users that are returned.
1209          </para>
1210         
1211          <programlisting language="java">
1212// RoleData.java
1213private Set&lt;UserData&gt; users;
1214/**
1215   Many-to-many from roles to users
1216   @hibernate.set table="`UserRoles`" lazy="true"
1217   @hibernate.collection-key column="`role_id`"
1218   @hibernate.collection-many-to-many column="`user_id`"
1219      class="net.sf.basedb.core.data.UserData"
1220*/
1221public Set&lt;UserData&gt; getUsers()
1222{
1223   if (users == null) users = new HashSet&lt;UserData&gt;();
1224   return users;
1225}
1226void setUsers(Set&lt;UserData&gt; users)
1227{
1228   this.users = users;
1229}
1230</programlisting>
1231         
1232          <para>
1233            As you can see this mapping is a lot more complicated than what we have
1234            seen before. The most important thing is the <code>lazy</code> attribute.
1235            It tells Hibernate to delay the loading of the related objects until the set
1236            is accessed. If the value is false or missing, Hibernate will load all objects
1237            immediately. There is almost never a good reason to specify something other
1238            than <code>lazy="true"</code>.
1239          </para>
1240         
1241          <para>
1242            Another important thing to remember is that the get method must always return
1243            the same object that Hibernate passed to the set method. Otherwise, Hibernate
1244            will not be able to detect changes made to the collection and as a result
1245            will have to delete and then recreate all links. To ensure that the collection
1246            object is not changed we have made the <methodname>setUsers()</methodname> method
1247            package private, and the <methodname>getUsers()</methodname> will create a
1248            new <classname>HashSet</classname> for us only if Hibernate didn't pass one
1249            in the first place.
1250          </para>
1251         
1252          <para>
1253            Let's also have a look at the reverse mapping:
1254          </para>
1255         
1256          <programlisting language="java">
1257// UserData.java
1258private Set&lt;RoleData&gt; roles;
1259/**
1260   Many-to-many from users to roles
1261   @hibernate.set table="`UserRoles`" lazy="true"
1262   @hibernate.collection-key column="`user_id`"
1263   @hibernate.collection-many-to-many column="`role_id`"
1264      class="net.sf.basedb.core.data.RoleData"
1265*/
1266Set&lt;RoleData&gt; getRoles()
1267{
1268   return roles;
1269}
1270void setRoles(Set&lt;RoleData&gt; roles)
1271{
1272   this.roles = roles;
1273}
1274</programlisting>
1275
1276          <para>
1277            The only real difference here is that both the setter and the getter methods
1278            are package private. This is required because Hibernate will get confused if
1279            we modify both ends. Thus, we are forced to always add/remove users to/from
1280            the set in the <classname docapi="net.sf.basedb.core.data">GroupData</classname> object. The methods in the
1281            <classname docapi="net.sf.basedb.core.data">RoleData</classname> class are never used by us.
1282            Note that we do not have to check for null and create a new set since Hibernate
1283            will handle null values as an empty set.
1284          </para>
1285         
1286          <para>
1287            So, why do we need the second collection at all? It is never accessed
1288            except by Hibernate, and since it is lazy it will always be "empty".
1289            The answer is that we want to use the relation in HQL statements.
1290            For example:
1291          </para>
1292         
1293          <programlisting language="sql">
1294SELECT ... FROM GroupData grp WHERE grp.users ...
1295SELECT ... FROM UserData usr WHERE usr.groups ...
1296</programlisting>
1297         
1298          <para>
1299            Without the inverse mapping, it would not have been possible to execute
1300            the second HQL statement. The inverse mapping is also important in
1301            parent-child relationships, where it is used to cascade delete the children
1302            if a parent is deleted.
1303          </para>
1304
1305          <warning>
1306            <title>Do not use the inverse="true" setting</title>
1307            <para>
1308              Hibernate defines an <code>inverse="true"</code> setting that can be used with
1309              the <code>@hibernate.set</code> tag. If specified, Hibernate will ignore
1310              changes made to that collection. However, there is one problem with specifying
1311              this attribute. Hibernate doesn't delete entries in the association table,
1312              leading to foreign key violations if we try to delete a user. The only
1313              solutions are to skip the <code>inverse="true"</code> attribute or to
1314              manually delete the object from all collections on the non-inverse end.
1315              The first alternative is the most efficient since it only requires a
1316              single SQL statement. The second alternative must first load all associated
1317              objects and then issue a single delete statement for each association.
1318            </para>
1319           
1320            <para>
1321              In the "Hibernate in action" book they have a very different design
1322              where they recommend that changes are made in both collections. We don't
1323              have to do this since we are only interested in maintaining the links,
1324              which is always done in one of the collections.
1325            </para>
1326          </warning>
1327
1328          <bridgehead>Parent-child relationships</bridgehead>
1329
1330          <para>
1331            When one or more objects are tightly linked to some other object we talk
1332            about a parent-child relationship. This kind of relationship becomes important
1333            when we are about to delete a parent object. The children cannot exist
1334            without the parent so they must also be deleted. Luckily, Hibernate can
1335            do this for us if we specify a <code>cascade="delete"</code> option for the link.
1336            This example is a one-to-many link between client and help texts.
1337          </para>
1338
1339          <programlisting language="java">
1340// ClientData.java
1341private Set&lt;HelpData&gt; helpTexts;
1342/**
1343   This is the inverse end.
1344   @see HelpData#getClient()
1345   @hibernate.set lazy="true" inverse="true" cascade="delete"
1346   @hibernate.collection-key column="`client_id`"
1347   @hibernate.collection-one-to-many class="net.sf.basedb.core.data.HelpData"
1348*/
1349Set&lt;HelpData&gt; getHelpTexts()
1350{
1351   return helpTexts;
1352}
1353
1354void setHelpTexts(Set&lt;HelpData&gt; helpTexts)
1355{
1356   this.helpTexts = helpTexts;
1357}
1358
1359// HelpData.java
1360private ClientData client;
1361/**
1362   Get the client for this help text.
1363   @hibernate.many-to-one column="`client_id`" not-null="true"
1364      update="false" outer-join="false" unique-key="uniquehelp"
1365*/
1366public ClientData getClient()
1367{
1368   return client;
1369}
1370public void setClient(ClientData client)
1371{
1372   this.client = client;
1373}
1374</programlisting>
1375
1376          <para>
1377            This show both sides of the one-to-many mapping between parent and children.
1378            As you can see the <code>@hibernate.set</code> doesn't specify a table,
1379            since it is given by the <code>class</code> attribute of the
1380            <code>@hibernate.collection-one-to-many</code> tag.
1381          </para>
1382         
1383          <para>
1384            In a one-to-many mapping, it is always the "one" side that handles the
1385            link so the "many" side should always be mapped with <code>inverse="true"</code>.
1386          </para>
1387
1388          <bridgehead>Maps</bridgehead>
1389         
1390          <para>
1391            Another type of many-to-many mapping uses a <interfacename>Map</interfacename>
1392            for the collection. This kind of mapping is needed when the association between
1393            two objects needs additional data to be kept as part of the association.
1394            For example, the permission (stored as an integer value) given to users that
1395            are members of a project. Note that you should use a <interfacename>Set</interfacename>
1396            for mapping the inverse end.
1397          </para>
1398         
1399          <programlisting language="java">
1400// ProjectData.java
1401private Map&lt;UserData, Integer&gt; users;
1402/**
1403   Many-to-many mapping between projects and users including permission values.
1404   @hibernate.map table="`UserProjects`" lazy="true"
1405   @hibernate.collection-key column="`project_id`"
1406   @hibernate.index-many-to-many column="`user_id`"
1407      class="net.sf.basedb.core.data.UserData"
1408   @hibernate.collection-element column="`permission`" type="int" not-null="true"
1409*/
1410public Map&lt;UserData, Integer&gt; getUsers()
1411{
1412   if (users == null) users = new HashMap&lt;UserData, Integer&gt;();
1413   return users;
1414}
1415void setUsers(Map&lt;UserData, Integer&gt; users)
1416{
1417   this.users = users;
1418}
1419
1420// UserData.java
1421private Set&lt;ProjectData&gt; projects;
1422/**
1423   This is the inverse end.
1424   @see ProjectData#getUsers()
1425   @hibernate.set table="`UserProjects`" lazy="true"
1426   @hibernate.collection-key column="`user_id`"
1427   @hibernate.collection-many-to-many column="`project_id`"
1428      class="net.sf.basedb.core.data.ProjectData"
1429*/
1430Set&lt;ProjectData&gt; getProjects()
1431{
1432   return projects;
1433}
1434void setProjects(Set&lt;ProjectData&gt; projects)
1435{
1436   this.projects = projects;
1437}
1438</programlisting>
1439       
1440        <para>
1441          See also:
1442        </para>
1443       
1444        <itemizedlist>
1445          <listitem>
1446            <para>
1447            "Hibernate in action", chapter 3.7 "Introducing associations", page 105-112
1448            </para>
1449          </listitem>
1450          <listitem>
1451            <para>
1452            "Hibernate in action", chapter 6.2 "Mapping collections of value types", page 211-220
1453            </para>
1454          </listitem>
1455          <listitem>
1456            <para>
1457            "Hibernate in action", chapter 6.3.2 "Many-to-many associations", page 225-233
1458            </para>
1459          </listitem>
1460          <listitem>
1461            <para>
1462            Hibernate user documentation: <ulink 
1463              url="http://www.hibernate.org/hib_docs/reference/en/html/collections.html">Chapter 6. Collection Mapping</ulink>
1464            </para>
1465          </listitem>
1466          <listitem>
1467            <para>
1468            Hibernate user documentation: <ulink 
1469              url="http://www.hibernate.org/hib_docs/reference/en/html/example-parentchild.html">Chapter 21. Example: Parent/Child</ulink>
1470            </para>
1471          </listitem>
1472          </itemizedlist>
1473       
1474
1475        </simplesect>
1476       
1477        <simplesect id="core_ref.rules.datalayer.onetoone">
1478          <title>One-to-one mappings</title>
1479         
1480          <para>
1481            A one-to-one mapping can come in two different forms, depending on if both
1482            objects should have the same id or not. We start with the case were the objects
1483            can have different id:s and the link is done with an extra column in one of
1484            the tables. The example is from the mapping between hybridizations and
1485            arrayslides.
1486          </para>
1487         
1488          <programlisting language="java">
1489// HybridizationData.java
1490private ArraySlideData arrayslide;
1491/**
1492   Get the array slide
1493   @hibernate.many-to-one column="`arrayslide_id`" not-null="false" unique="true"
1494*/
1495public ArraySlideData getArraySlide()
1496{
1497   return arrayslide;
1498}
1499public void setArraySlide(ArraySlideData arrayslide)
1500{
1501   arrayslide.setHybridization(this);
1502   this.arrayslide = arrayslide;
1503}
1504
1505// ArraySlideData.java
1506private HybridizationData hybridization;
1507/**
1508   Get the hybridization
1509   @hibernate.one-to-one property-ref="arraySlide"
1510*/
1511public HybridizationData getHybridization()
1512{
1513   return hybridization;
1514}
1515void setHybridization(HybridizationData hybridization)
1516{
1517   this.hybridization = hybridization;
1518}         
1519</programlisting>
1520         
1521          <para>
1522            As you can see, we use the many-to-one mapping on with a <code>unique="true"</code>
1523            option for the hybridization. This will force the database to only allow the
1524            same array slide to be linked once. Also note that since, <code>not-null="false"</code>,
1525            null values are allowed and it doesn't matter which end of the relation that
1526            is inserted first into the database.
1527          </para>
1528          <para>
1529            For the array slide end we use a <code>@hibernate.one-to-one</code>
1530            mapping and specify the name of the property on the other end that we are
1531            linking to. Also, note that the we can only change the link with the
1532            <methodname>HybridizationData.setArraySlide()</methodname> method, and that
1533            this method also updates the other end.
1534          </para>
1535
1536          <para>
1537            The second form of a one-to-one mapping is used when both objects must
1538            have the same id (primary key). The example is from the mapping between users
1539            and passwords.
1540          </para>
1541         
1542          <programlisting language="java">
1543// UserData.java
1544/**
1545   @hibernate.id column="`id`" generator-class="foreign"
1546   @hibernate.generator-param name="property" value="password"
1547*/
1548public int getId()
1549{
1550   return super.getId();
1551}
1552private PasswordData password;
1553/**
1554   Get the password.
1555   @hibernate.one-to-one class="net.sf.basedb.core.data.PasswordData"
1556      cascade="all" outer-join="false" constrained="true"
1557*/
1558public PasswordData getPassword()
1559{
1560   if (password == null)
1561   {
1562      password = new PasswordData();
1563      password.setUser(this);
1564   }
1565   return password;
1566}
1567void setPassword(PasswordData user)
1568{
1569   this.password = password;
1570}
1571
1572// PasswordData.java
1573private UserData user;
1574/**
1575   Get the user.
1576   @hibernate.one-to-one class="net.sf.basedb.core.data.UserData"
1577*/
1578public UserData getUser()
1579{
1580   return user;
1581}
1582void setUser(UserData user)
1583{
1584   this.user = user;
1585}
1586</programlisting>
1587         
1588          <para>
1589            In this case, we use the <code>@hibernate.one-to-one</code> mapping
1590            in both classes. The <code>constrained="true"</code> tag in <classname docapi="net.sf.basedb.core.data">UserData</classname>
1591            tells Hibernate to always insert the password first, and then the user. The makes it
1592            possible to use the (auto-generated) id for the password as the id
1593            for the user. This is controlled by the mapping for the <methodname>UserData.getId()</methodname>
1594            method, which uses the <code>foreign</code> id generator. This generator will look
1595            at the password property, ie. call <methodname>getPassword().getId()</methodname>
1596            to find the id for the user. Also note the initialisation code and <code>cascade="all"</code>
1597            tag in the <methodname>UserData.getPassword()</methodname> method. This is need
1598            to avoid <classname>NullPointerException</classname>:s and to make sure everything
1599            is created and deleted properly.
1600          </para>
1601         
1602          <para>
1603            See also:
1604          </para>
1605         
1606        <itemizedlist>
1607          <listitem>
1608            <para>
1609            "Hibernate in action", chapter 6.3.1 "One-to-one association", page 220-225
1610            </para>
1611          </listitem>
1612          <listitem>
1613            <para>
1614            Hibernate user documentation: <ulink 
1615              url="http://www.hibernate.org/hib_docs/reference/en/html/mapping.html#mapping-declaration-onetoone">5.1.11. one-to-one</ulink>
1616            </para>
1617          </listitem>
1618          </itemizedlist>
1619         
1620        </simplesect>
1621       
1622      </sect3>
1623
1624      <sect3 id="core_ref.rules.datalayer.documentation">
1625        <title>Documentation</title>
1626
1627        <para>
1628          The data layer code needs documentation. A simple approach is used for
1629          Javadoc documentation
1630        </para>
1631       
1632        <simplesect id="core_ref.rules.datalayer.documentation.class">
1633          <title>Class documentation</title>
1634          <para>
1635            The documentation for the class doesn't have to be very lengthy. A single
1636            sentence is usually enough. Provide tags for the author, version, last modification date
1637            and a reference to the corresponding class in the <package>net.sf.basedb.core</package>
1638            package.
1639          </para>
1640         
1641          <programlisting language="java">
1642/**
1643   This class holds information about any items.
1644
1645   @author Your name
1646   @version 2.0
1647   @see net.sf.basedb.core.AnyItem
1648   @base.modified $Date: 2007-08-17 09:18:29 +0200 (Fri, 17 Aug 2007) $
1649   @hibernate.class table="`Anys`" lazy="false"
1650*/
1651public class AnyData
1652   extends CommonData
1653{
1654...
1655}
1656</programlisting>
1657         
1658        </simplesect>
1659       
1660        <simplesect id="core_ref.rules.datalayer.documentation.method">
1661          <title>Method documentation</title>
1662         
1663          <para>
1664          Write a short one-sentence description for all public getter methods. You do not
1665          have document the parameters or the setter methods, since it would just be a
1666          repetition. Methods defined by interfaces are documented in the interface class.
1667          You should not have to write any documentation for those methods.
1668          </para>
1669         
1670          <para>
1671            For the inverse end of an association, which has only package private methods,
1672            write a notice about this and provide a link to to non-inverse end.
1673          </para>
1674         
1675          <programlisting language="java">
1676// UserData.java
1677private String address;
1678/**
1679   Get the address for the user.
1680   @hibernate.property column="`address`" type="string" length="255"
1681*/
1682public String getAddress()
1683{
1684   return address;
1685}
1686public void setAddress(String address)
1687{
1688   this.address = address;
1689}
1690
1691private Set&lt;GroupData&gt; groups;
1692/**
1693   This is the inverse end.
1694   @see GroupData#getUsers()
1695   @hibernate.set table="`UserGroups`" lazy="true" inverse="true"
1696   @hibernate.collection-key column="`user_id`"
1697   @hibernate.collection-many-to-many column="`group_id`"
1698      class="net.sf.basedb.core.data.GroupData"
1699*/
1700Set&lt;GroupData&gt; getGroups()
1701{
1702   return groups;
1703}
1704void setGroups(Set&lt;GroupData&gt; groups)
1705{
1706   this.groups = groups;
1707}
1708</programlisting>
1709         
1710        </simplesect>
1711       
1712        <simplesect id="core_ref.rules.datalayer.documentation.field">
1713          <title>Field documentation</title>
1714          <para>
1715            Write a short one-sentence description for <code>public static final</code>
1716            fields. Private fields does not have to be documented.
1717          </para>
1718         
1719          <programlisting language="java">
1720/**
1721   The maximum length of the name of an item that can be
1722   stored in the database.
1723   @see #setName(String)
1724*/
1725public static int MAX_NAME_LENGTH = 255;
1726</programlisting>
1727
1728        </simplesect>
1729       
1730        <simplesect id="core_ref.rules.datalayer.documentation.uml">
1731          <title>UML diagram</title>
1732         
1733          <para>
1734            Groups of related classes should be included in an UML-like
1735            diagram to show how they are connected and work together.
1736            For example we group together users, groups, roles, etc. into an
1737            authentication UML diagram. It is also possible that a single class
1738            may appear in more than one diagram. For more information about
1739            how to create UML diagrams see
1740            <xref linkend="documentation.magicdraw" />.
1741          </para>
1742        </simplesect>
1743
1744       
1745      </sect3>
1746
1747    </sect2>
1748    <sect2 id="core_ref.rules.itemclass">
1749      <title>Item-class rules</title>
1750      <para>
1751        This documentation is only available in the old format.
1752        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/coding/item/index.html"
1753          >http://base.thep.lu.se/chrome/site/doc/historical/development/coding/item/index.html</ulink>
1754      </para>
1755    </sect2>   
1756    <sect2 id="core_ref.rules.batchclass">
1757      <title>Batch-class rules</title>
1758      <para>
1759        TODO
1760      </para>
1761    </sect2>   
1762    <sect2 id="core_ref.rules.testclass">
1763      <title>Test-class rules</title>
1764      <para>
1765        TODO
1766      </para>
1767    </sect2>   
1768  </sect1>
1769 
1770  <sect1 id="core_ref.coreinternals">
1771    <title>Internals of the Core API</title>
1772    <para>
1773      This documentation is only available in the old format.
1774      See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/index.html"
1775        >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/index.html</ulink>
1776    </para>
1777    <sect2 id="core_ref.authentication">
1778      <title>Authentication and sessions</title>
1779      <para>
1780        This documentation is only available in the old format.
1781        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/authentication.html"
1782          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/authentication.html</ulink>
1783      </para>
1784    </sect2>   
1785    <sect2 id="core_ref.accesspermissions">
1786      <title>Access permissions</title>
1787      <para>
1788        This documentation is only available in the old format.
1789        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/accesspermissions.html"
1790          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/accesspermissions.html</ulink>
1791      </para>
1792    </sect2>   
1793    <sect2 id="core_ref.datavalidation">
1794      <title>Data validation</title>
1795      <para>
1796        TODO
1797      </para>
1798    </sect2>   
1799    <sect2 id="core_ref.transactions">
1800      <title>Transaction handling</title>
1801      <para>
1802        TODO
1803      </para>
1804    </sect2>   
1805    <sect2 id="core_ref.crwd">
1806      <title>Create/read/write/delete operations</title>
1807      <para>
1808        This documentation is only available in the old format.
1809        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/itemhandling.html"
1810          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/itemhandling.html</ulink>
1811      </para>
1812    </sect2>   
1813    <sect2 id="core_ref.batch">
1814      <title>Batch operations</title>
1815      <para>
1816        This documentation is only available in the old format.
1817        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/batchprocessing.html"
1818          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/batchprocessing.html</ulink>
1819      </para>
1820    </sect2>   
1821    <sect2 id="core_ref.quota">
1822      <title>Quota</title>
1823      <para>
1824        TODO
1825      </para>
1826    </sect2>   
1827    <sect2 id="core_ref.pluginexecution">
1828      <title>Plugin execution / job queue</title>
1829      <para>
1830        This documentation is only available in the old format.
1831        See <ulink url="http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/plugins.html"
1832          >http://base.thep.lu.se/chrome/site/doc/historical/development/overview/core/plugins.html</ulink>
1833      </para>
1834    </sect2>   
1835  </sect1>
1836
1837</chapter>
Note: See TracBrowser for help on using the repository browser.