1 package org.apache.ojb.broker.util.sequence;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import org.apache.commons.lang.SystemUtils;
19 import org.apache.ojb.broker.PersistenceBroker;
20 import org.apache.ojb.broker.platforms.PlatformException;
21 import org.apache.ojb.broker.accesslayer.LookupException;
22 import org.apache.ojb.broker.metadata.ClassDescriptor;
23 import org.apache.ojb.broker.metadata.FieldDescriptor;
24 import org.apache.ojb.broker.query.Query;
25 import org.apache.ojb.broker.util.logging.Logger;
26 import org.apache.ojb.broker.util.logging.LoggerFactory;
27
28 import java.sql.CallableStatement;
29 import java.sql.SQLException;
30 import java.sql.Statement;
31 import java.sql.Connection;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 public class SequenceManagerStoredProcedureImpl extends AbstractSequenceManager
126 {
127 private Logger log = LoggerFactory.getLogger(SequenceManagerStoredProcedureImpl.class);
128 protected static final String PROCEDURE_NAME = "ojb_nextval_proc";
129 protected static final String SEQ_NAME_STRING = "SEQ_NAME";
130 protected static final String SEQ_ID_STRING = "MAX_KEY";
131 protected static final String SEQ_TABLE_NAME = "OJB_NEXTVAL_SEQ";
132
133
134
135
136
137 public SequenceManagerStoredProcedureImpl(PersistenceBroker broker)
138 {
139 super(broker);
140 }
141
142
143
144
145
146
147
148 protected String sp_createSequenceQuery(String sequenceName, long maxKey)
149 {
150 return "insert into " + SEQ_TABLE_NAME + " ("
151 + SEQ_NAME_STRING + "," + SEQ_ID_STRING +
152 ") values ('" + sequenceName + "'," + maxKey + ")";
153 }
154
155
156
157
158
159
160
161
162 protected long getUniqueLong(FieldDescriptor field) throws SequenceManagerException
163 {
164 boolean needsCommit = false;
165 long result = 0;
166
167
168
169
170
171 PersistenceBroker targetBroker = getBrokerForClass();
172 if(!targetBroker.isInTransaction())
173 {
174 targetBroker.beginTransaction();
175 needsCommit = true;
176 }
177 try
178 {
179
180 String sequenceName = calculateSequenceName(field);
181 try
182 {
183 result = buildNextSequence(targetBroker, field.getClassDescriptor(), sequenceName);
184
185
186
187
188 if (result == 0)
189 {
190 throw new SequenceManagerException("No incremented value retrieved");
191 }
192 }
193 catch (Exception e)
194 {
195
196 log.info("Could not grab next key, message was " + e.getMessage() +
197 " - try to write a new sequence entry to database");
198 try
199 {
200
201 long maxKey = SequenceManagerHelper.getMaxForExtent(targetBroker, field);
202 createSequence(targetBroker, field, sequenceName, maxKey);
203 }
204 catch (Exception e1)
205 {
206 String eol = SystemUtils.LINE_SEPARATOR;
207 throw new SequenceManagerException(eol + "Could not grab next id, failed with " + eol +
208 e.getMessage() + eol + "Creation of new sequence failed with " +
209 eol + e1.getMessage() + eol, e1);
210 }
211 try
212 {
213 result = buildNextSequence(targetBroker, field.getClassDescriptor(), sequenceName);
214 }
215 catch (Exception e1)
216 {
217 throw new SequenceManagerException("Could not grab next id although a sequence seems to exist", e);
218 }
219 }
220 }
221 finally
222 {
223 if(targetBroker != null && needsCommit)
224 {
225 targetBroker.commitTransaction();
226 }
227 }
228 return result;
229 }
230
231
232
233
234
235
236
237
238
239
240
241 protected long buildNextSequence(PersistenceBroker broker, ClassDescriptor cld, String sequenceName)
242 throws LookupException, SQLException, PlatformException
243 {
244 CallableStatement cs = null;
245 try
246 {
247 Connection con = broker.serviceConnectionManager().getConnection();
248 cs = getPlatform().prepareNextValProcedureStatement(con, PROCEDURE_NAME, sequenceName);
249 cs.executeUpdate();
250 return cs.getLong(1);
251 }
252 finally
253 {
254 try
255 {
256 if (cs != null)
257 cs.close();
258 }
259 catch (SQLException ignore)
260 {
261
262 }
263 }
264 }
265
266
267
268
269
270
271
272
273
274 protected void createSequence(PersistenceBroker broker, FieldDescriptor field,
275 String sequenceName, long maxKey) throws Exception
276 {
277 Statement stmt = null;
278 try
279 {
280 stmt = broker.serviceStatementManager().getGenericStatement(field.getClassDescriptor(), Query.NOT_SCROLLABLE);
281 stmt.execute(sp_createSequenceQuery(sequenceName, maxKey));
282 }
283 catch (Exception e)
284 {
285 log.error(e);
286 throw new SequenceManagerException("Could not create new row in "+SEQ_TABLE_NAME+" table - TABLENAME=" +
287 sequenceName + " field=" + field.getColumnName(), e);
288 }
289 finally
290 {
291 try
292 {
293 if (stmt != null) stmt.close();
294 }
295 catch (SQLException sqle)
296 {
297 if(log.isDebugEnabled())
298 log.debug("Threw SQLException while in createSequence and closing stmt", sqle);
299
300 }
301 }
302 }
303 }