How to create a one-to-many relationship in XWiki?

Last modified by slauriere on 2015/09/03

Question How to create a one-to-many relationship in XWiki?
Answer

Many developers come with a relational database formation, thinking in tables and relations between them. While the default XWiki storage has a RDBMS for the backend, the abstract data inside XWiki is actually an object hierarchy: a set of documents, which have objects, which have properties. For more details, see the XWiki data model. There are no hard links between these entities, but like in a RDB, they have identifiers which are used to establish relations between them. With the help of these identifiers and the XWiki data model, new relations can be created between documents.

How to create a one-to-many relation: Let's assume you have different persons and projects, and you want to specify for each person the projects on which he worked or is working on.

  1. Create a new class which will hold the relation. If your application already has a main class for its datatype, you can use that one instead. Let's call it 1. Add a property of type Database List (DBListClass) to the class, called 1. Check the Multiple Select option, and optionally:
    • check the Relational Storage option if there will be persons with many projects or if you want to easily use this information in other queries
    • choose the Display Type
    • if the display type is 1*. define the Join Separator (", " is a good option)
  2. Define the query that will populate the list. This can be done in two ways: 1A. Using the XWiki Class Name, Id Field Name and Value Field Name properties: 1Aa. XWiki Class Name should be the name of the target class, in this case the class for projects, let's say 1Aa. Id Field Name should be the "foreign key" that will be stored in the database. Assuming that each project is stored in its own page, the name of the document holding the project object is a good choice: 1Aa. Value Field Name is the value that will be displayed to the user in the selection list, so the name of the project should be a good candidate. If it is stored as the document title, use 1A. Using the HQL query: 1Aa. While the previous approach is much simpler, a direct query gives more flexibility. Unlike the public 1Aa. A good example, doing what the previous approach does, using the projectName property as the value field, plus filtering out the project template document: 1Aa. Using the document title as the value field: 1. Display the list of projects in the person sheet (1. Display the list of persons working on a project in the project sheet (

#foreach($personDoc in $xwiki.wrapDocs($xwiki.searchDocuments(
    ", BaseObject obj, DBStringListProperty as projects join projects.list as project WHERE
    obj.name = doc.fullName AND projects.id.id = obj.id AND projects.id.name = 'projects'
    AND project = '${doc.fullName}'")))
  * $personDoc.title
  * or: $personDoc.use('My.PersonClass') $personDoc.display('personName', 'view')
#end

It is important to remember that the projects property does not hold real project objects, or project documents, but just the name of the documents holding the projects. To access the project objects, do something like:

#foreach($projectDoc in
    $xwiki.wrapDocs($doc.getObject('My.PersonClass').getProperty('projects').value))
  ## $projectDoc is now the document holding the project
  #set($projectObj = $projectDoc.getObject('My.ProjectClass'))
  ## $projectObj is now the xobject holding the project
  Do stuff with $projectDoc and $projectObj
#end
Tags:
Created by Sergiu Dumitriu on 2009/12/19
   

Get Connected