Source code: ojb/broker/util/sequence/SequenceManagerDefaultImpl.java
1 /*
2 * ObJectRelationalBridge - Bridging Java Objects and Relational Databases
3 * http://objectbridge.sourceforge.net
4 * Copyright (C) 2000, 2001 Thomas Mahler, et al.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 package ojb.broker.util.sequence;
21
22 import ojb.broker.PersistenceBrokerException;
23 import ojb.broker.PersistenceBrokerSQLException;
24 import ojb.broker.metadata.ClassDescriptor;
25 import ojb.broker.query.QueryByExample;
26 import ojb.broker.singlevm.PersistenceBrokerImpl;
27 import ojb.broker.util.logging.*;
28
29 import java.sql.ResultSet;
30 import java.sql.SQLException;
31 import java.sql.Statement;
32
33 /**
34 * A simple SequenceManager. This class is responsible for creating new unique ID's for primary columns
35 * containing integer values.
36 * The SequenceManager is aware of extends, that is: if you ask for an uid for an Interface with several implementor classes,
37 * or a baseclass with several subclasses the returned uid will unique accross all tables representing
38 * objects of the extent in question.
39 * @author: thma
40 */
41 public class SequenceManagerDefaultImpl implements SequenceManager
42 {
43
44 /**
45 * reference to the PersistenceBroker
46 */
47 protected PersistenceBrokerImpl broker;
48
49 /**
50 * singleton instance of the SequenceManager
51 */
52 private static SequenceManagerDefaultImpl _instance;
53
54 /**
55 *
56 * Public constructor
57 *
58 */
59 public SequenceManagerDefaultImpl(PersistenceBrokerImpl broker)
60 {
61 this.broker = broker;
62 }
63
64
65 /**
66 * lookup current maximum value for fieldName in table cld.getTableName()
67 */
68 private int getMaxIdForClass(ClassDescriptor cld, String fieldName) throws PersistenceBrokerException
69 {
70 int result = 0;
71 ResultSet rs = null;
72 Statement stmt = null;
73 try
74 {
75 String table = cld.getFullTableName();
76 String column = cld.getFieldDescriptorByName(fieldName).getColumnName();
77 String sql = "SELECT MAX(" + column + ") FROM " + table;
78 stmt = broker.getStatementManager().getGenericStatement(cld);
79 rs = stmt.executeQuery(sql);
80 rs.next();
81 result = rs.getInt(1);
82
83 }
84 catch (Throwable t)
85 {
86 LoggerFactory.getDefaultLogger().error(t);
87 throw new PersistenceBrokerException(t);
88 }
89 finally
90 {
91 try
92 {
93 rs.close();
94 stmt.close();
95 }
96 catch (SQLException e)
97 {
98 LoggerFactory.getDefaultLogger().error(e);
99 throw new PersistenceBrokerSQLException(e);
100 }
101 return result;
102 }
103 }
104
105 /**
106 *
107 */
108 private synchronized int getNextId(Class clazz, String fieldName) throws PersistenceBrokerException
109 {
110 // check if there is an entry for this class
111 SequenceEntry tmp = new SequenceEntry();
112 tmp.setClassname(clazz.getName());
113 tmp.setFieldname(fieldName);
114 SequenceEntry entry = (SequenceEntry) broker.getObjectByQuery(new QueryByExample(tmp));
115 // if no entry found, build a new one first:
116 if (entry == null)
117 {
118 int lastId = getMaxForExtent(clazz, fieldName);
119 entry = new SequenceEntry(clazz.getName(), fieldName, lastId);
120 }
121 // compute next uid, update the entry, store it and return
122 int nextId = entry.getCurrent() + 1;
123 entry.setCurrent(nextId);
124 broker.store(entry);
125 return nextId;
126 }
127
128 /**
129 * returns a unique int for class clazz and field fieldName.
130 * the returned uid is unique accross all tables in the extent of clazz.
131 */
132 public int getUniqueId(Class clazz, String fieldName)
133 {
134 return getNextId(clazz, fieldName);
135 }
136
137 /**
138 * lookup all tables in extent clazz to find the current maximum value for fieldName
139 */
140 protected int getMaxForExtent(Class clazz,
141 String fieldName) throws PersistenceBrokerException
142 {
143 int max = 0;
144 ClassDescriptor cld = broker.getClassDescriptor(clazz);
145 // if class is no Interface we have to search its directly mapped table
146 if (!cld.isInterface())
147 {
148 int tmp = getMaxIdForClass(cld, fieldName);
149 if (tmp > max)
150 {
151 max = tmp;
152 }
153 }
154 // if class is an extent we have to search through its subclasses
155 if (cld.isExtent())
156 {
157 java.util.Vector extentClasses = cld.getExtentClasses();
158 for (int i = 0; i < extentClasses.size(); i++)
159 {
160 Class ec = (Class) extentClasses.get(i);
161 cld = broker.getClassDescriptor(ec);
162 int tmp = getMaxIdForClass(cld, fieldName);
163 if (tmp > max)
164 {
165 max = tmp;
166 }
167 }
168 }
169 return max;
170 }
171
172 /**
173 * returns a unique String for class clazz and field fieldName.
174 * the returned uid is unique accross all tables in the extent of clazz.
175 *
176 */
177 public String getUniqueString(Class clazz, String fieldName)
178 {
179 return Integer.toString(getUniqueId(clazz, fieldName));
180 }
181
182 /**
183 * returns a unique long value for class clazz and field fieldName.
184 * the returned number is unique accross all tables in the extent of clazz.
185 */
186 public long getUniqueLong(Class clazz, String fieldName)
187 {
188 return (long) getUniqueId(clazz, fieldName);
189 }
190
191 /**
192 * returns a unique Object for class clazz and field fieldName.
193 * the returned Object is unique accross all tables in the extent of clazz.
194 */
195 public Object getUniqueObject(Class clazz, String fieldName)
196 {
197 return getUniqueString(clazz, fieldName);
198 }
199 }