com.j256.ormlite.dao.Dao Maven / Gradle / Ivy
Show all versions of ormlite-core Show documentation
package com.j256.ormlite.dao;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import com.j256.ormlite.field.DataType;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.field.ForeignCollectionField;
import com.j256.ormlite.stmt.DeleteBuilder;
import com.j256.ormlite.stmt.GenericRowMapper;
import com.j256.ormlite.stmt.PreparedDelete;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.PreparedUpdate;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.SelectArg;
import com.j256.ormlite.stmt.UpdateBuilder;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.support.DatabaseConnection;
import com.j256.ormlite.support.DatabaseResults;
import com.j256.ormlite.table.ObjectFactory;
import com.j256.ormlite.table.TableInfo;
/**
* The definition of the Database Access Objects that handle the reading and writing a class from the database. Kudos to
* Robert A. for the general concept of this hierarchy.
*
* @param
* The class that the code will be operating on.
* @param
* The class of the ID column associated with the class. The T class does not require an ID field. The class
* needs an ID parameter however so you can use Void or Object to satisfy the compiler.
* @author graywatson
*/
public interface Dao extends CloseableIterable {
/**
* Retrieves an object associated with a specific ID.
*
* @param id
* Identifier that matches a specific row in the database to find and return.
* @return The object that has the ID field which equals id or null if no matches.
* @throws SQLException
* on any SQL problems or if more than 1 item with the id are found in the database.
*/
public T queryForId(ID id) throws SQLException;
/**
* Query for and return the first item in the object table which matches the PreparedQuery. See
* {@link #queryBuilder()} for more information. This can be used to return the object that matches a single unique
* column. You should use {@link #queryForId(Object)} if you want to query for the id column.
*
* @param preparedQuery
* Query used to match the objects in the database.
* @return The first object that matches the query.
* @throws SQLException
* on any SQL problems.
*/
public T queryForFirst(PreparedQuery preparedQuery) throws SQLException;
/**
* Query for all of the items in the object table. For medium sized or large tables, this may load a lot of objects
* into memory so you should consider using the {@link #iterator()} method instead.
*
* @return A list of all of the objects in the table.
* @throws SQLException
* on any SQL problems.
*/
public List queryForAll() throws SQLException;
/**
* Query for the items in the object table that match a simple where with a single field = value type of WHERE
* clause. This is a convenience method for calling queryBuilder().where().eq(fieldName, value).query().
*
* @return A list of the objects in the table that match the fieldName = value;
* @throws SQLException
* on any SQL problems.
*/
public List queryForEq(String fieldName, Object value) throws SQLException;
/**
* Query for the rows in the database that match the object passed in as a parameter. Any fields in the matching
* object that are not the default value (null, false, 0, 0.0, etc.) are used as the matching parameters with AND.
* If you are worried about SQL quote escaping, you should use {@link #queryForMatchingArgs(Object)}.
*/
public List queryForMatching(T matchObj) throws SQLException;
/**
* Same as {@link #queryForMatching(Object)} but this uses {@link SelectArg} and SQL ? arguments. This is slightly
* more expensive but you don't have to worry about SQL quote escaping.
*/
public List queryForMatchingArgs(T matchObj) throws SQLException;
/**
* Query for the rows in the database that matches all of the field to value entries from the map passed in. If you
* are worried about SQL quote escaping, you should use {@link #queryForFieldValuesArgs(Map)}.
*/
public List queryForFieldValues(Map fieldValues) throws SQLException;
/**
* Same as {@link #queryForFieldValues(Map)} but this uses {@link SelectArg} and SQL ? arguments. This is slightly
* more expensive but you don't have to worry about SQL quote escaping.
*/
public List queryForFieldValuesArgs(Map fieldValues) throws SQLException;
/**
* Query for a data item in the table that has the same id as the data parameter.
*/
public T queryForSameId(T data) throws SQLException;
/**
* Create and return a new query builder object which allows you to build a custom SELECT statement. You call
* methods on the builder to construct your statement and then call {@link QueryBuilder#prepare()} once you are
* ready to build. This returns a {@link PreparedQuery} object which gets passed to {@link #query(PreparedQuery)} or
* {@link #iterator(PreparedQuery)}.
*/
public QueryBuilder queryBuilder();
/**
* Like {@link #queryBuilder()} but allows you to build an UPDATE statement. You can then call call
* {@link UpdateBuilder#prepare()} and pass the returned {@link PreparedUpdate} to {@link #update(PreparedUpdate)}.
*/
public UpdateBuilder updateBuilder();
/**
* Like {@link #queryBuilder()} but allows you to build an DELETE statement. You can then call call
* {@link DeleteBuilder#prepare()} and pass the returned {@link PreparedDelete} to {@link #delete(PreparedDelete)}.
*/
public DeleteBuilder deleteBuilder();
/**
* Query for the items in the object table which match the prepared query. See {@link #queryBuilder} for more
* information.
*
*
* NOTE: For medium sized or large tables, this may load a lot of objects into memory so you should consider
* using the {@link #iterator(PreparedQuery)} method instead.
*
*
* @param preparedQuery
* Query used to match the objects in the database.
* @return A list of all of the objects in the table that match the query.
* @throws SQLException
* on any SQL problems.
*/
public List query(PreparedQuery preparedQuery) throws SQLException;
/**
* Create a new row in the database from an object. If the object being created uses
* {@link DatabaseField#generatedId()} then the data parameter will be modified and set with the corresponding id
* from the database.
*
* @param data
* The data item that we are creating in the database.
* @return The number of rows updated in the database. This should be 1.
*/
public int create(T data) throws SQLException;
/**
* Just like {@link #create(Object)} but with a collection of objects. This will wrap the creates using the same
* mechanism as {@link #callBatchTasks(Callable)}.
*
* @param datas
* The collection of data items that we are creating in the database.
* @return The number of rows updated in the database.
*/
public int create(Collection datas) throws SQLException;
/**
* This is a convenience method to creating a data item but only if the ID does not already exist in the table. This
* extracts the id from the data parameter, does a {@link #queryForId(Object)} on it, returning the data if it
* exists. If it does not exist {@link #create(Object)} will be called with the parameter.
*
*
* NOTE: This method is synchronized because otherwise race conditions would be encountered if this is used
* by multiple threads.
*
*
* @return Either the data parameter if it was inserted (now with the ID field set via the create method) or the
* data element that existed already in the database.
*/
public T createIfNotExists(T data) throws SQLException;
/**
* This is a convenience method for creating an item in the database if it does not exist. The id is extracted from
* the data parameter and a query-by-id is made on the database. If a row in the database with the same id exists
* then all of the columns in the database will be updated from the fields in the data parameter. If the id is null
* (or 0 or some other default value) or doesn't exist in the database then the object will be created in the
* database. This also means that your data item must have an id field defined.
*
*
* NOTE: This method is synchronized because otherwise race conditions would be encountered if this is used
* by multiple threads.
*
*
* @return Status object with the number of rows changed and whether an insert or update was performed.
*/
public CreateOrUpdateStatus createOrUpdate(T data) throws SQLException;
/**
* Store the fields from an object to the database row corresponding to the id from the data parameter. If you have
* made changes to an object, this is how you persist those changes to the database. You cannot use this method to
* update the id field -- see {@link #updateId} .
*
*
* NOTE: This will not save changes made to foreign objects or to foreign collections.
*
*
* @param data
* The data item that we are updating in the database.
* @return The number of rows updated in the database. This should be 1.
* @throws SQLException
* on any SQL problems.
* @throws IllegalArgumentException
* If there is only an ID field in the object. See the {@link #updateId} method.
*/
public int update(T data) throws SQLException;
/**
* Update the data parameter in the database to change its id to the newId parameter. The data must have its
* current (old) id set. If the id field has already changed then it cannot be updated. After the id has been
* updated in the database, the id field of the data parameter will also be changed.
*
*
* NOTE: Depending on the database type and the id type, you may be unable to change the id of the field.
*
*
* @param data
* The data item that we are updating in the database with the current id.
* @param newId
* The new id that you want to update the data with.
* @return The number of rows updated in the database. This should be 1.
* @throws SQLException
* on any SQL problems.
*/
public int updateId(T data, ID newId) throws SQLException;
/**
* Update all rows in the table according to the prepared statement parameter. To use this, the
* {@link UpdateBuilder} must have set-columns applied to it using the
* {@link UpdateBuilder#updateColumnValue(String, Object)} or
* {@link UpdateBuilder#updateColumnExpression(String, String)} methods.
*
* @param preparedUpdate
* A prepared statement to match database rows to be deleted and define the columns to update.
* @return The number of rows updated in the database.
* @throws SQLException
* on any SQL problems.
* @throws IllegalArgumentException
* If there is only an ID field in the object. See the {@link #updateId} method.
*/
public int update(PreparedUpdate preparedUpdate) throws SQLException;
/**
* Does a query for the data parameter's id and copies in each of the field values from the database to refresh the
* data parameter. Any local object changes to persisted fields will be overwritten. If the database has been
* updated this brings your local object up to date.
*
* @param data
* The data item that we are refreshing with fields from the database.
* @return The number of rows found in the database that correspond to the data id. This should be 1.
* @throws SQLException
* on any SQL problems or if the data item is not found in the table or if more than 1 item is found
* with data's id.
*/
public int refresh(T data) throws SQLException;
/**
* Delete the database row corresponding to the id from the data parameter.
*
* @param data
* The data item that we are deleting from the database.
* @return The number of rows updated in the database. This should be 1.
* @throws SQLException
* on any SQL problems.
*/
public int delete(T data) throws SQLException;
/**
* Delete an object from the database that has an id.
*
* @param id
* The id of the item that we are deleting from the database.
* @return The number of rows updated in the database. This should be 1.
* @throws SQLException
* on any SQL problems.
*/
public int deleteById(ID id) throws SQLException;
/**
* Delete a collection of objects from the database using an IN SQL clause. The ids are extracted from the datas
* parameter and used to remove the corresponding rows in the database with those ids.
*
* @param datas
* A collection of data items to be deleted.
* @return The number of rows updated in the database. This should be the size() of the collection.
* @throws SQLException
* on any SQL problems.
*/
public int delete(Collection datas) throws SQLException;
/**
* Delete the objects that match the collection of ids from the database using an IN SQL clause.
*
* @param ids
* A collection of data ids to be deleted.
* @return The number of rows updated in the database. This should be the size() of the collection.
* @throws SQLException
* on any SQL problems.
*/
public int deleteIds(Collection ids) throws SQLException;
/**
* Delete the objects that match the prepared statement parameter.
*
* @param preparedDelete
* A prepared statement to match database rows to be deleted.
* @return The number of rows updated in the database.
* @throws SQLException
* on any SQL problems.
*/
public int delete(PreparedDelete preparedDelete) throws SQLException;
/**
* This satisfies the {@link Iterable} interface for the class and allows you to iterate through the objects in the
* table using SQL. You can use code similar to the following:
*
*
* for (Account account : accountDao) { ... }
*
*
*
* WARNING: because the {@link Iterator#hasNext()}, {@link Iterator#next()}, etc. methods can only throw
* {@link RuntimeException}, the code has to wrap any {@link SQLException} with {@link IllegalStateException}. Make
* sure to catch {@link IllegalStateException} and look for a {@link SQLException} cause.
*
*
*
* WARNING: The underlying results object will only be closed if you page all the way to the end of the
* iterator using the for() loop or if you call {@link CloseableIterator#close()} directly. You can also call the
* {@link #closeLastIterator()} if you are not iterating across this DAO in multiple threads.
*
*
*
* NOTE: With this iterator you can only move forward through the object collection. See the
* {@link #iterator(int)} method to create a cursor that can go both directions.
*
*
* @return An iterator of the class that uses SQL to step across the database table.
*
* @throws IllegalStateException
* When it encounters a SQLException or in other cases.
*/
@Override
public CloseableIterator iterator();
/**
* Same as {@link #iterator()} but while specifying flags for the results. This is necessary with certain database
* types. The resultFlags could be something like ResultSet.TYPE_SCROLL_INSENSITIVE or other values.
*
*
* WARNING: Depending on the database type the underlying connection may never be freed -- even if you go all
* of the way through the results. It is strongly recommended that you call the
* {@link CloseableIterator#close()} method when you are done with the iterator.
*
*/
public CloseableIterator iterator(int resultFlags);
/**
* Same as {@link #iterator()} but with a prepared query parameter. See {@link #queryBuilder} for more information.
* You use it like the following:
*
*
* QueryBuilder<Account, String> qb = accountDao.queryBuilder();
* ... custom query builder methods
* CloseableIterator<Account> iterator = partialDao.iterator(qb.prepare());
* try {
* while (iterator.hasNext()) {
* Account account = iterator.next();
* ...
* }
* } finish {
* iterator.close();
* }
*
*
* @param preparedQuery
* Query used to iterate across a sub-set of the items in the database.
* @return An iterator for T.
* @throws SQLException
* on any SQL problems.
*/
public CloseableIterator iterator(PreparedQuery preparedQuery) throws SQLException;
/**
* Same as {@link #iterator(PreparedQuery)} but while specifying flags for the results. This is necessary with
* certain database types.
*/
public CloseableIterator iterator(PreparedQuery preparedQuery, int resultFlags) throws SQLException;
/**
*
* This makes a one time use iterable class that can be closed afterwards. The DAO itself is
* {@link CloseableWrappedIterable} but multiple threads can each call this to get their own closeable iterable.
* This allows you to do something like:
*
*
*
* CloseableWrappedIterable<Foo> wrappedIterable = fooDao.getWrappedIterable();
* try {
* for (Foo foo : wrappedIterable) {
* ...
* }
* } finally {
* wrappedIterable.close();
* }
*
*/
public CloseableWrappedIterable getWrappedIterable();
/**
* Same as {@link #getWrappedIterable()} but with a prepared query parameter. See {@link #queryBuilder} or
* {@link #iterator(PreparedQuery)} for more information.
*/
public CloseableWrappedIterable getWrappedIterable(PreparedQuery preparedQuery);
/**
* This closes the last iterator returned by the {@link #iterator()} method.
*
*
* NOTE: This is not reentrant. If multiple threads are getting iterators from this DAO then you should use
* the {@link #getWrappedIterable()} method to get a wrapped iterable for each thread instead.
*
*/
public void closeLastIterator() throws IOException;
/**
*
* Similar to the {@link #iterator(PreparedQuery)} except it returns a GenericRawResults object associated with the
* SQL select query argument. Although you should use the {@link #iterator()} for most queries, this method allows
* you to do special queries that aren't supported otherwise. Like the above iterator methods, you must call close
* on the returned RawResults object once you are done with it. The arguments are optional but can be set with
* strings to expand ? type of SQL.
*
*
*
* You can use the {@link QueryBuilder#prepareStatementString()} method here if you want to build the query using
* the structure of the QueryBuilder.
*
*
*
* QueryBuilder<Account, Integer> qb = accountDao.queryBuilder();
* qb.where().ge("orderCount", 10);
* results = accountDao.queryRaw(qb.prepareStatementString());
*
*
*
* If you want to use the QueryBuilder with arguments to the raw query then you should do something like:
*
*
*
* QueryBuilder<Account, Integer> qb = accountDao.queryBuilder();
* // we specify a SelectArg here to generate a ? in the statement string below
* qb.where().ge("orderCount", new SelectArg());
* // the 10 at the end is an optional argument to fulfill the SelectArg above
* results = accountDao.queryRaw(qb.prepareStatementString(), rawRowMapper, 10);
*
*
*
* NOTE: If you are using the {@link QueryBuilder#prepareStatementString()} to build your query, it may have
* added the id column to the selected column list if the Dao object has an id you did not include it in the columns
* you selected. So the results might have one more column than you are expecting.
*
*/
public GenericRawResults queryRaw(String query, String... arguments) throws SQLException;
/**
* Similar to the {@link #queryRaw(String, String...)} but this iterator returns rows that you can map yourself. For
* every result that is returned by the database, the {@link RawRowMapper#mapRow(String[], String[])} method is
* called so you can convert the result columns into an object to be returned by the iterator. The arguments are
* optional but can be set with strings to expand ? type of SQL. For a simple implementation of a raw row mapper,
* see {@link #getRawRowMapper()}.
*/
public GenericRawResults queryRaw(String query, RawRowMapper mapper, String... arguments)
throws SQLException;
/**
* Similar to the {@link #queryRaw(String, RawRowMapper, String...)} but uses the column-types array to present an
* array of object results to the mapper instead of strings. The arguments are optional but can be set with strings
* to expand ? type of SQL.
*/
public GenericRawResults queryRaw(String query, DataType[] columnTypes, RawRowObjectMapper mapper,
String... arguments) throws SQLException;
/**
* Similar to the {@link #queryRaw(String, String...)} but instead of an array of String results being returned by
* the iterator, this uses the column-types parameter to return an array of Objects instead. The arguments are
* optional but can be set with strings to expand ? type of SQL.
*/
public GenericRawResults