/**
* $Id$
* $URL$
* JdbcBasicGenericDao.java - genericdao - Apr 26, 2008 12:27:46 AM - azeckoski
**************************************************************************
* Copyright (c) 2008 Aaron Zeckoski
* Licensed under the Apache License, Version 2
*
* A copy of the Apache License, Version 2 has been included in this
* distribution and is available at: http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Aaron Zeckoski ([email protected]) ([email protected]) ([email protected])
*/
package org.sakaiproject.genericdao.springjdbc;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.azeckoski.reflectutils.ArrayUtils;
import org.sakaiproject.genericdao.api.BasicGenericDao;
import org.sakaiproject.genericdao.api.finders.ByPropsFinder;
import org.sakaiproject.genericdao.api.mappers.DataMapper;
import org.sakaiproject.genericdao.api.mappers.NamesRecord;
import org.sakaiproject.genericdao.api.mappers.StatementMapper;
import org.sakaiproject.genericdao.api.search.Order;
import org.sakaiproject.genericdao.api.search.Restriction;
import org.sakaiproject.genericdao.api.search.Search;
import org.sakaiproject.genericdao.api.translators.DatabaseTranslator;
import org.sakaiproject.genericdao.springjdbc.translators.BasicTranslator;
import org.sakaiproject.genericdao.util.JDBCUtils;
import org.sakaiproject.genericdao.util.JDBCUtils.QueryData;
/**
* Spring JDBC based implementation of BasicGenericDao which can be extended to add more
* specialized DAO methods.
*
* See the overview for installation/usage tips.
*
* @author Aaron Zeckoski ([email protected])
*/
@SuppressWarnings("deprecation")
public class JdbcBasicGenericDao extends JdbcGenericDao implements BasicGenericDao {
/**
* Default constructor - does nothing and leaves the object in an incomplete state,
* you need to at least set the following:
* {@link #setDataSource(DataSource)}
* {@link #setAutoDDL(boolean)}
* {@link #setAutoCommitDDL(boolean)}
* {@link #setDatabaseType(String)}
* {@link #setDataMappers(List)}
*
* This does not actually start the DAO, run {@link #startup()} to start it
* Note that this will be started automatically by Spring if this is created as a Spring bean,
* no actions are necessary and setting an init method is not needed
*/
public JdbcBasicGenericDao() {
super();
}
/**
* Complete constructor, sets all required values for running the DAO,
* does not actually start the DAO, run {@link #startup()} to start it
* Note that this will be started automatically by Spring if this is created as a Spring bean,
* no actions are necessary and setting an init method is not needed
*
* @param dataSource the DataSource to use with this DAO
* @param threadBoundDataSource if true then the DataSource will be bound to threads and
* only unbound and closed when {@link #closeConnection()} is called,
* otherwise a new DataSource is obtained each time,
* this has no effect if the DataSource is a Spring DataSource
* @param databaseType the databaseType that this DAO is connecting to (use constants in {@link DatabaseTranslator})
* @param autoDDL if true then DDL is executed on DAO startup (can be run manually if desired)
* @param autoCommitDDL if true then commit is executed after each DDL file is executed, if false then you need a TX manager to do this for you
* @param dataMappers the data mappers which map this DAO to the tables
*/
public JdbcBasicGenericDao(DataSource dataSource, boolean threadBoundDataSource,
String databaseType, boolean autoDDL, boolean autoCommitDDL, DataMapper[] dataMappers) {
super(dataSource, threadBoundDataSource, databaseType, autoDDL, autoCommitDDL, dataMappers);
}
protected QueryData makeQueryFromSearch(Class> type, Search search) {
// Checks to see if the required params are set and throws exception if not
if (search == null) {
throw new IllegalArgumentException("search cannot be null");
}
NamesRecord namesRecord = getNamesRecord(type);
return JDBCUtils.makeSQLfromSearch(namesRecord, search);
}
// OVERRIDES
protected long baseCountBySearch(Class type, Search search) {
QueryData sd = makeQueryFromSearch(type, search);
String sql = makeSQL(getSelectTemplate(type), getTableNameFromClass(type),
StatementMapper.SELECT, "count(*)", StatementMapper.WHERE, sd.getAfterTableSQL());
if (showSQL) {
logInfo("SQL="+sql+":\n Params="+ArrayUtils.arrayToString(sd.getArgs()));
}
long count = getSpringJdbcTemplate().queryForObject(sql, Long.class, sd.getArgs());
return count;
}
@SuppressWarnings("unchecked")
protected List baseFindBySearch(Class type, Search search) {
String tableName = getTableNameFromClass(type);
QueryData sd = makeQueryFromSearch(type, search);
String sql = makeSQL(getSelectTemplate(type), tableName,
StatementMapper.SELECT, tableName + ".*", StatementMapper.WHERE, sd.getAfterTableSQL());
// handle limit/offset
int firstResult = (int) search.getStart();
int maxResults = (int) search.getLimit();
if (firstResult > 0 || maxResults > 0) {
sql = getDatabaseTranslator().makeLimitQuery(sql, search.getStart(), search.getLimit(), tableName);
getSpringJdbcTemplate().setMaxRows(firstResult + maxResults); // this limit is always ok to put in
}
if (showSQL) {
logInfo("SQL="+sql+":\n Params="+ArrayUtils.arrayToString(sd.getArgs()));
}
List