package jef.database;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import jef.database.dialect.DatabaseDialect;
import jef.database.query.JoinElement;
import jef.database.query.SqlContext;
import jef.database.routing.PartitionResult;
import jef.database.support.SqlLog;
import jef.database.wrapper.clause.BindSql;
import jef.database.wrapper.executor.DbTask;
import jef.database.wrapper.variable.BindVariableContext;
/**
* 基本数据库操作
*
* @author jiyi
*
*/
public abstract class DeleteProcessor {
abstract int processDelete0(OperateTarget db, IQueryableEntity obj, BindSql where, PartitionResult site, SqlLog sb) throws SQLException;
abstract BindSql toWhereClause(JoinElement joinElement, SqlContext context, DatabaseDialect profile);
static DeleteProcessor get(DatabaseDialect profile, DbClient parent) {
return new PreparedImpl(parent.preProcessor);
}
final int processDelete(Session session, final IQueryableEntity obj, final BindSql where, PartitionResult[] sites, long parseCost) throws SQLException {
long parse = System.currentTimeMillis();
final SqlLog log = ORMConfig.getInstance().newLogger();
int total = 0;
String dbname = null;
if (sites.length >= ORMConfig.getInstance().getParallelSelect()) {
List<DbTask> tasks = new ArrayList<DbTask>();
final AtomicInteger count = new AtomicInteger();
for (final PartitionResult site : sites) {
final OperateTarget target = session.selectTarget(site.getDatabase());
dbname = target.getTransactionId();
tasks.add(new DbTask() {
@Override
public void execute() throws SQLException {
count.addAndGet(processDelete0(target, obj, where, site, log));
}
});
}
DbUtils.parallelExecute(tasks);
total = count.get();
} else {
for (PartitionResult site : sites) {
OperateTarget target = session.selectTarget(site.getDatabase());
dbname = target.getTransactionId();
total += processDelete0(target, obj, where, site, log);
}
}
log.append("Deleted:", total).append("\t Time cost([ParseSQL]:", parse - parseCost).append("ms, [DbAccess]:", System.currentTimeMillis() - parse).append("ms) |", dbname);
log.output();
return total;
}
private static final class PreparedImpl extends DeleteProcessor {
private SqlProcessor parent;
public PreparedImpl(SqlProcessor parent) {
this.parent = parent;
}
int processDelete0(OperateTarget db, IQueryableEntity obj, BindSql where, PartitionResult site, SqlLog sb) throws SQLException {
int count = 0;
for (String tablename : site.getTables()) {
String sql = "delete from " + DbUtils.escapeColumn(db.getProfile(), tablename) + where.getSql();
sb.ensureCapacity(sql.length() + 150);
sb.append(sql).append(db);
PreparedStatement psmt = null;
try {
psmt = db.prepareStatement(sql);
int deleteTimeout = ORMConfig.getInstance().getDeleteTimeout();
if (deleteTimeout > 0) {
psmt.setQueryTimeout(deleteTimeout);
}
BindVariableContext context = new BindVariableContext(psmt, db.getProfile(), sb);
context.setVariables(obj.getQuery(), null, where.getBind());
psmt.execute();
count += psmt.getUpdateCount();
} catch (SQLException e) {
DbUtils.processError(e, tablename, db);
db.releaseConnection();// 如果在处理过程中发现异常,方法即中断,就要释放连接,这样就不用在外面再套一层finally
throw e;
} catch (RuntimeException e) {
db.releaseConnection();// 如果在处理过程中发现异常,方法即中断,就要释放连接,这样就不用在外面再套一层finally
} finally {
sb.output();
if (psmt != null)
psmt.close();
}
}
db.releaseConnection();
return count;
}
@Override
BindSql toWhereClause(JoinElement joinElement, SqlContext context, DatabaseDialect profile) {
return parent.toWhereClause(joinElement, context, null, profile,false);
}
}
}