package li.dao_2;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.List;
import javax.sql.DataSource;
import li.dao.Page;
import li.dao.Record;
import li.dao.Trans;
import li.ioc.Ioc;
import li.model.Bean;
import li.model.Field;
import li.util.Log;
import li.util.Reflect;
import li.util.Verify;
/**
* AbstractDao,通常,业务对象的Dao要继承这个基类
*
* @param <T> 指示对象类型
* @param <ID> 指示ID类型
* @author li (limingwei@mail.com)
* @version 0.1.7 (2012-06-26)
*/
public class AbstractDao<T, ID extends Serializable> {
private static final Log log = Log.init();
private Class<T> modelType;// 泛型参数的实际类型,即是数据对象类型
private Bean beanMeta;// 存储数据对象结构
private QueryBuilder queryBuilder;// QueryBuilder,SQL构造器
private DataSource dataSource;// 当前Dao的DataSource
/**
* 如果还没有注入dataSource,则尝试次从Ioc中搜索DataSource类型的Bean
*/
public DataSource getDataSource() {
if (null == this.dataSource) {
log.warn("DataSource not injected for ?", this);
this.dataSource = Ioc.get(DataSource.class);
}
return this.dataSource;
}
/**
* setDataSource
*/
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 得到一个Connection,从Trans或者从Datasource
*
* @see li.dao.Trans
* @see li.dao.QueryRunner
*/
public Connection getConnection() {
try {
Trans trans = Trans.current();
if (null == trans) {// 如果未进入事务
return this.getDataSource().getConnection();// 则简单获取一个connection
} else { // 如果已经进入事务
return trans.getConnection(this.getDataSource());
}
} catch (Exception e) {
throw new RuntimeException(e + " ", e);
}
}
/**
* 通过泛型参数得到modelType
*
* @see li.util.Reflect#actualTypes(Class)
*/
public Class<T> getType() {
if (null == this.modelType) {
this.modelType = (Class<T>) Reflect.actualTypes(getClass())[0]; // 通过泛型参数得到modelType,在Record中可以直接通过getClass得到
}
return this.modelType;
}
/**
* 得到当前Dao所操作的数据对象的结构
*
* @see li.model.Bean#getMeta(DataSource, Class)
*/
public Bean getBeanMeta() {
if (null == this.beanMeta) {
this.beanMeta = Bean.getMeta(getDataSource(), getType());
}
return this.beanMeta;
}
/**
* 得到SQL构造器
*
* @see li.dao.QueryBuilder
*/
public QueryBuilder getQueryBuilder() {
if (null == this.queryBuilder) {
QueryBuilder queryBuilder = new QueryBuilder();
this.queryBuilder = queryBuilder;
}
if (null == this.queryBuilder.beanMeta) {
this.queryBuilder.beanMeta = this.getBeanMeta();
}
return this.queryBuilder;
}
/**
* setQueryBuilder
*/
public void setQueryBuilder(QueryBuilder queryBuilder) {
this.queryBuilder = queryBuilder;
}
/**
* 得到 ModelBuilder
*
* @see li.dao.ModelBuilder
*/
public ModelBuilder getModelBuilder(QueryRunner queryRunner, ResultSet resultSet) {
return new ModelBuilder(queryRunner, resultSet);
}
/**
* 得到 QueryRunner
*
* @see li.dao.QueryRunner
*/
public QueryRunner getQueryRunner(Connection connection) {
return new QueryRunner(connection);
}
/**
* 查询对象对应的表的总记录数
*
* @see li.dao.AbstractDao#count(String, Object...)
*/
public Integer count() {
return count(getQueryBuilder().countAll());
}
/**
* 根据SQL条件查询返回一个数字
*
* @param sql 传入的sql语句,可以包含'?'占位符和具名占位符
* @param args 替换sql中占位符的值,或者对应具名占位符的Map
*/
public Integer count(String sql, Object... args) {
QueryRunner queryRunner = this.getQueryRunner(this.getConnection());
String _sql = getQueryBuilder().countBySql(sql, args);
ResultSet resultSet = queryRunner.executeQuery(_sql);
ModelBuilder modelBuilder = this.getModelBuilder(queryRunner, resultSet);
String count = modelBuilder.value(1, true, true);
return Verify.isEmpty(count) ? -1 : Integer.valueOf(count);
}
/**
* 删除ID等于传入参数的一条记录,如果存在的话
*
* @see li.dao.AbstractDao#delete(String, Object...)
*/
public Boolean delete(ID id) {
return 0 < delete(getQueryBuilder().deleteById(id));
}
/**
* 根据SQL条件删除若干条数据
*
* @param sql 传入的sql语句,可以包含'?'占位符和具名占位符
* @param args 替换sql中占位符的值,或者对应具名占位符的Map
* @return 受影响的行数
* @see li.dao.AbstractDao#update(String, Object...)
*/
public Integer delete(String sql, Object... args) {
String _sql = getQueryBuilder().deleteBySql(sql, args);
QueryRunner queryRunner = this.getQueryRunner(this.getConnection());
return queryRunner.executeUpdate(_sql, false);
}
/**
* 根据ID查询一条记录
*
* @see li.dao.AbstractDao#find(String, Object...)
*/
public T find(ID id) {
return find(this.getQueryBuilder().findById(), id);
}
/**
* 根据SQL条件查询一条记录
*
* @param sql 传入的sql语句,可以包含'?'占位符和具名占位符
* @param args 替换sql中占位符的值,或者对应具名占位符的Map
* @see li.dao.AbstractDao#list(Page, String, Object...)
*/
public T find(String sql, Object... args) {
List<T> list = this.list(sql, args);
return null != list && list.size() > 0 ? list.get(0) : null;
}
/**
* 根据分页对象进行分页查询,如果page不为NULL,他会被自动设置总记录数
*
* @see li.dao.AbstractDao#list(Page, String, Object...)
*/
public List<T> list(Page page) {
QueryBuilder queryBuilder = this.getQueryBuilder();
return this.list(queryBuilder.list(), page.getFrom(), page.getPageSize());
}
/**
* 根据SQL条件和分页对象进行分页查询
*
* @param sql 传入的sql语句,可以包含'?'占位符和具名占位符
* @param args 替换sql中占位符的值,或者对应具名占位符的Map
*/
public List<T> list(String sql, Object... args) {
QueryRunner queryRunner = this.getQueryRunner(this.getConnection());
ResultSet resultSet = queryRunner.executeQuery(sql, args);
ModelBuilder modelBuilder = this.getModelBuilder(queryRunner, resultSet);
return modelBuilder.list(getType(), getBeanMeta().fields, true);
}
/**
* 执行SQL查询并将结果集封装成Record或其子类的List
*/
public List<Record<?, ?>> query(Page page, String sql, Object... args) {
String _sql = getQueryBuilder().listBySql(page, sql, args);
QueryRunner queryRunner = this.getQueryRunner(this.getConnection());
ResultSet resultSet = queryRunner.executeQuery(_sql);
ModelBuilder modelBuilder = this.getModelBuilder(queryRunner, resultSet);
if (null != resultSet && null != page && page.count()) {
page.setRecordCount(count(_sql));
}
Integer count = null == page ? Integer.MAX_VALUE : page.getPageSize();
Class<?> type = Record.class.isAssignableFrom(getType()) ? getType() : Record.class;// Record类型或其子类
return (List<Record<?, ?>>) modelBuilder.list(type, Field.list(resultSet), count, true);
}
/**
* 向数据库中插入一条记录,完成后,对象的ID将会被设值
*/
public Boolean save(T entity) {
QueryRunner queryRunner = this.getQueryRunner(this.getConnection());
Integer updateCount = queryRunner.executeUpdate(getQueryBuilder().insert(entity), true);
Reflect.set(entity, getBeanMeta().getId().name, queryRunner.getLastInsertId());// 设置对象ID为最后主键值
return 0 < updateCount;
}
/**
* 向数据库中插入一条记录,忽略为空的属性,完成后,对象的ID将会被设值
*/
public Boolean saveIgnoreNull(T entity) {
QueryRunner queryRunner = this.getQueryRunner(this.getConnection());
Integer updateCount = queryRunner.executeUpdate(getQueryBuilder().insertIgnoreNull(entity), true);
Reflect.set(entity, getBeanMeta().getId().name, queryRunner.getLastInsertId());// 设置对象ID为最后主键值
return 0 < updateCount;
}
/**
* 向数据库中插入一条记录
*/
public Boolean insert(T entity) {
QueryRunner queryRunner = this.getQueryRunner(this.getConnection());
return 0 < queryRunner.executeUpdate(getQueryBuilder().insert(entity), false);
}
/**
* 向数据库中插入一条记录,忽略为空的属性
*/
public Boolean insertIgnoreNull(T entity) {
QueryRunner queryRunner = this.getQueryRunner(this.getConnection());
return 0 < queryRunner.executeUpdate(getQueryBuilder().insertIgnoreNull(entity), false);
}
/**
* 执行更新类的自定义SQL
*
* @param sql 传入的sql语句,可以包含'?'占位符和具名占位符
* @param args 替换sql中占位符的值,或者对应具名占位符的Map
* @return 受影响的行数
*/
public Integer update(String sql, Object... args) {
String _sql = getQueryBuilder().updateBySql(sql, args);
QueryRunner queryRunner = this.getQueryRunner(this.getConnection());
return queryRunner.executeUpdate(_sql, false);
}
/**
* 更新一个对象,根据ID得到对象,然后更新其他属性值
*
* @see li.dao.AbstractDao#update(String, Object...)
*/
public Boolean update(T entity) {
return 0 < update(getQueryBuilder().update(entity));
}
/**
* 更新一个数据对象,忽略其中值为null的属性
*
* @see li.dao.AbstractDao#update(String, Object...)
*/
public Boolean updateIgnoreNull(T entity) {
return 0 < update(getQueryBuilder().updateIgnoreNull(entity));
}
}