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

Last change on this file since 3715 was 3715, checked in by Nicklas Nordborg, 15 years ago

References #746 and #554. Added new new UML file for MagicDraw? 12.5. Updated documentation about
how to use MagicDraw?. Transfered some of the old data layer documentation to docbook.

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