需求:拦截系统所有删除sql,修改为假删除,即更新数据的删除状态
1.建立类PreparedStatementHandler,注意包路径与mybatis-3.2.3.jar一致
package org.apache.ibatis.executor.statement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
public class PreparedStatementHandler extends BaseStatementHandler {
public PreparedStatementHandler(Executor executor,
MappedStatement mappedStatement, Object parameter,
RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
super(executor, mappedStatement, parameter, rowBounds, resultHandler,
boundSql);
}
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
keyGenerator.processAfter(executor, mappedStatement, ps,
parameterObject);
return rows;
}
public void batch(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.addBatch();
}
public <E> List<E> query(Statement statement, ResultHandler resultHandler)
throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.<E> handleResultSets(ps);
}
protected Statement instantiateStatement(Connection connection)
throws SQLException {
String sql = boundSql.getSql();
//删除语句替换为修改
sql = changeDeleteSql2UpdateSql(sql);
if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
String[] keyColumnNames = mappedStatement.getKeyColumns();
if (keyColumnNames == null) {
return connection.prepareStatement(sql,
PreparedStatement.RETURN_GENERATED_KEYS);
} else {
return connection.prepareStatement(sql, keyColumnNames);
}
} else if (mappedStatement.getResultSetType() != null) {
return connection.prepareStatement(sql, mappedStatement
.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
} else {
return connection.prepareStatement(sql);
}
}
public void parameterize(Statement statement) throws SQLException {
parameterHandler.setParameters((PreparedStatement) statement);
}
/**
* 变化删除语句为更新语句
* @param originalSql 原始语句
* @return 变化后的语句
*/
private String changeDeleteSql2UpdateSql(String originalSql) {
Pattern patternDelete = Pattern.compile("\\bdelete\\b",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
Matcher matcherDelete = patternDelete.matcher(originalSql);
// 如果是删除语句
if (matcherDelete.find()) {
StringBuffer updateSql = new StringBuffer();
// 找到from关键字
Pattern patternFrom = Pattern.compile("\\bfrom\\b",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
Matcher matcherFrom = patternFrom.matcher(originalSql);
// 得到from关键字的结尾位置
if (matcherFrom.find()) {
int indexFromEnd = matcherFrom.end();
// 找到where的开头位置
Pattern patternWhere = Pattern.compile("\\bwhere\\b",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
Matcher matcherWhere = patternWhere.matcher(originalSql);
String tableName = "";
String whereSql = "";
// 如果找到where,where和from之间的都是表名
if (matcherWhere.find()) {
int indexWhereStart = matcherWhere.start();
tableName = originalSql.substring(indexFromEnd,
indexWhereStart);
whereSql = originalSql.substring(indexWhereStart);
}
// 如果没找到where,认为后面的都是表名
else {
tableName = originalSql.substring(indexFromEnd);
}
//如果表为工作流中的数据库表,则不做任何操作,直接返回。
if(tableName.toUpperCase().trim().startsWith("ACT_") || tableName.toUpperCase().trim().startsWith("PPP_")){
return originalSql;
}
if (tableName != null && !tableName.trim().equals("")) {
updateSql.append("UPDATE ").append(tableName)
.append(" SET STATUS='2' ").append(whereSql);
}
if (updateSql != null && updateSql.length() > 1) {
originalSql = updateSql.toString();
}
}
}
return originalSql;
}
}
如此,项目移动后自定义的类会替换mybatis-3.2.3.jar中的对应类,即实现类的覆盖。