⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keykeeper.java

📁 jGossip是一个简单而功能强大的Java论坛软件(消息板)
💻 JAVA
字号:
/*
 * $Id: KeyKeeper.java,v 1.5 2004/06/29 00:23:29 alexnet Exp $
 *
 * ***** BEGIN LICENSE BLOCK *****
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in 
 * compliance with the License. You may obtain a copy of the License 
 * at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and 
 * limitations under the License.
 *
 * The Original Code is JGossip forum code.
 *
 * The Initial Developer of the Original Code is the JResearch, Org. 
 * Portions created by the Initial Developer are Copyright (C) 2004 
 * the Initial Developer. All Rights Reserved. 
 * 
 * Contributor(s): 
 *              Alexey Pavlov <alexnet@users.sourceforge.net>
 *        
 * ***** END LICENSE BLOCK ***** */
package org.jresearch.gossip.dao.drivers.keygen;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jresearch.gossip.exception.ConfiguratorException;

/**
 * This class provides generated keys.
 * 
 * With this method, there's a multi-row table which has two columns,
 * one for the identifier for the table name, and another for the next
 * key value for that table.
 * In this variation, a grab size is specified to get a block of 
 * keys to reduce database accesses.
 *
 * @author <a href="alexnet@sourceforge.net">A. Pavlov</a>
 * @version $version$ $Date: 2004/06/29 00:23:29 $
 */
public class KeyKeeper {

	/**
	 * Logger instance.
	 */
	private static final Log LOG = LogFactory.getLog(HighLowKeyGenerator.class);
	
	private static final String DATA_TYPE = "DATA_TYPE";
	
	private static int increment = -1;
	private int columnType = -1;

	/**
	 * The high value is combined with the low value to
	 * produce the key.
	 */
	Object high;
	int low;

	String[] primaryKey;

	/**
	 * The key is generated for this table.
	 */
	String tableName;

	KeyKeeper(String tableName, String[] primaryKey) {
		this.tableName = tableName;
		this.primaryKey = primaryKey;
	}

	/**
	 * Obtains a block of available keys from the key-values table.
	 *
	 * @return the value beyond the block of available keys,
	 * @exception PersistenceException if an error occurs
	 */
	Object fetchHigh(Connection connection) throws SQLException {
		Object identity = null;

		String tableColumn;
		String table;
		String keyColumn;
		try {
			//Get the name of the table used to store two columns. 
			table =
				KeyGeneratorFactory.conf.get(IKeyGenConst.KEY_KEEPER_TABLE_NAME);
			//column name for identifier  for table name 
			tableColumn =
				KeyGeneratorFactory.conf.get(IKeyGenConst.KEY_KEEPER_TABLE_COLUMN);
			//column name for the next key for that table
			keyColumn =
				KeyGeneratorFactory.conf.get(IKeyGenConst.KEY_KEEPER_KEY_COLUMN);
		} catch (ConfiguratorException ce) {
			if(LOG.isErrorEnabled()) {
				LOG.error("Configurator error. Check your config files. Cause: ", ce);
			}
			// Nothing we can do - configuration info corrupted or incomplete.
			// set default values here:
			table = "JRF_KEY_KEEPER";
			tableColumn = "table_name";
			keyColumn = "next_key";
		}
		StringBuffer condition = new StringBuffer();
		condition.append(tableColumn + " = ?");

		ResultSet rs = null;
		PreparedStatement pstmt = null;
		PreparedStatement pstmt2 = null;
		try {
			//TODO: start db transaction here, if it is available

			// First get column type of key.
			if (columnType == -1) {
				columnType = getColumnType(connection, table, keyColumn);
			}

			if (columnType != java.sql.Types.INTEGER
				&& columnType != java.sql.Types.NUMERIC
				&& columnType != java.sql.Types.DECIMAL) {
				throw new SQLException(
					MessageFormat.format(
						"Key keeper has a SQL type[{0}] of key column[{1}]",
						new Object[] { new Integer(columnType), keyColumn }));

			}

			String sql = getStatement(keyColumn, table, condition.toString());
			pstmt = connection.prepareStatement(sql);
			pstmt.setString(1, tableName);

			rs = pstmt.executeQuery();

			// Count of records updated by SQL database
			int count = 0;
			if (rs.next()) {
				Object lastIdentity = rs.getObject(1);
				rs.close();

				if (columnType == java.sql.Types.INTEGER) {
					identity =
						new Integer(
							((Number) lastIdentity).intValue() + getGrabSize());
				} else {
					identity =
						new BigDecimal(
							((Number) lastIdentity).doubleValue() + getGrabSize());
				}

				condition.append(" and " + keyColumn + "=?");

				// Update value 
				sql = getUpdateStatement(keyColumn, table, condition.toString());
				pstmt2 = connection.prepareStatement(sql);
				pstmt2.setObject(1, identity);
				pstmt2.setString(2, tableName);
				pstmt2.setObject(3, lastIdentity);
				count = pstmt2.executeUpdate();
			}

			if (count < 1)
				throw new SQLException("persist.highlowFailed");
			if (connection.getAutoCommit() == false) {
				connection.commit();
			}
		} catch (SQLException sqle) {
			LOG.error("persist.highlowFailed", sqle);
		} finally {
			try {
				if (rs != null)
					rs.close();

				if (pstmt != null) {
					pstmt.close();
				}
				pstmt = null;

				if (pstmt2 != null) {
					pstmt2.close();
				}
				pstmt2 = null;

			} catch (SQLException excep) {
				// We can safely ignore all SQLException here, since we are not in the position
				// to do much about it anyway.
			}
		}

		return identity;
	}

	private final int getColumnType(Connection conn, String table, String column)
				throws SQLException 
	{
		return java.sql.Types.INTEGER;
/*		
		ResultSet rs = null;
		try {
			// Using meta data because many DBMS can not
			// pre-compile statements.
			DatabaseMetaData dmd = conn.getMetaData();
			//TODO: //provide concrete references to tablespace.
			// jgossip%
			rs = dmd.getColumns(null, null, primaryKey[0].toUpperCase(), primaryKey[1].toUpperCase());
			synchronized (this) {
				if (rs.next()) {
					return rs.getInt(DATA_TYPE);
				}
				throw new SQLException(
					"mapping.checkKeyGen",
					getClass().getName());
			}
		} finally {
			if (rs != null) {
				rs.close();
				rs = null;
			}
		}
*/		
	}

	private final String getStatement(
		String column,
		String table,
		String condition) {
		//todo: make it tunable.
		final String sql = "SELECT {0} FROM {1} WHERE {2} "; //FOR UPDATE?
		return MessageFormat.format(
			sql,
			new Object[] { column, table, condition });
	}

	private final String getUpdateStatement(
		String column,
		String table,
		String condition) {
		//todo: make it tunable.
		final String sql = "UPDATE {1} SET {0}=? WHERE {2}";
		return MessageFormat.format(
			sql,
			new Object[] { column, table, condition });
	}

	/**
	 * Returns the next generated key.
	 *
	 * @param db the source of database connections for the key-values table
	 * @return the generated key
	 * @exception PersistenceException if an error occurs
	 */
	synchronized Object nextKey(Connection con) throws SQLException {
		if (high == null || low >= getGrabSize()) {
			high = fetchHigh(con);
			low = 0;
		}

		Class highClass = high.getClass();
		if (highClass.equals(Integer.class)) {
			return new Integer(((Integer) high).intValue() - getGrabSize() + low++);
		} else if (highClass.equals(BigDecimal.class)) {
			return new BigDecimal(
				((BigDecimal) high).intValue() - getGrabSize() + low++);

		}
		throw new SQLException(
			MessageFormat.format(
				"KeyKeeper[{0}] can't handle primary key of type[{1}]",
				new Object[] { getClass().getName(), highClass }));
	}

	private static int getGrabSize()
	 
	{
		if(-1 == increment) {
			synchronized(KeyKeeper.class) {
				if(-1 == increment) {
					try {
						final String value = KeyGeneratorFactory.conf.get(IKeyGenConst.KEY_KEEPER_INCREMENT);
						increment = Integer.parseInt(value);
					} catch (Exception e) {
						increment = 10;
						if(LOG.isErrorEnabled()) {
							LOG.error("Can't retreive increment value from configuration", e);
						}
					}
				}
			}
		}
		return increment;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -