001: /*
002: * Copyright (C) 2006 Methodhead Software LLC. All rights reserved.
003: *
004: * This file is part of TransferCM.
005: *
006: * TransferCM is free software; you can redistribute it and/or modify it under the
007: * terms of the GNU General Public License as published by the Free Software
008: * Foundation; either version 2 of the License, or (at your option) any later
009: * version.
010: *
011: * TransferCM is distributed in the hope that it will be useful, but WITHOUT ANY
012: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
013: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
014: * details.
015: *
016: * You should have received a copy of the GNU General Public License along with
017: * TransferCM; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
018: * Fifth Floor, Boston, MA 02110-1301 USA
019: */
020:
021: package com.methodhead.aikp;
022:
023: import java.sql.ResultSet;
024: import java.sql.SQLException;
025:
026: import java.util.List;
027: import java.util.Map;
028:
029: import com.methodhead.persistable.ConnectionSingleton;
030: import com.methodhead.persistable.Persistable;
031: import com.methodhead.persistable.Key;
032: import com.methodhead.persistable.KeyedPersistable;
033: import com.methodhead.persistable.KeyFactory;
034: import com.methodhead.persistable.PersistableException;
035: import org.apache.commons.beanutils.DynaClass;
036: import org.apache.log4j.Logger;
037: import org.apache.commons.lang.exception.ExceptionUtils;
038: import com.methodhead.persistable.ConnectionSingleton;
039:
040: /**
041: * Extends <tt>KeyedPersistable</tt> to generate new <tt>IntKeys</tt>
042: * automatically. Ids are managed using a simple database table; make sure
043: * this table exists in the database:
044: * <pre>
045: * CREATE TABLE mh_id (
046: * name VARCHAR(32),
047: * value INT
048: * );</pre>
049: * <tt>saveNew(Key)</tt> is overridden and made protected. Instead, use
050: * <tt>saveNew()</tt> which generates the id itself.
051: */
052: public abstract class AutoIntKeyPersistable extends KeyedPersistable {
053:
054: // constructors /////////////////////////////////////////////////////////////
055:
056: public AutoIntKeyPersistable(DynaClass dynaClass) {
057:
058: super (dynaClass);
059: }
060:
061: // constants ////////////////////////////////////////////////////////////////
062:
063: // classes //////////////////////////////////////////////////////////////////
064:
065: private static class IntKeyFactory implements KeyFactory {
066:
067: public Key newInstance() {
068: return new IntKey();
069: }
070: }
071:
072: // methods //////////////////////////////////////////////////////////////////
073:
074: /**
075: * Returns a new id for the specified <tt>key</tt>.
076: */
077: protected synchronized IntKey newKey(String name) {
078:
079: String sql = null;
080:
081: ResultSet rs = null;
082:
083: try {
084: sql = "SELECT " + " value " + "FROM " + " mh_id "
085: + "WHERE " + " name=" + getSqlLiteral(name);
086:
087: rs = ConnectionSingleton.runQuery(sql);
088:
089: if (rs == null) {
090: throw new SQLException("Null result set.");
091: }
092:
093: if (!rs.next()) {
094: sql = "INSERT INTO " + " mh_id " + "( " + " name, "
095: + " value ) " + "VALUES ( " + " "
096: + getSqlLiteral(name) + ", " + " 2" + ")";
097:
098: ConnectionSingleton.runUpdate(sql);
099:
100: return new IntKey(1);
101: } else {
102: int value = rs.getInt("value");
103:
104: sql = "UPDATE " + " mh_id " + "SET " + " value="
105: + (value + 1) + " " + "WHERE " + " name="
106: + getSqlLiteral(name);
107:
108: ConnectionSingleton.runUpdate(sql);
109:
110: return new IntKey(value);
111: }
112: } catch (SQLException e) {
113: String msg = "Creating new key for \"" + name + "\". "
114: + ExceptionUtils.getStackTrace(e);
115: logger_.error(msg);
116: throw new RuntimeException(msg);
117: } finally {
118: ConnectionSingleton.close(rs);
119: }
120: }
121:
122: /**
123: * Saves the persistable, automatically generating a new id for it.
124: */
125: public void saveNew() {
126: super .saveNew(newKey(getDynaClass().getName()));
127: }
128:
129: /**
130: * Loads the persistable like {@link
131: * com.methodhead.persistable.Persistable#load(java.lang.String)
132: * Persistable.load()} and sets its key appropriately.
133: */
134: public void load(String whereClause) {
135:
136: super .load(whereClause, new IntKeyFactory());
137:
138: }
139:
140: /**
141: * See super class's documentation.
142: */
143: public static List loadAll(DynaClass dynaClass, String whereClause,
144: String orderByClause) {
145:
146: return KeyedPersistable.loadAll(dynaClass, whereClause,
147: orderByClause, new IntKeyFactory());
148: }
149:
150: // properties ///////////////////////////////////////////////////////////////
151:
152: // attributes ///////////////////////////////////////////////////////////////
153:
154: private static Logger logger_ = Logger
155: .getLogger(AutoIntKeyPersistable.class);
156: }
|