001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.cocoon.components.modules.database;
019:
020: import java.sql.Connection;
021: import java.sql.PreparedStatement;
022: import java.sql.ResultSet;
023: import java.sql.SQLException;
024: import java.sql.Statement;
025: import java.util.HashMap;
026: import java.util.Map;
027:
028: import org.apache.avalon.framework.configuration.Configuration;
029: import org.apache.avalon.framework.configuration.ConfigurationException;
030: import org.apache.avalon.framework.thread.ThreadSafe;
031:
032: /**
033: * Abstraction layer to encapsulate different DBMS behaviour for
034: * autoincrement columns.
035: *
036: * Here: manual mode The new value is determined by doing a "select
037: * max(column)+1 from table" query. With transactions and correct
038: * isolation levels, this should to the trick almost everywhere.
039: *
040: * Note however, that the above query does not prevent a parallel
041: * transaction to try to insert a row with the same ID since it
042: * requires only shared locks. C.f. "Phantom Problem"
043: *
044: * @author <a href="mailto:haul@apache.org">Christian Haul</a>
045: * @version CVS $Id: ManualAutoIncrementModule.java 433543 2006-08-22 06:22:54Z crossley $
046: */
047: public class ManualAutoIncrementModule extends
048: AbstractAutoIncrementModule implements ThreadSafe {
049:
050: private Map selectStatements = new HashMap();
051:
052: public Object getPostValue(Configuration tableConf,
053: Configuration columnConf, Configuration modenConf,
054: Connection conn, Statement stmt, Map objectModel)
055: throws SQLException, ConfigurationException {
056:
057: return null;
058: }
059:
060: public boolean includeInQuery() {
061: return true;
062: }
063:
064: public boolean includeAsValue() {
065: return true;
066: }
067:
068: public Object getPreValue(Configuration tableConf,
069: Configuration columnConf, Configuration modeConf,
070: Connection conn, Map objectModel) throws SQLException,
071: ConfigurationException {
072:
073: /** Set the key value using SELECT MAX(keyname)+1 **/
074: String tableName = tableConf.getAttribute("name", "");
075: String selectQuery = this .getSelectQuery(tableName, columnConf);
076: PreparedStatement select_statement = conn
077: .prepareStatement(selectQuery);
078: ResultSet set = select_statement.executeQuery();
079: set.next();
080: int maxid = set.getInt("maxid");
081: set.close();
082: select_statement.close();
083: if (getLogger().isDebugEnabled())
084: getLogger().debug("autoincrementValue " + (maxid + 1));
085: return new Integer(maxid + 1);
086: }
087:
088: public String getSubquery(Configuration tableConf,
089: Configuration columnConf, Configuration modeConf)
090: throws ConfigurationException {
091:
092: return null;
093: }
094:
095: /**
096: * Set the String representation of the MaxID lookup statement. This is
097: * mapped to the Configuration object itself, so if it doesn't exist,
098: * it will be created.
099: */
100: protected final synchronized void setSelectQuery(String tableName,
101: Configuration entry) throws ConfigurationException {
102:
103: StringBuffer queryBuffer = new StringBuffer("SELECT max(");
104: queryBuffer.append(entry.getAttribute("name"));
105: queryBuffer.append(") AS maxid FROM ");
106: queryBuffer.append(tableName);
107:
108: this .selectStatements.put(entry, queryBuffer.toString());
109: }
110:
111: protected final synchronized String getSelectQuery(
112: String tableName, Configuration entry)
113: throws ConfigurationException {
114:
115: String result = (String) this .selectStatements.get(entry);
116: if (result == null) {
117: setSelectQuery(tableName, entry);
118: result = (String) this.selectStatements.get(entry);
119: }
120: return result;
121: }
122:
123: }
|