package org.nutz.dao;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import org.nutz.dao.impl.DaoExecutor;
import org.nutz.dao.sql.DaoStatement;
import org.nutz.dao.sql.SqlContext;
import org.nutz.lang.random.R;
import org.nutz.log.Log;
import org.nutz.log.Logs;
/**
* Dao执行拦截器链.
*
* @author wendal
* @see org.nutz.dao.impl.interceptor.DaoLogInterceptor
* @see org.nutz.dao.impl.interceptor.DaoTimeInterceptor
*/
public class DaoInterceptorChain implements ConnCallback {
private static final Log log = Logs.get();
protected int autoTransLevel;
protected Connection connection;
protected int current = 0;
protected DaoStatement daoStatement;
protected DaoExecutor executor;
protected List<DaoInterceptor> interceptors = new ArrayList<DaoInterceptor>();
protected int updateCount;
protected DaoStatement[] sts;
protected String id;
/**
* 新建一个DaoInterceptorChain.
*
* @param sts
* 将要进行的Dao操作(不一定是SQL操作,有可能是EL)
*/
public DaoInterceptorChain(DaoStatement... sts) {
this.sts = sts;
id = R.UU32();
}
/**
* 继续下一个拦截器,如果已经是最后一个拦截器,那么执行executor.exec
*
* @return 本对象,用于链式操作
* @throws Exception
*/
public DaoInterceptorChain doChain() throws DaoException {
if (hasNext()) {
DaoInterceptor interceptor = next();
current++;
interceptor.filter(this);
} else {
executor.exec(getConnection(), getDaoStatement());
updateCount += getDaoStatement().getUpdateCount();
}
return this;
}
/**
* 获取当前自动事务级别,DaoRunner中使用强制事务时会使用之.拦截器不能修改,即使修改也不会生效
*
* @return 当前自动(强制)事务级别
*/
public int getAutoTransLevel() {
return autoTransLevel;
}
/**
* 当前执行的DaoStatement
*
* @return 当前执行的DaoStatement
*/
public DaoStatement getDaoStatement() {
return daoStatement;
}
/**
* 全部DaoStatement,可能不止一条
*
* @return 全部DaoStatement
*/
public DaoStatement[] getDaoStatements() {
return sts;
}
/**
* 拦截器列表(暂不开放修改)
*
* @return 全体拦截器列表
*/
public List<DaoInterceptor> getInterceptors() {
return interceptors;
}
/**
* 更新总数,用于DaoSupport(NutDao)获取更新总数.
*
* @return 更新记录总数
*/
public int getUpdateCount() {
return updateCount;
}
/**
* 是否还有下一个拦截器
*
* @return true,如果还有拦截器要执行
*/
public boolean hasNext() {
return current < interceptors.size();
}
/**
* 这是DaoExecutor会执行的方法,拦截器内不要执行这个方法!! 这里也是拦截器开始生效的地方.
*/
public void invoke(Connection conn) throws Exception {
for (DaoStatement st : sts) {
if (st == null) {
if (log.isInfoEnabled())
log.info("Found a null DaoStatement(SQL), ingore it ~~");
continue;
}
current = 0;
daoStatement = st;
this.connection = conn;
doChain();
}
}
/**
* 获取下一个拦截器. 调用前必须先调用hasNext进行判断
*
* @return 下一个拦截器
*/
public DaoInterceptor next() {
return interceptors.get(current);
}
/**
* 设置强制事务的级别,对拦截器来说无意义.
*
* @param autoTransLevel
* 与DaoSupport(NutDao)内的值一致
*/
public void setAutoTransLevel(int autoTransLevel) {
this.autoTransLevel = autoTransLevel;
}
/**
* 设置当前拦截器索引. 若设置值大于拦截器列表的大小,那么效果就等同于跳过剩余拦截器,直接执行DaoStatement
*
* @param current
*/
public void setCurrent(int current) {
this.current = current;
}
/**
* 设置DaoExecutor. 典型应用是在拦截器中替换成daocache提供的DaoExecutor
*
* @param executor
* 新的DaoExecutor,不可以是null
*/
public void setExecutor(DaoExecutor executor) {
this.executor = executor;
}
/**
* 设置新的拦截器列表.
*
* @param interceptors
* 新的拦截器列表
*/
public void setInterceptors(List<DaoInterceptor> interceptors) {
this.interceptors = interceptors;
}
/**
* 设置当前使用的数据库连接
*
* @param connection
* 新的数据库连接,不可以是null
*/
public void setConnection(Connection connection) {
this.connection = connection;
}
/**
* 获取当前数据库连接
*
* @return 当前数据库连接
*/
public Connection getConnection() {
return connection;
}
/**
* 获取当前DaoStatement的上下文,注意,一个拦截器链可能包含多个DaoStatement
*
* @return 当前DaoStatement的上下文
*/
public SqlContext getSqlContext() {
return getDaoStatement().getContext();
}
/**
* 拦截器链的id, 为一个uu32识别符.
*
* @return 本拦截器链的id
*/
public String getId() {
return id;
}
}