1
2
3
4
5
6
7
8 /
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class DefaultPersistence implements Persistence
50 {
51 /*** The Database. */
52 private Database database;
53
54 /*** The logger */
55 private Logger logger;
56
57 /***
58 * Component constructor.
59 *
60 * @param database the database.
61 * @param logger the logger.
62 */
63 public DefaultPersistence(Database database, Logger logger)
64 {
65 this.logger = logger;
66 this.database = database;
67 }
68
69
70
71 /***
72 * Loads an object from the database.
73 *
74 * @param id the identifier of the object.
75 * @param factory the object instance factory.
76 * @return the presistent object.
77 * @throws PersistenceException if any exception occured.
78 */
79 public Persistent load(long id, PersistentFactory factory) throws PersistenceException
80 {
81 Connection conn = null;
82 try
83 {
84 conn = database.getConnection();
85 Persistent obj = factory.newInstance();
86 PreparedStatement statement = DefaultInputRecord.getSelectStatement(id, obj, conn);
87 ResultSet rs = statement.executeQuery();
88 if (!rs.next())
89 {
90 return null;
91 }
92 InputRecord record = new DefaultInputRecord(rs);
93 obj.setData(record);
94 obj.setSaved(record.getLong(obj.getKeyColumns()[0]));
95 return obj;
96 }
97 catch (Exception e)
98 {
99 throw new PersistenceException("Failed to retrieve object", e);
100 }
101 finally
102 {
103 DatabaseUtils.close(conn);
104 }
105 }
106
107 /***
108 * Loads objects from the database.
109 *
110 * <p>Note that joins are not supported. This package provides a means of
111 * converting objects to rows in a table and vice versa. If you want more,
112 * you need some different tool.</p>
113 *
114 * @param where the where clause to be used in the query
115 * @param factory the object instance factory.
116 * @return the list of presistent objects.
117 * @throws PersistenceException if any exception occured.
118 */
119 public List load(String where, PersistentFactory factory) throws PersistenceException
120 {
121 Connection conn = null;
122 try
123 {
124 conn = database.getConnection();
125 Persistent obj = factory.newInstance();
126 PreparedStatement statement = DefaultInputRecord.getSelectStatement(where, obj, conn);
127 ResultSet rs = statement.executeQuery();
128 InputRecord record = new DefaultInputRecord(rs);
129 ArrayList list = new ArrayList();
130 while (rs.next())
131 {
132 obj.setData(record);
133 obj.setSaved(record.getLong(obj.getKeyColumns()[0]));
134 list.add(obj);
135 obj = factory.newInstance();
136 }
137 return list;
138 }
139 catch (Exception e)
140 {
141 throw new PersistenceException("Failed to retrieve object", e);
142 }
143 finally
144 {
145 DatabaseUtils.close(conn);
146 }
147 }
148
149 /***
150 * Saves an object in the database.
151 *
152 * @param object the object to be saved.
153 * @throws PersistenceException if any exception occured.
154 */
155 public void save(Persistent object) throws PersistenceException
156 {
157 synchronized (object)
158 {
159 OutputRecord record = new DefaultOutputRecord(object);
160 String table = object.getTable();
161 String[] keys = object.getKeyColumns();
162 object.getData(record);
163 Connection conn = null;
164
165 try
166 {
167 conn = database.getConnection();
168 PreparedStatement statement;
169 if (object.getSaved())
170 {
171 statement = record.getUpdateStatement(conn);
172 statement.execute();
173 }
174 else
175 {
176 long id;
177 if (keys.length == 1)
178 {
179 id = database.getNextId(table);
180 record.setLong(keys[0], id);
181 }
182 else
183 {
184 id = -1;
185 }
186 statement = record.getInsertStatement(conn);
187 statement.execute();
188 object.setSaved(id);
189 }
190 }
191 catch (Exception e)
192 {
193 throw new PersistenceException("Failed to save object", e);
194 }
195 finally
196 {
197 DatabaseUtils.close(conn);
198 }
199 }
200 }
201
202 /***
203 * Reverts the object to the saved state.
204 *
205 * @param object the object to have it's state restored.
206 * @throws PersistenceException if any exception occured.
207 * @throws IllegalStateException if no state has been saved yet for the
208 * object in question.
209 */
210 public void revert(Persistent object) throws PersistenceException, IllegalStateException
211 {
212 synchronized (object)
213 {
214 if (!object.getSaved())
215 {
216 throw new IllegalStateException("no state has been saved yet");
217 }
218 Connection conn = null;
219 try
220 {
221 conn = database.getConnection();
222 PreparedStatement statement = DefaultInputRecord.getSelectStatements(object, conn);
223 ResultSet rs = statement.executeQuery();
224 if (!rs.next())
225 {
226 throw new PersistenceException("saved state was lost");
227 }
228 InputRecord irecord = new DefaultInputRecord(rs);
229 object.setData(irecord);
230 }
231 catch (Exception e)
232 {
233 throw new PersistenceException("failed to revert object's state", e);
234 }
235 finally
236 {
237 DatabaseUtils.close(conn);
238 }
239 }
240 }
241
242 /***
243 * Removes an object from the database.
244 *
245 * @param object the object to be removed.
246 * @throws PersistenceException if any exception occured.
247 */
248 public void delete(Persistent object) throws PersistenceException
249 {
250 synchronized (object)
251 {
252 Connection conn = null;
253 try
254 {
255 conn = database.getConnection();
256 OutputRecord record = new DefaultOutputRecord(object);
257 object.getData(record);
258 PreparedStatement statement = record.getDeleteStatement(conn);
259 statement.execute();
260 if(statement.getUpdateCount() != 1)
261 {
262 throw new PersistenceException("unsuccessful DELETE statement");
263 }
264 }
265 catch (Exception e)
266 {
267 if(e instanceof PersistenceException)
268 {
269 throw (PersistenceException)e;
270 }
271 throw new PersistenceException("Failed to delete object", e);
272 }
273 finally
274 {
275 DatabaseUtils.close(conn);
276 }
277 }
278 }
279
280 /***
281 * Removes the objects from the database.
282 *
283 * @param where the where clause to be used in the query
284 * @param factory the object instance factory.
285 * @throws PersistenceException if any exception occured.
286 */
287 public void delete(String where, PersistentFactory factory) throws PersistenceException
288 {
289 Connection conn = null;
290 try
291 {
292 conn = database.getConnection();
293 Persistent obj = factory.newInstance();
294 PreparedStatement statement = conn.prepareStatement("DELETE FROM " + obj.getTable() +
295 " WHERE " + where);
296 statement.executeUpdate();
297 }
298 catch (Exception e)
299 {
300 throw new PersistenceException("Failed to retrieve object", e);
301 }
302 finally
303 {
304 DatabaseUtils.close(conn);
305 }
306 }
307
308 /***
309 * An utility method for checking for existence of rows.
310 *
311 * @param table the table to be checked.
312 * @param where the condition.
313 * @return <code>true</code> if the <code>condition</code> is true for one
314 * or more rows in the <code>table</code>.
315 * @throws PersistenceException if any exception occured.
316 */
317 public boolean exists(String table, String where) throws PersistenceException
318 {
319 Connection conn = null;
320 try
321 {
322 conn = database.getConnection();
323 Statement statement = conn.createStatement();
324 ResultSet rs;
325 if (where != null)
326 {
327 rs = statement.executeQuery("SELECT DISTINCT 1 FROM " + table + " WHERE " + where);
328 }
329 else
330 {
331 rs = statement.executeQuery("SELECT DISTINCT 1 FROM " + table);
332 }
333 return (rs.next());
334 }
335 catch (Exception e)
336 {
337 throw new PersistenceException("Failed to execute query", e);
338 }
339 finally
340 {
341 DatabaseUtils.close(conn);
342 }
343 }
344
345 /***
346 * An utility method for checking the number of matching rows.
347 *
348 * @param table the table to be chcked.
349 * @param where the condition.
350 * @return the number of <code>table</code> matching the condition.
351 * @throws PersistenceException if any exception occured.
352 */
353 public int count(String table, String where) throws PersistenceException
354 {
355 Connection conn = null;
356 try
357 {
358 conn = database.getConnection();
359 Statement statement = conn.createStatement();
360 ResultSet rs;
361 if (where != null)
362 {
363 rs = statement.executeQuery("SELECT COUNT(*) FROM " + table + " WHERE " + where);
364 }
365 else
366 {
367 rs = statement.executeQuery("SELECT COUNT(*) FROM " + table);
368 }
369 if (!rs.next())
370 {
371 throw new PersistenceException("internal error - no data???");
372 }
373 return (rs.getInt(1));
374 }
375 catch (Exception e)
376 {
377 throw new PersistenceException("Failed to execute query", e);
378 }
379 finally
380 {
381 DatabaseUtils.close(conn);
382 }
383 }
384
385 /***
386 * {@inheritDoc}
387 */
388 public Database getDatabase()
389 {
390 return database;
391 }
392 }