1.创建工具类
import org.apache.ibatis.builder.StaticSqlSource;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.Configuration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author honghh
* @version 2017/11/9
*/
public class SqlMapper {
private final MSUtils msUtils;
private final SqlSession sqlSession;
/**
* 构造方法,默认缓存MappedStatement
*
* @param sqlSession
*/
public SqlMapper(SqlSession sqlSession) {
this.sqlSession = sqlSession;
this.msUtils = new MSUtils(sqlSession.getConfiguration());
}
/**
* 获取List中最多只有一个的数据
*
* @param list List结果
* @param <T> 泛型类型
* @return
*/
private <T> T getOne(List<T> list) {
if (list.size() == 1) {
return list.get(0);
} else if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
/**
* 查询返回一个结果,多个结果时抛出异常
*
* @param sql 执行的sql
* @return
*/
public Map<String, Object> selectOne(String sql) {
List<Map<String, Object>> list = selectList(sql);
return getOne(list);
}
/**
* 查询返回一个结果,多个结果时抛出异常
*
* @param sql 执行的sql
* @param value 参数
* @return
*/
public Map<String, Object> selectOne(String sql, Object value) {
List<Map<String, Object>> list = selectList(sql, value);
return getOne(list);
}
/**
* 查询返回一个结果,多个结果时抛出异常
*
* @param sql 执行的sql
* @param resultType 返回的结果类型
* @param <T> 泛型类型
* @return
*/
public <T> T selectOne(String sql, Class<T> resultType) {
List<T> list = selectList(sql, resultType);
return getOne(list);
}
/**
* 查询返回一个结果,多个结果时抛出异常
*
* @param sql 执行的sql
* @param value 参数
* @param resultType 返回的结果类型
* @param <T> 泛型类型
* @return
*/
public <T> T selectOne(String sql, Object value, Class<T> resultType) {
List<T> list = selectList(sql, value, resultType);
return getOne(list);
}
/**
* 查询返回List<Map<String, Object>>
*
* @param sql 执行的sql
* @return
*/
public List<Map<String, Object>> selectList(String sql) {
String msId = msUtils.select(sql);
return sqlSession.selectList(msId);
}
/**
* 查询返回List<Map<String, Object>>
*
* @param sql 执行的sql
* @param value 参数
* @return
*/
public List<Map<String, Object>> selectList(String sql, Object value) {
Class<?> parameterType = value != null ? value.getClass() : null;
String msId = msUtils.selectDynamic(sql, parameterType);
return sqlSession.selectList(msId, value);
}
/**
* 查询返回指定的结果类型
*
* @param sql 执行的sql
* @param resultType 返回的结果类型
* @param <T> 泛型类型
* @return
*/
public <T> List<T> selectList(String sql, Class<T> resultType) {
String msId;
if (resultType == null) {
msId = msUtils.select(sql);
} else {
msId = msUtils.select(sql, resultType);
}
return sqlSession.selectList(msId);
}
/**
* 查询返回指定的结果类型
*
* @param sql 执行的sql
* @param value 参数
* @param resultType 返回的结果类型
* @param <T> 泛型类型
* @return
*/
public <T> List<T> selectList(String sql, Object value, Class<T> resultType) {
String msId;
Class<?> parameterType = value != null ? value.getClass() : null;
if (resultType == null) {
msId = msUtils.selectDynamic(sql, parameterType);
} else {
msId = msUtils.selectDynamic(sql, parameterType, resultType);
}
return sqlSession.selectList(msId, value);
}
/**
* 插入数据
*
* @param sql 执行的sql
* @return
*/
public int insert(String sql) {
String msId = msUtils.insert(sql);
return sqlSession.insert(msId);
}
/**
* 插入数据
*
* @param sql 执行的sql
* @param value 参数
* @return
*/
public int insert(String sql, Object value) {
Class<?> parameterType = value != null ? value.getClass() : null;
String msId = msUtils.insertDynamic(sql, parameterType);
return sqlSession.insert(msId, value);
}
/**
* 更新数据
*
* @param sql 执行的sql
* @return
*/
public int update(String sql) {
String msId = msUtils.update(sql);
return sqlSession.update(msId);
}
/**
* 更新数据
*
* @param sql 执行的sql
* @param value 参数
* @return
*/
public int update(String sql, Object value) {
Class<?> parameterType = value != null ? value.getClass() : null;
String msId = msUtils.updateDynamic(sql, parameterType);
return sqlSession.update(msId, value);
}
/**
* 删除数据
*
* @param sql 执行的sql
* @return
*/
public int delete(String sql) {
String msId = msUtils.delete(sql);
return sqlSession.delete(msId);
}
/**
* 删除数据
*
* @param sql 执行的sql
* @param value 参数
* @return
*/
public int delete(String sql, Object value) {
Class<?> parameterType = value != null ? value.getClass() : null;
String msId = msUtils.deleteDynamic(sql, parameterType);
return sqlSession.delete(msId, value);
}
private class MSUtils {
private Configuration configuration;
private LanguageDriver languageDriver;
private MSUtils(Configuration configuration) {
this.configuration = configuration;
languageDriver = configuration.getDefaultScriptingLanuageInstance();
}
/**
* 创建MSID
*
* @param sql 执行的sql
* @param sql 执行的sqlCommandType
* @return
*/
private String newMsId(String sql, SqlCommandType sqlCommandType) {
StringBuilder msIdBuilder = new StringBuilder(sqlCommandType.toString());
msIdBuilder.append(".").append(sql.hashCode());
return msIdBuilder.toString();
}
/**
* 是否已经存在该ID
*
* @param msId
* @return
*/
private boolean hasMappedStatement(String msId) {
return configuration.hasStatement(msId, false);
}
/**
* 创建一个查询的MS
*
* @param msId
* @param sqlSource 执行的sqlSource
* @param resultType 返回的结果类型
*/
private void newSelectMappedStatement(String msId, SqlSource sqlSource, final Class<?> resultType) {
MappedStatement ms = new MappedStatement.Builder(configuration, msId, sqlSource, SqlCommandType.SELECT)
.resultMaps(new ArrayList<ResultMap>() {
{
add(new ResultMap.Builder(configuration, "defaultResultMap", resultType, new ArrayList<ResultMapping>(0)).build());
}
})
.build();
//缓存
configuration.addMappedStatement(ms);
}
/**
* 创建一个简单的MS
*
* @param msId
* @param sqlSource 执行的sqlSource
* @param sqlCommandType 执行的sqlCommandType
*/
private void newUpdateMappedStatement(String msId, SqlSource sqlSource, SqlCommandType sqlCommandType) {
MappedStatement ms = new MappedStatement.Builder(configuration, msId, sqlSource, sqlCommandType)
.resultMaps(new ArrayList<ResultMap>() {
{
add(new ResultMap.Builder(configuration, "defaultResultMap", int.class, new ArrayList<ResultMapping>(0)).build());
}
})
.build();
//缓存
configuration.addMappedStatement(ms);
}
private String select(String sql) {
String msId = newMsId(sql, SqlCommandType.SELECT);
if (hasMappedStatement(msId)) {
return msId;
}
StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql);
newSelectMappedStatement(msId, sqlSource, Map.class);
return msId;
}
private String selectDynamic(String sql, Class<?> parameterType) {
String msId = newMsId(sql + parameterType, SqlCommandType.SELECT);
if (hasMappedStatement(msId)) {
return msId;
}
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType);
newSelectMappedStatement(msId, sqlSource, Map.class);
return msId;
}
private String select(String sql, Class<?> resultType) {
String msId = newMsId(resultType + sql, SqlCommandType.SELECT);
if (hasMappedStatement(msId)) {
return msId;
}
StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql);
newSelectMappedStatement(msId, sqlSource, resultType);
return msId;
}
private String selectDynamic(String sql, Class<?> parameterType, Class<?> resultType) {
String msId = newMsId(resultType + sql + parameterType, SqlCommandType.SELECT);
if (hasMappedStatement(msId)) {
return msId;
}
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType);
newSelectMappedStatement(msId, sqlSource, resultType);
return msId;
}
private String insert(String sql) {
String msId = newMsId(sql, SqlCommandType.INSERT);
if (hasMappedStatement(msId)) {
return msId;
}
StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql);
newUpdateMappedStatement(msId, sqlSource, SqlCommandType.INSERT);
return msId;
}
private String insertDynamic(String sql, Class<?> parameterType) {
String msId = newMsId(sql + parameterType, SqlCommandType.INSERT);
if (hasMappedStatement(msId)) {
return msId;
}
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType);
newUpdateMappedStatement(msId, sqlSource, SqlCommandType.INSERT);
return msId;
}
private String update(String sql) {
String msId = newMsId(sql, SqlCommandType.UPDATE);
if (hasMappedStatement(msId)) {
return msId;
}
StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql);
newUpdateMappedStatement(msId, sqlSource, SqlCommandType.UPDATE);
return msId;
}
private String updateDynamic(String sql, Class<?> parameterType) {
String msId = newMsId(sql + parameterType, SqlCommandType.UPDATE);
if (hasMappedStatement(msId)) {
return msId;
}
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType);
newUpdateMappedStatement(msId, sqlSource, SqlCommandType.UPDATE);
return msId;
}
private String delete(String sql) {
String msId = newMsId(sql, SqlCommandType.DELETE);
if (hasMappedStatement(msId)) {
return msId;
}
StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql);
newUpdateMappedStatement(msId, sqlSource, SqlCommandType.DELETE);
return msId;
}
private String deleteDynamic(String sql, Class<?> parameterType) {
String msId = newMsId(sql + parameterType, SqlCommandType.DELETE);
if (hasMappedStatement(msId)) {
return msId;
}
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, parameterType);
newUpdateMappedStatement(msId, sqlSource, SqlCommandType.DELETE);
return msId;
}
}
}
2,创建service
@Service
public class DataMaintainService {
private Logger logger = LoggerFactory.getLogger(DataMaintainService.class);
@Autowired
DataMaintainHandler dataMaintainHandler;
@Autowired
protected SqlMapper sqlMapper;
private static final String SQL_EXECUTE_CONFIG = "SqlExecuteConfig";
private static final String DO_SQL_CODE = "DoSqlCode";
/**
* 执行sql<br>
* 此方法允许在归档库或生产库执行,执行的sql会被记录相应的maintain_log表中。 即执行生产执行sql记录生产maintain_log表
*
* @param
* @return
*/
public List<String> execSql(LoginBean user, String orgSql) throws DataException {
if (StringUtil.isBlank(orgSql)) {
return null;
}
String sqls = orgSql.replaceAll("\\r|\\t|\\v|\\e|\\f", "");
String[] arr = TextUtils.split(sqls, ";\\n");
if (arr == null || arr.length < 1) {
return null;
}
List<String> result = new ArrayList<String>();
List<ThxMaintainLog> maintainLogs = new ArrayList<ThxMaintainLog>();
boolean isException = false;
Exception resultException = null;
for (int i = 0; i < arr.length; i++) {
// 如果sql为空不执行
String sql = arr[i];
if (StringUtil.isBlank(sql)) {
continue;
}
sql = sql.replaceAll("\\n", "").trim().replaceAll(";$", "");
try {
// 无异常时需要执行sql
if (!isException) {
int count = 0;
if (sql.startsWith("insert")) {
count = sqlMapper.insert(sql);
} else if (sql.startsWith("update")) {
count = sqlMapper.update(sql);
} else if (sql.startsWith("delete")) {
count = sqlMapper.delete(sql);
} else {
result.add(TextUtils.joinString("[ ", sql, " ]", " 语句异常"));
isException = true;
}
result.add(TextUtils.joinString("[ ", sql, " ]", " 语句影响数据行数:", String.valueOf(count)));
maintainLogs.add(getMaintainLog(user, count, sql));
} else {
// 提醒此sql没有被执行
result.add(TextUtils.joinString("[ ", sql, " ]", " 语句不执行"));
}
} catch (Exception ex) {
logger.error("bulkUpdateBySql", ex);
// 执行时异常了需要返回
result.add(TextUtils.joinString("[ ", sql, " ]", " 执行异常:", ex.getMessage()));
isException = true;
resultException = ex;
}
}
// 如果有异常需要回滚所有数据
if (isException) {
result.add("因为存在异常,此次执行sql将被回滚");
throw new DataException(result, resultException);
}
if (CollectionUtils.isNotEmpty(maintainLogs)) {
dataMaintainHandler.saveMaintainLogs(maintainLogs);
}
return result;
}
}
3.注入SQLMapper
<bean id="sqlMapper" class="com.cpic.acpe.common.persistence.SqlMapper" scope="prototype">
<constructor-arg ref="sqlSession"/>
</bean>