1 package com.atlassian.activeobjects.external;
2
3 import com.atlassian.sal.api.transaction.TransactionCallback;
4 import net.java.ao.Accessor;
5 import net.java.ao.DBParam;
6 import net.java.ao.EntityStreamCallback;
7 import net.java.ao.Query;
8 import net.java.ao.RawEntity;
9
10 import java.util.Map;
11
12 /**
13 * Interface to the active objects framework. Instance is threadsafe.
14 */
15 public interface ActiveObjects {
16 /**
17 * Creates the schema for the specified entities
18 */
19 void migrate(Class<? extends RawEntity<?>>... entities);
20
21 /**
22 * Create the schema for the specified entities, dropping columns and tables which are no longer required
23 */
24 void migrateDestructively(Class<? extends RawEntity<?>>... entities);
25
26 /**
27 * Flushes all value caches contained within entities controlled by this {@code EntityManager}
28 * instance. This does not actually remove the entities from the instance cache maintained
29 * within this class. Rather, it simply dumps all of the field values cached within the entities
30 * themselves (with the exception of the primary key value). This should be used in the case
31 * of a complex process outside AO control which may have changed values in the database. If
32 * it is at all possible to determine precisely which rows have been changed, the
33 * {@link #flush(net.java.ao.RawEntity...)} method should be used instead.
34 */
35 void flushAll();
36
37 /**
38 * Flushes the value caches of the specified entities along with all of the relevant
39 * relations cache entries. This should be called after a process outside of AO control
40 * may have modified the values in the specified rows. This does not actually remove
41 * the entity instances themselves from the instance cache. Rather, it just flushes all
42 * of their internally cached values (with the exception of the primary key).
43 */
44 void flush(RawEntity<?>... entities);
45
46 /**
47 * Returns an array of entities of the specified type corresponding to the
48 * varargs primary keys. If an in-memory reference already exists to a corresponding
49 * entity (of the specified type and key), it is returned rather than creating
50 * a new instance.
51 * <p>
52 * No checks are performed to ensure that the key actually exists in the
53 * database for the specified object. Thus, this method is solely a Java
54 * memory state modifying method. There is no database access involved.
55 * The upshot of this is that the method is very very fast. The flip side of
56 * course is that one could conceivably maintain entities which reference
57 * non-existent database rows.
58 *
59 * @param type The type of the entities to retrieve
60 * @param keys The primary keys corresponding to the entities to retrieve. All
61 * keys must be typed according to the generic type parameter of the entity's
62 * {@link RawEntity} inheritance (if inheriting from {@link net.java.ao.Entity}, this is {@code Integer}
63 * or {@code int}). Thus, the {@code keys} array is type-checked at compile time.
64 * @return An array of entities of the given type corresponding with the specified primary keys
65 */
66 @SuppressWarnings("unchecked")
67 <T extends RawEntity<K>, K> T[] get(Class<T> type, K... keys);
68
69 /**
70 * Cleverly overloaded method to return a single entity of the specified type
71 * rather than an array in the case where only one ID is passed. This method
72 * merely delegates the call to the overloaded <code>get</code> method
73 * and functions as syntactical sugar.
74 *
75 * @param type The type of the entity instance to retrieve
76 * @param key The primary key corresponding to the entity to be retrieved
77 * @return An entity instance of the given type corresponding to the specified primary key
78 * @see #get(Class, Object...)
79 */
80 <T extends RawEntity<K>, K> T get(Class<T> type, K key);
81
82 /**
83 * Creates a new entity of the specified type with the optionally specified
84 * initial parameters. This method actually inserts a row into the table represented
85 * by the entity type and returns the entity instance which corresponds to that
86 * row.
87 * <p>
88 * The {@link net.java.ao.DBParam} object parameters are designed to allow the creation
89 * of entities which have non-null fields which have no defalut or auto-generated
90 * value. Insertion of a row without such field values would of course fail,
91 * thus the need for db params. The db params can also be used to set
92 * the values for any field in the row, leading to more compact code under
93 * certain circumstances.
94 * <p>
95 * Unless within a transaction, this method will commit to the database
96 * immediately and exactly once per call. Thus, care should be taken in
97 * the creation of large numbers of entities. There doesn't seem to be a more
98 * efficient way to create large numbers of entities, however one should still
99 * be aware of the performance implications.
100 * <p>
101 * This method delegates the action INSERT action to
102 * This is necessary because not all databases support the JDBC <code>RETURN_GENERATED_KEYS</code>
103 * constant (e.g. PostgreSQL and HSQLDB). Thus, the database provider itself is
104 * responsible for handling INSERTion and retrieval of the correct primary key
105 * value.
106 *
107 * @param type The type of the entity to INSERT
108 * @param params An optional varargs array of initial values for the fields in the row. These
109 * values will be passed to the database within the INSERT statement.
110 * @return The new entity instance corresponding to the INSERTed row
111 * @see net.java.ao.DBParam
112 */
113 <T extends RawEntity<K>, K> T create(Class<T> type, DBParam... params);
114
115 /**
116 * Creates and INSERTs a new entity of the specified type with the given map of
117 * parameters. This method merely delegates to the {@link #create(Class, DBParam...)}
118 * method. The idea behind having a separate convenience method taking a map is in
119 * circumstances with large numbers of parameters or for people familiar with the
120 * anonymous inner class constructor syntax who might be more comfortable with
121 * creating a map than with passing a number of objects.
122 *
123 * @param type The type of the entity to INSERT
124 * @param params A map of parameters to pass to the INSERT
125 * @return The new entity instance corresponding to the INSERTed row
126 * @see #create(Class, DBParam...)
127 */
128 <T extends RawEntity<K>, K> T create(Class<T> type, Map<String, Object> params);
129
130 /**
131 * Deletes the specified entities from the database. DELETE statements are
132 * called on the rows in the corresponding tables and the entities are removed
133 * from the instance cache. The entity instances themselves are not invalidated,
134 * but it doesn't even make sense to continue using the instance without a row
135 * with which it is paired.
136 * <p>
137 * This method does attempt to group the DELETE statements on a per-type
138 * basis. Thus, if you pass 5 instances of <code>EntityA</code> and two
139 * instances of <code>EntityB</code>, the following SQL prepared statements
140 * will be invoked:
141 * <pre>
142 * DELETE FROM entityA WHERE id IN (?,?,?,?,?);
143 * DELETE FROM entityB WHERE id IN (?,?);
144 * </pre>
145 * Thus, this method scales very well for large numbers of entities grouped
146 * into types. However, the execution time increases linearly for each entity of
147 * unique type.
148 *
149 * @param entities A varargs array of entities to delete. Method returns immediately if length == 0.
150 */
151 @SuppressWarnings("unchecked")
152 void delete(RawEntity<?>... entities);
153
154 /**
155 * Deletes rows from the table corresponding to {@code type}. In contrast to {@link #delete(RawEntity[])},
156 * this method allows you to delete rows without creating entities for them first.
157 * <p>
158 * Example:
159 * <pre>
160 * manager.deleteWithSQL(Person.class, "name = ?", "Charlie")
161 * </pre>
162 * The SQL in {@code criteria} is not parsed or modified in any way by ActiveObjects, and is simply appended
163 * to the DELETE statement in a WHERE clause. The above example would cause an SQL statement similar to the
164 * following to be executed:
165 * <pre>
166 * DELETE FROM people WHERE name = 'Charlie';
167 * </pre>
168 * If {@code criteria} is {@code null}, this method deletes all rows from the table corresponding to {@code type}.
169 * <p>
170 * This method does not attempt to determine the set of entities affected by the statement. As such, it is
171 * recommended that you call {@link #flushAll()} after calling this method.
172 *
173 * @param type The entity type corresponding to the table to delete from
174 * @param criteria An optional SQL fragment specifying which rows to delete
175 * @param parameters A varargs array of parameters to be passed to the executed prepared statement. The length
176 * of this array <i>must</i> match the number of parameters (denoted by the '?' char) in {@code criteria}.
177 * @return The number of rows deleted from the table
178 * @see #delete(RawEntity...)
179 * @see #find(Class, String, Object...)
180 * @see #findWithSQL(Class, String, String, Object...)
181 */
182 <K> int deleteWithSQL(Class<? extends RawEntity<K>> type, String criteria, Object... parameters);
183
184 /**
185 * Returns all entities of the given type. This actually peers the call to
186 * the {@link #find(Class, net.java.ao.Query)} method.
187 *
188 * @param type The type of entity to retrieve
189 * @return An array of all entities which correspond to the given type
190 */
191 <T extends RawEntity<K>, K> T[] find(Class<T> type);
192
193 /**
194 * Convenience method to select all entities of the given type with the
195 * specified, parameterized criteria. The <code>criteria</code> String
196 * specified is appended to the SQL prepared statement immediately
197 * following the <code>WHERE</code>.
198 * <p>
199 * Example:
200 * <pre>
201 * manager.find(Person.class, "name LIKE ? OR age > ?", "Joe", 9);
202 * </pre>
203 * This actually delegates the call to the {@link #find(Class, net.java.ao.Query)}
204 * method, properly parameterizing the {@link net.java.ao.Query} object.
205 *
206 * @param type The type of the entities to retrieve
207 * @param criteria A parameterized WHERE statement used to determine the results
208 * @param parameters A varargs array of parameters to be passed to the executed
209 * prepared statement. The length of this array <i>must</i> match the number of
210 * parameters (denoted by the '?' char) in the <code>criteria</code>.
211 * @return An array of entities of the given type which match the specified criteria
212 */
213 <T extends RawEntity<K>, K> T[] find(Class<T> type, String criteria, Object... parameters);
214
215 /**
216 * Selects all entities matching the given type and {@link net.java.ao.Query}. By default, the
217 * entities will be created based on the values within the primary key field for the
218 * specified type (this is usually the desired behavior).
219 * <p>
220 * Example:
221 * <pre>
222 * manager.find(Person.class, Query.select().where("name LIKE ? OR age > ?", "Joe", 9).limit(10));
223 * </pre>
224 * This method delegates the call to {@link #find(Class, String, net.java.ao.Query)}, passing the
225 * primary key field for the given type as the <code>String</code> parameter.
226 *
227 * @param type The type of the entities to retrieve
228 * @param query The {@link net.java.ao.Query} instance to be used to determine the results
229 * @return An array of entities of the given type which match the specified query
230 */
231 <T extends RawEntity<K>, K> T[] find(Class<T> type, Query query);
232
233 /**
234 * Selects all entities of the specified type which match the given
235 * <code>Query</code>. This method creates a <code>PreparedStatement</code>
236 * using the <code>Query</code> instance specified against the table
237 * represented by the given type. This query is then executed (with the
238 * parameters specified in the query). The method then iterates through
239 * the result set and extracts the specified field, mapping an entity
240 * of the given type to each row. This array of entities is returned.
241 *
242 * @param type The type of the entities to retrieve
243 * @param field The field value to use in the creation of the entities. This is usually
244 * the primary key field of the corresponding table.
245 * @param query The {@link Query} instance to use in determining the results
246 * @return An array of entities of the given type which match the specified query
247 */
248 <T extends RawEntity<K>, K> T[] find(Class<T> type, String field, Query query);
249
250 /**
251 * Executes the specified SQL and extracts the given key field, wrapping each
252 * row into a instance of the specified type. The SQL itself is executed as
253 * a {@link java.sql.PreparedStatement} with the given parameters.
254 * <p>
255 * Example:
256 * <pre>
257 * manager.findWithSQL(Person.class, "personID", "SELECT personID FROM chairs WHERE position < ? LIMIT ?", 10, 5);
258 * </pre>
259 * The SQL is not parsed or modified in any way by ActiveObjects. As such, it is
260 * possible to execute database-specific queries using this method without realizing
261 * it. For example, the above query will not run on MS SQL Server or Oracle, due to
262 * the lack of a LIMIT clause in their SQL implementation. As such, be extremely
263 * careful about what SQL is executed using this method, or else be conscious of the
264 * fact that you may be locking yourself to a specific DBMS.
265 *
266 * @param type The type of the entities to retrieve
267 * @param keyField The field value to use in the creation of the entities. This is usually
268 * the primary key field of the corresponding table.
269 * @param sql The SQL statement to execute.
270 * @param parameters A varargs array of parameters to be passed to the executed
271 * prepared statement. The length of this array <i>must</i> match the number of
272 * parameters (denoted by the '?' char) in the <code>criteria</code>.
273 * @return An array of entities of the given type which match the specified query
274 */
275 @SuppressWarnings("unchecked")
276 <T extends RawEntity<K>, K> T[] findWithSQL(Class<T> type, String keyField, String sql, Object... parameters);
277
278 /**
279 * Optimised read for large datasets. This method will stream all rows for the given type to the given callback.
280 * <p>
281 * Please see {@link #stream(Class, Query, EntityStreamCallback)} for details / limitations.
282 *
283 * @param type The type of the entities to retrieve
284 * @param streamCallback The receiver of the data, will be passed one entity per returned row
285 */
286 <T extends RawEntity<K>, K> void stream(Class<T> type, EntityStreamCallback<T, K> streamCallback);
287
288 /**
289 * Selects all entities of the given type and feeds them to the callback, one by one. The entities are slim,
290 * uncached, read-only representations of the data. They only supports getters or designated {@link Accessor}
291 * methods. Calling setters or <pre>save</pre> will result in an exception. Other method calls will be ignored.
292 * The proxies do not support lazy-loading of related entities.
293 * <p>
294 * This call is optimised for efficient read operations on large datasets. For best memory usage, do not buffer
295 * the entities passed to the callback but process and discard them directly.
296 *
297 * Unlike regular Entities, the read only implementations do not support flushing/refreshing. The data is a
298 * snapshot view at the time of
299 * query.
300 *
301 * @param type The type of the entities to retrieve
302 * @param query The {@link Query} instance to use in determining the results
303 * @param streamCallback The receiver of the data, will be passed one entity per returned row
304 */
305 <T extends RawEntity<K>, K> void stream(Class<T> type, Query query, EntityStreamCallback<T, K> streamCallback);
306
307 /**
308 * Counts all entities of the specified type. This method is actually
309 * a delegate for: <code>count(Class<? extends Entity>, Query)</code>
310 *
311 * @param type The type of the entities which should be counted.
312 * @return The number of entities of the specified type.
313 */
314 <K> int count(Class<? extends RawEntity<K>> type);
315
316 /**
317 * Counts all entities of the specified type matching the given criteria
318 * and parameters. This is a convenience method for:
319 * <code>count(type, Query.select().where(criteria, parameters))</code>
320 *
321 * @param type The type of the entities which should be counted
322 * @param criteria A parameterized WHERE statement used to determine the result set which will be counted
323 * @param parameters A varargs array of parameters to be passed to the executed
324 * prepared statement. The length of this array <i>must</i> match the number of
325 * parameters (denoted by the '?' char) in the <code>criteria</code>.
326 * @return The number of entities of the given type which match the specified criteria
327 */
328 <K> int count(Class<? extends RawEntity<K>> type, String criteria, Object... parameters);
329
330 /**
331 * Counts all entities of the specified type matching the given {@link Query}
332 * instance. The SQL runs as a <code>SELECT COUNT(*)</code> to
333 * ensure maximum performance.
334 *
335 * @param type The type of the entities which should be counted
336 * @param query The {@link Query} instance used to determine the result set which will be counted
337 * @return The number of entities of the given type which match the specified query
338 */
339 <K> int count(Class<? extends RawEntity<K>> type, Query query);
340
341 /**
342 * Execute the given callback within a transaction if the host supports transactions,
343 * otherwise executes the callback immediately.
344 *
345 * @param callback the callback to execute within a transaction
346 * @return the result of the transactionCallback
347 */
348 <T> T executeInTransaction(TransactionCallback<T> callback);
349
350 /**
351 * Provides information about the state of the ActiveObjects module
352 *
353 * @return activeObjectsModuleMetaData
354 * @since 0.24
355 */
356 ActiveObjectsModuleMetaData moduleMetaData();
357 }