org.sagacity.sqltoy.dialect.impl.DefaultDialect Maven / Gradle / Ivy
/**
*
*/
package org.sagacity.sqltoy.dialect.impl;
import java.io.Serializable;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.sagacity.sqltoy.SqlExecuteStat;
import org.sagacity.sqltoy.SqlToyContext;
import org.sagacity.sqltoy.callback.DecryptHandler;
import org.sagacity.sqltoy.callback.GenerateSavePKStrategy;
import org.sagacity.sqltoy.callback.GenerateSqlHandler;
import org.sagacity.sqltoy.callback.ReflectPropsHandler;
import org.sagacity.sqltoy.callback.UpdateRowHandler;
import org.sagacity.sqltoy.config.model.EntityMeta;
import org.sagacity.sqltoy.config.model.PKStrategy;
import org.sagacity.sqltoy.config.model.SqlToyConfig;
import org.sagacity.sqltoy.config.model.SqlType;
import org.sagacity.sqltoy.dialect.Dialect;
import org.sagacity.sqltoy.dialect.model.SavePKStrategy;
import org.sagacity.sqltoy.dialect.utils.DefaultDialectUtils;
import org.sagacity.sqltoy.dialect.utils.DialectExtUtils;
import org.sagacity.sqltoy.dialect.utils.DialectUtils;
import org.sagacity.sqltoy.model.ColumnMeta;
import org.sagacity.sqltoy.model.LockMode;
import org.sagacity.sqltoy.model.QueryExecutor;
import org.sagacity.sqltoy.model.QueryResult;
import org.sagacity.sqltoy.model.StoreResult;
import org.sagacity.sqltoy.model.TableMeta;
import org.sagacity.sqltoy.model.inner.QueryExecutorExtend;
import org.sagacity.sqltoy.utils.SqlUtil;
/**
* @project sagacity-sqltoy
* @description 提供一个不能匹配数据库类型的实现,确保通用查询功能可以使用
* @author zhongxuchen
* @version v1.0, Date:2020-9-2
* @modify 2020-9-2,修改说明
*/
@SuppressWarnings({ "rawtypes" })
public class DefaultDialect implements Dialect {
/**
* 判定为null的函数
*/
public static final String NVL_FUNCTION = "ifnull";
@Override
public boolean isUnique(SqlToyContext sqlToyContext, Serializable entity, String[] paramsNamed, Connection conn,
Integer dbType, String tableName) {
return DialectUtils.isUnique(sqlToyContext, entity, paramsNamed, conn, dbType, tableName,
(entityMeta, realParamNamed, table, topSize) -> {
String queryStr = DialectExtUtils.wrapUniqueSql(entityMeta, realParamNamed, dbType, table);
return queryStr + " limit " + topSize;
});
}
/**
* 以mysql 为蓝本实现
*/
@Override
public QueryResult getRandomResult(SqlToyContext sqlToyContext, SqlToyConfig sqlToyConfig,
QueryExecutor queryExecutor, final DecryptHandler decryptHandler, Long totalCount, Long randomCount,
Connection conn, Integer dbType, String dialect, final int fetchSize, final int maxRows) throws Exception {
return DefaultDialectUtils.getRandomResult(sqlToyContext, sqlToyConfig, queryExecutor, decryptHandler,
totalCount, randomCount, conn, dbType, dialect, fetchSize, maxRows);
}
/**
* 以postgres 标准的limit offset 模式
*/
@Override
public QueryResult findPageBySql(SqlToyContext sqlToyContext, SqlToyConfig sqlToyConfig,
QueryExecutor queryExecutor, final DecryptHandler decryptHandler, Long pageNo, Integer pageSize,
Connection conn, Integer dbType, String dialect, final int fetchSize, final int maxRows) throws Exception {
return DefaultDialectUtils.findPageBySql(sqlToyContext, sqlToyConfig, queryExecutor, decryptHandler, pageNo,
pageSize, conn, dbType, dialect, fetchSize, maxRows);
}
/**
* 以mysql为蓝本实现
*/
@Override
public QueryResult findTopBySql(SqlToyContext sqlToyContext, SqlToyConfig sqlToyConfig, QueryExecutor queryExecutor,
final DecryptHandler decryptHandler, Integer topSize, Connection conn, Integer dbType, String dialect,
final int fetchSize, final int maxRows) throws Exception {
return DefaultDialectUtils.findTopBySql(sqlToyContext, sqlToyConfig, queryExecutor, decryptHandler, topSize,
conn, dbType, dialect, fetchSize, maxRows);
}
@Override
public QueryResult findBySql(SqlToyContext sqlToyContext, SqlToyConfig sqlToyConfig, String sql,
Object[] paramsValue, QueryExecutorExtend queryExecutorExtend, final DecryptHandler decryptHandler,
Connection conn, LockMode lockMode, Integer dbType, String dialect, int fetchSize, int maxRows)
throws Exception {
String realSql = sql.concat(getLockSql(sql, dbType, lockMode));
return DialectUtils.findBySql(sqlToyContext, sqlToyConfig, realSql, paramsValue, queryExecutorExtend,
decryptHandler, conn, dbType, 0, fetchSize, maxRows);
}
@Override
public Long getCountBySql(SqlToyContext sqlToyContext, SqlToyConfig sqlToyConfig, String sql, Object[] paramsValue,
boolean isLastSql, Connection conn, Integer dbType, String dialect) throws Exception {
return DialectUtils.getCountBySql(sqlToyContext, sqlToyConfig, sql, paramsValue, isLastSql, conn, dbType);
}
@Override
public Serializable load(SqlToyContext sqlToyContext, Serializable entity, boolean onlySubTables,
List cascadeTypes, LockMode lockMode, Connection conn, Integer dbType, String dialect,
String tableName) throws Exception {
EntityMeta entityMeta = sqlToyContext.getEntityMeta(entity.getClass());
// 获取loadsql(loadsql 可以通过@loadSql进行改变,所以需要sqltoyContext重新获取)
SqlToyConfig sqlToyConfig = sqlToyContext.getSqlToyConfig(entityMeta.getLoadSql(tableName), SqlType.search,
dialect, null);
String loadSql = sqlToyConfig.getSql(dialect);
loadSql = loadSql.concat(getLockSql(loadSql, dbType, lockMode));
return (Serializable) DialectUtils.load(sqlToyContext, sqlToyConfig, loadSql, entityMeta, entity, onlySubTables,
cascadeTypes, conn, dbType);
}
@Override
public List> loadAll(SqlToyContext sqlToyContext, List> entities, boolean onlySubTables,
List cascadeTypes, LockMode lockMode, Connection conn, Integer dbType, String dialect,
String tableName, final int fetchSize, final int maxRows) throws Exception {
return DialectUtils.loadAll(sqlToyContext, entities, onlySubTables, cascadeTypes, lockMode, conn, dbType,
tableName, (sql, dbTypeValue, lockedMode) -> {
return getLockSql(sql, dbTypeValue, lockedMode);
}, fetchSize, maxRows);
}
/**
* 以mysql为蓝本实现
*/
@Override
public Object save(SqlToyContext sqlToyContext, Serializable entity, Connection conn, Integer dbType,
String dialect, String tableName) throws Exception {
EntityMeta entityMeta = sqlToyContext.getEntityMeta(entity.getClass());
// save行为根据主键是否赋值情况调整最终的主键策略
PKStrategy pkStrategy = DialectUtils.getSavePKStrategy(entityMeta, entity, dbType);
boolean isAssignPK = isAssignPKValue(pkStrategy);
String insertSql = DialectExtUtils.generateInsertSql(sqlToyContext.getUnifyFieldsHandler(), dbType, entityMeta,
pkStrategy, NVL_FUNCTION, "NEXTVAL FOR " + entityMeta.getSequence(), isAssignPK, tableName);
return DialectUtils.save(sqlToyContext, entityMeta, pkStrategy, isAssignPK, insertSql, entity,
new GenerateSqlHandler() {
@Override
public String generateSql(EntityMeta entityMeta, String[] forceUpdateField) {
return DialectExtUtils.generateInsertSql(sqlToyContext.getUnifyFieldsHandler(), dbType,
entityMeta, entityMeta.getIdStrategy(), NVL_FUNCTION,
"NEXTVAL FOR " + entityMeta.getSequence(), isAssignPKValue(entityMeta.getIdStrategy()),
null);
}
}, new GenerateSavePKStrategy() {
@Override
public SavePKStrategy generate(EntityMeta entityMeta) {
return new SavePKStrategy(entityMeta.getIdStrategy(),
isAssignPKValue(entityMeta.getIdStrategy()));
}
}, conn, dbType);
}
@Override
public Long saveAll(SqlToyContext sqlToyContext, List> entities, int batchSize,
ReflectPropsHandler reflectPropsHandler, Connection conn, Integer dbType, String dialect,
Boolean autoCommit, String tableName) throws Exception {
EntityMeta entityMeta = sqlToyContext.getEntityMeta(entities.get(0).getClass());
boolean isAssignPK = isAssignPKValue(entityMeta.getIdStrategy());
String insertSql = DialectExtUtils.generateInsertSql(sqlToyContext.getUnifyFieldsHandler(), dbType, entityMeta,
entityMeta.getIdStrategy(), NVL_FUNCTION, "NEXTVAL FOR " + entityMeta.getSequence(), isAssignPK,
tableName);
return DialectUtils.saveAll(sqlToyContext, entityMeta, entityMeta.getIdStrategy(), isAssignPK, insertSql,
entities, batchSize, reflectPropsHandler, conn, dbType, autoCommit);
}
@Override
public Long update(SqlToyContext sqlToyContext, Serializable entity, String[] forceUpdateFields, boolean cascade,
Class[] forceCascadeClasses, HashMap subTableForceUpdateProps, Connection conn,
Integer dbType, String dialect, String tableName) throws Exception {
// 不支持级联
return DialectUtils.update(sqlToyContext, entity, NVL_FUNCTION, forceUpdateFields, false, null,
forceCascadeClasses, subTableForceUpdateProps, conn, dbType, tableName);
}
@Override
public Long updateAll(SqlToyContext sqlToyContext, List> entities, int batchSize, final String[] uniqueFields,
String[] forceUpdateFields, ReflectPropsHandler reflectPropsHandler, Connection conn, Integer dbType,
String dialect, Boolean autoCommit, String tableName) throws Exception {
return DialectUtils.updateAll(sqlToyContext, entities, batchSize, forceUpdateFields, reflectPropsHandler,
NVL_FUNCTION, conn, dbType, autoCommit, tableName, false);
}
@Override
public Serializable updateSaveFetch(SqlToyContext sqlToyContext, Serializable entity,
UpdateRowHandler updateRowHandler, String[] uniqueProps, Connection conn, Integer dbType, String dialect,
String tableName) throws Exception {
return DefaultDialectUtils.updateSaveFetch(sqlToyContext, entity, updateRowHandler, uniqueProps, conn, dbType,
dialect, tableName);
}
@Override
public Long saveOrUpdate(SqlToyContext sqlToyContext, Serializable entity, String[] forceUpdateFields,
Connection conn, Integer dbType, String dialect, Boolean autoCommit, String tableName) throws Exception {
List entities = new ArrayList();
entities.add(entity);
return saveOrUpdateAll(sqlToyContext, entities, sqlToyContext.getBatchSize(), null, forceUpdateFields, conn,
dbType, dialect, autoCommit, tableName);
}
@Override
public Long saveOrUpdateAll(SqlToyContext sqlToyContext, List> entities, int batchSize,
ReflectPropsHandler reflectPropsHandler, String[] forceUpdateFields, Connection conn, Integer dbType,
String dialect, Boolean autoCommit, String tableName) throws Exception {
Long updateCnt = DialectUtils.updateAll(sqlToyContext, entities, batchSize, forceUpdateFields,
reflectPropsHandler, NVL_FUNCTION, conn, dbType, autoCommit, tableName, true);
// 如果修改的记录数量跟总记录数量一致,表示全部是修改
if (updateCnt >= entities.size()) {
SqlExecuteStat.debug("修改记录", "修改记录量:" + updateCnt + " 条,等于entities集合长度,不再做insert操作!");
return updateCnt;
}
Long saveCnt = saveAllIgnoreExist(sqlToyContext, entities, batchSize, reflectPropsHandler, conn, dbType,
dialect, autoCommit, tableName);
SqlExecuteStat.debug("新增记录", "新建记录数量:" + saveCnt + " 条!");
return updateCnt + saveCnt;
}
@Override
public Long saveAllIgnoreExist(SqlToyContext sqlToyContext, List> entities, int batchSize,
ReflectPropsHandler reflectPropsHandler, Connection conn, Integer dbType, String dialect,
Boolean autoCommit, String tableName) throws Exception {
EntityMeta entityMeta = sqlToyContext.getEntityMeta(entities.get(0).getClass());
boolean isAssignPK = isAssignPKValue(entityMeta.getIdStrategy());
String insertSql = DialectExtUtils.generateInsertSql(sqlToyContext.getUnifyFieldsHandler(), dbType, entityMeta,
entityMeta.getIdStrategy(), NVL_FUNCTION, "NEXTVAL FOR " + entityMeta.getSequence(), isAssignPK,
tableName).replaceFirst("(?i)insert ", "insert ignore ");
return DialectUtils.saveAll(sqlToyContext, entityMeta, entityMeta.getIdStrategy(), isAssignPK, insertSql,
entities, batchSize, reflectPropsHandler, conn, dbType, autoCommit);
}
@Override
public Long delete(SqlToyContext sqlToyContext, Serializable entity, Connection conn, Integer dbType,
String dialect, String tableName) throws Exception {
return DialectUtils.delete(sqlToyContext, entity, conn, dbType, tableName);
}
@Override
public Long deleteAll(SqlToyContext sqlToyContext, List> entities, int batchSize, Connection conn, Integer dbType,
String dialect, Boolean autoCommit, String tableName) throws Exception {
return DialectUtils.deleteAll(sqlToyContext, entities, batchSize, conn, dbType, autoCommit, tableName);
}
@Override
public QueryResult updateFetch(SqlToyContext sqlToyContext, SqlToyConfig sqlToyConfig, String sql,
Object[] paramValues, UpdateRowHandler updateRowHandler, Connection conn, Integer dbType, String dialect,
final LockMode lockMode, final int fetchSize, final int maxRows) throws Exception {
String realSql = sql.concat(getLockSql(sql, dbType, (lockMode == null) ? LockMode.UPGRADE : lockMode));
return DialectUtils.updateFetchBySql(sqlToyContext, sqlToyConfig, realSql, paramValues, updateRowHandler, conn,
dbType, 0, fetchSize, maxRows);
}
@Override
public StoreResult executeStore(SqlToyContext sqlToyContext, SqlToyConfig sqlToyConfig, String sql,
Object[] inParamsValue, Integer[] outParamsType, final boolean moreResult, Connection conn, Integer dbType,
String dialect, final int fetchSize) throws Exception {
return DialectUtils.executeStore(sqlToyConfig, sqlToyContext, sql, inParamsValue, outParamsType, moreResult,
conn, dbType, fetchSize);
}
private String getLockSql(String sql, Integer dbType, LockMode lockMode) {
// 判断是否已经包含for update
if (lockMode == null || SqlUtil.hasLock(sql, dbType)) {
return "";
}
if (lockMode == LockMode.UPGRADE_NOWAIT) {
return " for update nowait ";
}
if (lockMode == LockMode.UPGRADE_SKIPLOCK) {
return " for update skip locked";
}
return " for update ";
}
/**
* 指的是在identity、sequence主键场景下,是否允许手工给主键赋值
* @param pkStrategy
* @return
*/
private static boolean isAssignPKValue(PKStrategy pkStrategy) {
if (pkStrategy == null) {
return true;
}
// 目前不支持sequence模式
if (pkStrategy.equals(PKStrategy.SEQUENCE)) {
return true;
}
if (pkStrategy.equals(PKStrategy.IDENTITY)) {
return false;
}
return true;
}
@Override
public List getTableColumns(String catalog, String schema, String tableName, Connection conn,
Integer dbType, String dialect) throws Exception {
return DefaultDialectUtils.getTableColumns(catalog, schema, tableName, conn, dbType, dialect);
}
@Override
public List getTables(String catalog, String schema, String tableName, Connection conn, Integer dbType,
String dialect) throws Exception {
return DefaultDialectUtils.getTables(catalog, schema, tableName, conn, dbType, dialect);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy