Jive is a famous open source forum. This time we will study the structure of its post. The Forum is composed of posts, followed by one or more replies. This is a typical tree structure, the branches and leaves are as follows: 1 | -- 3 | -- 4 | -- 6 | -- 5 Tree structures are widely used, such as Directory classification systems and menu systems. Therefore, we understand the application principles of jive, we can flexibly deal with the tree structure in our own system. Here we will mainly talk about using relational databases such as MySQL to store tree-structured data, and then expand it in memory. Later we will try to store tree-structured data using XML. There are three basic objects in jive: 1. Forum: forumid should be included in the forum Forum database; 2. Message: Post, the database should have messageid; 3. thread: thread is a hierarchy that represents a series of messages. it can be understood as the messages Directory, which is a "branch". The messages of a post is of course "leaf"; the difference between "branch" and "leaf" is: "branches" can also contain "branches" or "leaves", while "leaves" are independent elements. the typical tree data structure comes out. External, like messages, thread exists as an independent object and can be created and queried like a query post. Therefore, threadid should exist in the database. There are two ways to access the messages in the thread: 1. treewalker provides a tree-like view, which we will discuss in detail below; 2. iterator this is a flat view. As we know, relational databases are not good at storing tree-structured data. Therefore, once a relational database is used to store tree-structured data, there will be no more than n SQL query statements when accessing the query in the future, reduces the system speed. The most primitive solution is to do it on the code.ArticleThe code is divided into several parts and each part uses several digits. This method has obvious limitations. (unfortunately, this method was used by famous websites such as ebay when I wrote this article .) In jive, treewalker is used to establish a tree structure for the data in the database in the memory, and at the same time implement buffering, which greatly speeds up data access. The key here is its util class: Longtree is a class that provides functions such as creating, modifying, and accessing the tree structure of data: Public final class Longtree implements cacheable { // Use these three arrays to store data relations // We need to put our own data ID into the array keys. leftchildren and rightsiblings are the relationship between the array IDs of the record array keys. // Leftchildren stores the son rightsiblings and stores his brother (parallel 〕 Long [] keys; // Char arrays let us address get about 65 K nodes. Char [] leftchildren; Char [] rightsiblings; // Pointer to next available slot. Char nextindex = 2; /** * To construct a new tree, you only need to provide two parameters: the root data ID and the size of the tree structure. */ Public Longtree (long rootkey, int size ){ Keys = new long [size + 1]; Leftchildren = new char [size + 1]; Rightsiblings = new char [size + 1]; // New tree. The first element stores the provided parameter: Root data ID: rootkey. // New tree, so set the fields to null at root. Keys [1] = rootkey; Leftchildren [1] = 0; Rightsiblings [1] = 0; } /** * Adds a child to the tree. * * @ Param parentkey: the parent to which the new son is added. Therefore, you need to provide the father's data ID. * @ Param newkey: Data ID of the new son */ Public void addchild (long parentkey, long newkey ){ // Find record for parent check whether the provided father exists Char parentindex = findkey (parentkey, (char) 1 ); If (parentindex = 0 ){ Throw new illegalargumentexception ("parent key" + parentkey + "Not found when adding child" + newkey + "."); } // Create record for new key. The relationship before and after adding the array is set to 0. Keys [nextindex] = newkey; Leftchildren [nextindex] = 0; Rightsiblings [nextindex] = 0; // Adjust references. Check to see if the parent has any children. If (leftchildren [parentindex] = 0 ){ // No children, therefore make the new key the first child. Leftchildren [parentindex] = nextindex; } Else { // The parent has children, so find the right-most child. // If the father has a son, find the son on the rightmost side, similar to 6. // This is to append the new son to the back or to the far right of the new son. Long siblingindex = leftchildren [parentindex]; While (rightsiblings [New Long (siblingindex). intvalue ()]! = 0 ){ Siblingindex = rightsiblings [New Long (siblingindex). intvalue ()]; } // Add the new entry as a sibling of that last child. Rightsiblings [New Long (siblingindex). intvalue ()] = nextindex; } // Finally, increment nextindex so it's ready for next add. Nextindex ++; } ........... } From the above simple analysis of the method for adding a son to Longtree, we will probably understand the principle and usage of this class. Let's take a look at how treewalker uses Longtree. Treewalker has a subclass dbtreewalker: Let's first look at the database that stores tree-structured data: Create Table jivemessage ( Messageid bigint not null, Parentmessageid bigint null, # record the father of the current post Threadid bigint not null, # The threadid of the current post is the directory ID Forumid bigint not null, Userid bigint null, Subject varchar (255 ), Body text, .... ) We can see that the database mainly uses two fields to specify the relationship between such tree structure data. Let's take a look at how dbtreewalker uses Longtree to display the data stored in this database. Public class dbtreewalker implements treewalker { /** Database queries SQL statement **/ Private Static final string get_messages = "Select messageid, parentmessageid, creationdate from jivemessage" + "Where threadid =? And parentmessageid is not null "+ "Order by creationdate ASC "; ........ Private long threadid; Private dbforumfactory factory; // Use Longtree to generate an object. Private Longtree tree; /** * Treewalker Constructor */ Public dbtreewalker (dbforumthread thread, dbforumfactory factory ){ This. threadid = thread. GETID (); This. Factory = factory; Forummessage root = thread. getrootmessage (); Int nummessages = thread. getmessagecount (ignore_moderation_filter ); // Create the tree, set the root. Create a new tree Tree = new Longtree (root. GETID (), nummessages ); // Now, build the rest of the tree. Create the complete tree // Load all data in the current directory (current thread) to the tree in the database Connection con = NULL; Preparedstatement pstmt = NULL; Try { Con = connectionmanager. getconnection (); Pstmt = con. preparestatement (get_messages ); Pstmt. setlong (1, thread. GETID ()); Resultset rs = pstmt.exe cutequery (); While (Rs. Next ()){ Long messageid = Rs. getlong (1 ); Long parentmessageid = Rs. getlong (2 ); // Add son Tree. addchild (parentmessageid, messageid ); } } ..... } } ....... // You can easily get a post parent Public forummessage getparent (forummessage message) Throws forummessagenotfoundexception { ........ } // You can easily get the son of a post Public forummessage getchild (forummessage message, int index) Throws forummessagenotfoundexception { ........... } The cache technology is used in jive to ensure that frequently accessed trees can be stored in the memory. In short, we have found a combination of tree-structured data, relational databases, and object-oriented languages, it is worth learning from in practice. Source: www.jdon.com |