dbforumcategory.java
来自「Jive是基于JSP/JAVA技术构架的一个大型BBS论坛系统,这是Jive论坛」· Java 代码 · 共 1,544 行 · 第 1/4 页
JAVA
1,544 行
package com.jivesoftware.forum.database;import com.jivesoftware.forum.*;import com.jivesoftware.util.*;import java.util.*;import java.util.LinkedList;import java.util.Date;import java.sql.*;import java.io.IOException;/** * Database implementation of the ForumCategory interface. The SQL tree structure we * use is Joe Celko's. For more information, see: * http://searchdatabase.techtarget.com/tip/1,289483,sid13_gci537290,00.html. * <p> * The lft and rgt column values are responsible for defining the tree. * An example tree with the lft and rgt column values (respectively) is as * follows: <pre> * * (1,12) * / \ * (2,3) (4,11) * / | \ * / | \ * (5,6) (7,8) (9,10) * </pre> * * As you can see from the tree, the lft and rgt values of a child are * always between the values of its parent. We can use this property to * load the entire tree into memory using a single select. The simple way to * to determine the lft and rgt values of an arbitrary tree structure is to * label lft then rgt by traversing the tree in depth-first order. */public class DbForumCategory implements ForumCategory, Cacheable { /** DATABASE QUERIES **/ protected static final String FIND_FORUM_INDEX = "SELECT categoryIndex FROM jiveForum WHERE forumID=? AND categoryID=?"; protected static final String FORUM_IN_CATEGORY_COUNT = "SELECT count(categoryIndex) FROM jiveForum WHERE categoryID=?"; protected static final String SHIFT_FORUM_INDEX_1 = "UPDATE jiveForum SET categoryIndex=categoryIndex+1 WHERE categoryID=? " + "AND categoryIndex >= ? AND categoryIndex <?"; protected static final String SHIFT_FORUM_INDEX_2 = "UPDATE jiveForum SET categoryIndex=categoryIndex-1 WHERE categoryID=? " + "AND categoryIndex <= ? AND categoryIndex > ?"; protected static final String SHIFT_CATEGORY_INDEX_1 = "UPDATE jiveCategory SET lft=lft+?, rgt=rgt+? WHERE lft>=? AND lft<?"; protected static final String SHIFT_CATEGORY_INDEX_2 = "UPDATE jiveCategory SET lft=lft+?, rgt=rgt+? WHERE lft>? AND rgt>? AND rgt<=?"; private static final String SET_FORUM_INDEX = "UPDATE jiveForum SET categoryIndex=? WHERE forumID=?"; private static final String MOVE_FORUM = "UPDATE jiveForum SET categoryID=?, categoryIndex=? WHERE forumID=?"; private static final String LOAD_CATEGORY = "SELECT name, description, creationDate, modifiedDate, lft, rgt FROM " + "jiveCategory WHERE categoryID=?"; private static final String FIND_LFT_RGT = "SELECT lft, rgt FROM jiveCategory WHERE categoryID=?"; private static final String CHANGE_LFT = "UPDATE jiveCategory SET lft=lft+? WHERE lft > ? AND rgt > ?"; private static final String CHANGE_RGT = "UPDATE jiveCategory SET rgt=rgt+? WHERE rgt >= ?"; private static final String UPDATE_CATEGORY_MODIFIED_DATE = "UPDATE jiveCategory SET modifiedDate=? WHERE lft<? AND rgt>?"; private static final String INSERT_CATEGORY = "INSERT INTO jiveCategory(categoryID,name,description,creationDate," + "modifiedDate,lft,rgt) VALUES (?,?,?,?,?,?,?)"; private static final String SAVE_CATEGORY = "UPDATE jiveCategory SET name=?, description=?, creationDate=?, " + "modifiedDate=? WHERE categoryID=?"; private static final String DELETE_CATEGORY = "DELETE FROM jiveCategory WHERE categoryID=?"; private static final String LOAD_PROPERTIES = "SELECT name, propValue FROM jiveCategoryProp WHERE categoryID=?"; private static final String DELETE_PROPERTY = "DELETE FROM jiveCategoryProp WHERE categoryID=? AND name=?"; private static final String UPDATE_PROPERTY = "UPDATE jiveCategoryProp SET propValue=? WHERE name=? AND categoryID=?"; private static final String INSERT_PROPERTY = "INSERT INTO jiveCategoryProp(categoryID,name,propValue) VALUES(?,?,?)"; private static final String CATEGORY_COUNT = "SELECT count(*) FROM jiveCategory"; private static final String LOAD_CATEGORY_TREE = "SELECT categoryID, lft, rgt FROM jiveCategory ORDER BY lft ASC"; private static LongTree categoryTree; /** * Number of forumID's per cache block. */ public static final int BLOCK_SIZE = 50; // Constant for an empty bock. This is returned in the case that there are // no results when trying to load a thread or message block. private static final long[] EMPTY_BLOCK = new long[0]; // A ResultFilter is used to filter and sort the values that are returned // from the forums() method. private static final ResultFilter DEFAULT_FORUM_FILTER = ResultFilter.createDefaultForumFilter(); private static final long serialVersionUID = 01L; /** * Doing operations on the category tree is dangerious for databases without * transaction support. To help minimize the risk, we use a static lock * that must be acquired before modifying the tree. */ private static Object lock = new Object(); private long id; private String name; private String description; private Date creationDate; private Date modifiedDate; private Map properties; int lft; int rgt; // List to keep track of the keys that we insert into global caches. // Keeping track of the keys allows us to delete them from the caches // as necessary. private LinkedList queryKeys = new LinkedList(); private transient DbForumFactory factory; /** * Loads an existing category. * * @param id the ID of the category to load. * @throws ForumCategoryNotFoundException */ public DbForumCategory(long id) throws ForumCategoryNotFoundException { this.id = id; loadFromDb(); init(); } /** * Creates a new category. * * @param name the name of the new category. * @param description * @param parentCategory */ public DbForumCategory(String name, String description, DbForumCategory parentCategory) { this.id = SequenceManager.nextID(JiveGlobals.FORUM_CATEGORY); this.name = name; this.description = description; long now = System.currentTimeMillis(); creationDate = new java.util.Date(now); modifiedDate = new java.util.Date(now); insertIntoDb(parentCategory); properties = new Hashtable(); init(); } private void init() { factory = DbForumFactory.getInstance(); if (categoryTree == null) { refreshCategoryTree(); } } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); init(); } public long getID() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; saveToDb(); // Re-add category to cache. factory.cacheManager.categoryCache.put(new Long(this.id), this); } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; saveToDb(); // Re-add category to cache. factory.cacheManager.categoryCache.put(new Long(this.id), this); } public java.util.Date getCreationDate() { return creationDate; } public void setCreationDate(java.util.Date creationDate) { this.creationDate = creationDate; saveToDb(); // Re-add category to cache. factory.cacheManager.categoryCache.put(new Long(this.id), this); } public java.util.Date getModifiedDate() { return modifiedDate; } public void setModifiedDate(java.util.Date modifiedDate) throws UnauthorizedException { this.modifiedDate = modifiedDate; saveToDb(); // Re-add category to cache. factory.cacheManager.categoryCache.put(new Long(this.id), this); } public String getProperty(String name) { return (String)properties.get(name); } public void setProperty(String name, String value) { // Make sure the property name and value aren't null. if (name == null || value == null || "".equals(name) || "".equals(value)) { throw new NullPointerException("Cannot set property with empty or null value."); } // See if we need to update a property value or insert a new one. if (properties.containsKey(name)) { // Only update the value in the database if the property value // has changed. if (!(value.equals(properties.get(name)))) { properties.put(name, value); updatePropertyInDb(name, value); // Re-add category to cache. factory.cacheManager.categoryCache.put(new Long(this.id), this); } } else { properties.put(name, value); insertPropertyIntoDb(name, value); // Re-add category to cache. factory.cacheManager.categoryCache.put(new Long(this.id), this); } } public void deleteProperty(String name) throws UnauthorizedException { // Only delete the property if it exists. if (properties.containsKey(name)) { properties.remove(name); deletePropertyFromDb(name); // Re-add category to cache. factory.cacheManager.categoryCache.put(new Long(this.id), this); } } public Iterator propertyNames() { return Collections.unmodifiableSet(properties.keySet()).iterator(); } public int getForumCount() { return getForumCount(DEFAULT_FORUM_FILTER); } public int getForumCount(ResultFilter resultFilter) { String sql = getForumListSQL(resultFilter, true, false); QueryCacheKey key = new QueryCacheKey(JiveGlobals.FORUM_CATEGORY, id, sql, -1); return getCount(key); } public int getRecursiveForumCount() { return getRecursiveForumCount(DEFAULT_FORUM_FILTER); } public int getRecursiveForumCount(ResultFilter resultFilter) { String sql = getForumListSQL(resultFilter, true, true); QueryCacheKey key = new QueryCacheKey(JiveGlobals.FORUM_CATEGORY, id, sql, -1); return getCount(key); } public Iterator forums() { return forums(DEFAULT_FORUM_FILTER); } public Iterator forums(ResultFilter resultFilter) { String query = getForumListSQL(resultFilter, false, false); long [] forumBlock = getBlock(query.toString(), resultFilter.getStartIndex()); int startIndex = resultFilter.getStartIndex(); int endIndex; // If number of results is set to inifinite, set endIndex to the total // number of threads in the forum. if (resultFilter.getNumResults() == ResultFilter.NULL_INT) { endIndex = (int)getForumCount(resultFilter); } else { endIndex = resultFilter.getNumResults() + startIndex; } return new ForumBlockIterator(forumBlock, query.toString(), startIndex, endIndex, this.id, factory); } public Iterator recursiveForums() { return recursiveForums(DEFAULT_FORUM_FILTER); } public Iterator recursiveForums(ResultFilter resultFilter) { String query = getForumListSQL(resultFilter, false, true); long [] forumBlock = getBlock(query.toString(), resultFilter.getStartIndex()); int startIndex = resultFilter.getStartIndex(); int endIndex; // If number of results is set to inifinite, set endIndex to the total // number of threads in the forum. if (resultFilter.getNumResults() == ResultFilter.NULL_INT) { endIndex = (int)getRecursiveForumCount(resultFilter); } else { endIndex = resultFilter.getNumResults() + startIndex; } return new ForumBlockIterator(forumBlock, query.toString(), startIndex, endIndex, this.id, factory); } public void setForumIndex(Forum forum, int newIndex) { if (newIndex < 0 || newIndex > getForumCount() -1) { throw new IllegalArgumentException("Invalid index"); } Connection con = null; PreparedStatement pstmt = null; boolean abortTransaction = false; try { con = ConnectionManager.getTransactionConnection(); // First, find the old index value for the forum. pstmt = con.prepareStatement(FIND_FORUM_INDEX); pstmt.setLong(1, forum.getID()); pstmt.setLong(2, this.id); ResultSet rs = pstmt.executeQuery(); // If we didn't find a row, that means the forum does not belong // to the category. In that case, throw an exception. if (!rs.next()) { throw new IllegalArgumentException("Forum " + forum.getID() + " is not in category " + this.id); } int oldIndex = rs.getInt(1); pstmt.close(); // We need to shift the values of other forums to make room for // the new placement. if (newIndex < oldIndex) { pstmt = con.prepareStatement(SHIFT_FORUM_INDEX_1); } else { pstmt = con.prepareStatement(SHIFT_FORUM_INDEX_2); } pstmt.setLong(1, this.id); pstmt.setInt(2, newIndex); pstmt.setInt(3, oldIndex); pstmt.execute(); pstmt.close(); // Finally, update the actual entry. pstmt = con.prepareStatement(SET_FORUM_INDEX); pstmt.setInt(1, newIndex); pstmt.setLong(2, forum.getID()); pstmt.execute(); } catch (SQLException sqle) { sqle.printStackTrace(); abortTransaction = true; } finally { try { pstmt.close(); } catch (Exception e) { e.printStackTrace(); } ConnectionManager.closeTransactionConnection(con, abortTransaction); } // Expire cache. clearCache(); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?