Skip to content

Commit

Permalink
QueryPlanCache增加租户支持
Browse files Browse the repository at this point in the history
  • Loading branch information
entropy-cloud committed Aug 19, 2024
1 parent e043cc4 commit a9950c7
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 11 deletions.
2 changes: 2 additions & 0 deletions nop-orm-eql/src/main/java/io/nop/orm/eql/ICompiledSql.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
public interface ICompiledSql {
String getName();

boolean isUseTenantModel();

/**
* 一条SQL语句只能是在一个数据源中执行。目前不支持一条SQL语句访问多个数据源。
*/
Expand Down
10 changes: 10 additions & 0 deletions nop-orm-eql/src/main/java/io/nop/orm/eql/compile/CompiledSql.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class CompiledSql implements ICompiledSql {
private SQL sql;
private List<String> readEntityModels = Collections.emptyList();
private String writeEntityModel;
private boolean useTenantModel;

@Override
public List<String> getReadEntityNames() {
Expand Down Expand Up @@ -120,6 +121,15 @@ public void setParamBuilders(List<ISqlParamBuilder> paramBuilders) {
this.paramBuilders = paramBuilders;
}

@Override
public boolean isUseTenantModel() {
return useTenantModel;
}

public void setUseTenantModel(boolean useTenantModel) {
this.useTenantModel = useTenantModel;
}

@Override
public List<Object> buildParams(List<Object> input) {
List<Object> ret = new ArrayList<>(sql.getMarkers().size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public ICompiledSql compile(String name, String eql, ISqlCompileContext context)
compiledSql.setParamBuilders(transformer.getParams());
compiledSql.setReadEntityModels(transformer.getReadEntityModels());
compiledSql.setWriteEntityModel(transformer.getWriteEntityModel());
compiledSql.setUseTenantModel(transformer.isUseTenantModel());

if (stm.getStatementKind() == SqlStatementKind.SELECT) {
SqlSelect select = stm instanceof SqlSelectWithCte ? ((SqlSelectWithCte) stm).getSelect() : (SqlSelect) stm;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ public class EqlTransformVisitor extends EqlASTVisitor {

private final Set<String> readEntityModels = new LinkedHashSet<>();
private String writeEntityModel;
private boolean useTenantModel;

/**
* 判断是否正在处理order by子句。如果仅在order by语句中通过a.b.c这种属性表达式引用关联表上的字段,且关联字段允许为空, 则使用left join来实现隐式关联。
Expand All @@ -173,6 +174,10 @@ public IDialect getDialect() {
return dialect;
}

public boolean isUseTenantModel() {
return useTenantModel;
}

public void transform(SqlProgram program) {
collectNames(program);
visitSqlProgram(program);
Expand Down Expand Up @@ -621,6 +626,9 @@ void visitJoinRight(SqlTableScope tableScope, SqlJoinTableSource source) {
void addResolvedEntity(SourceLocation loc, ISqlTableMeta tableMeta) {
readEntityModels.add(tableMeta.getEntityName());

if (tableMeta.getEntityModel().isTenantModel())
this.useTenantModel = true;

String querySpace = tableMeta.getQuerySpace();
querySpaceToEntityNames.put(querySpace, tableMeta.getEntityName());
if (querySpaceToEntityNames.size() > 1)
Expand Down Expand Up @@ -881,6 +889,8 @@ SqlExpr makeEqExpr(SqlTableSource source, IColumnModel keyCol, String keyValue)

SqlSingleTableSource makeTableSource(SourceLocation loc, IEntityModel entityModel, SqlAlias alias) {
readEntityModels.add(entityModel.getName());
if (entityModel.isTenantModel())
this.useTenantModel = entityModel.isTenantModel();

SqlSingleTableSource table = new SqlSingleTableSource();
table.setLocation(loc);
Expand Down Expand Up @@ -1320,6 +1330,8 @@ public void visitSqlInsert(SqlInsert node) {
node.setResolvedTableSource(source);

writeEntityModel = tableMeta.getEntityName();
if (tableMeta.getEntityModel().isTenantModel())
this.useTenantModel = tableMeta.getEntityModel().isTenantModel();

visitChildren(node.getColumns());

Expand Down Expand Up @@ -1361,6 +1373,8 @@ public void visitSqlUpdate(SqlUpdate node) {
node.setResolvedTableSource(source);

writeEntityModel = tableMeta.getEntityName();
if (tableMeta.getEntityModel().isTenantModel())
this.useTenantModel = tableMeta.getEntityModel().isTenantModel();

this.visitChildren(node.getAssignments());
this.visitChild(node.getWhere());
Expand Down Expand Up @@ -1404,6 +1418,8 @@ public void visitSqlDelete(SqlDelete node) {

ISqlTableMeta tableMeta = resolveEntity(table);
writeEntityModel = tableMeta.getEntityName();
if (tableMeta.getEntityModel().isTenantModel())
this.useTenantModel = tableMeta.getEntityModel().isTenantModel();

SqlSingleTableSource source = newSingleTableSource(table, node.getAlias());
node.setResolvedTableSource(source);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ public interface IEntityModel extends IPdmElement, IOrmDataType {

boolean isTableView();

/**
* 一般的租户设计是所有租户共享同一个表结构,通过tenantId来区分,但是对于NopDynEntityMeta配置的动态结构,不同的租户可能会定义同名的实体结构
*
* @return 是否是某个租户定义的实体
*/
boolean isTenantModel();

default String getSimpleClassName() {
return StringHelper.simpleClassName(getClassName());
}
Expand Down
11 changes: 11 additions & 0 deletions nop-orm-model/src/main/java/io/nop/orm/model/OrmEntityModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public class OrmEntityModel extends _OrmEntityModel implements IEntityModel, INe

private Map<String, IEntityPropModel> propsByUnderscoreName;

private boolean tenantModel;

private boolean inited;

public OrmEntityModel() {
Expand All @@ -83,6 +85,15 @@ public String toString() {
+ getTableName() + "]@" + getLocation();
}

@Override
public boolean isTenantModel() {
return tenantModel;
}

public void setTenantModel(boolean tenantModel) {
this.tenantModel = tenantModel;
}

/**
* 所有的列都是主键。一般对应于多对多中间表
*/
Expand Down
2 changes: 1 addition & 1 deletion nop-orm/src/main/java/io/nop/orm/IOrmSessionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public interface IOrmSessionFactory extends AutoCloseable, IDialectProvider, ISq

IOrmSession openSession(boolean stateless);

ICache<QueryPlanCacheKey, ICompiledSql> getQueryPlanCache();
ICache<QueryPlanCacheKey, IOrmCachedQueryPlan> getQueryPlanCache();

ICacheProvider getGlobalCache();

Expand Down
27 changes: 20 additions & 7 deletions nop-orm/src/main/java/io/nop/orm/factory/SessionFactoryImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import io.nop.dao.shard.IShardSelector;
import io.nop.dao.txn.ITransactionTemplate;
import io.nop.dao.utils.DaoHelper;
import io.nop.orm.IOrmCachedQueryPlan;
import io.nop.orm.IOrmComponent;
import io.nop.orm.IOrmDaoListener;
import io.nop.orm.IOrmEntity;
Expand Down Expand Up @@ -90,7 +91,7 @@ public class SessionFactoryImpl implements IPersistEnv {

private ICacheProvider globalCache;

private ICache<QueryPlanCacheKey, ICompiledSql> queryPlanCache;
private ICache<QueryPlanCacheKey, IOrmCachedQueryPlan> queryPlanCache;

private IQueryExecutor defaultQueryExecutor;

Expand Down Expand Up @@ -174,11 +175,11 @@ public void setDefaultDynamicEntityClass(Class<?> defaultDynamicEntityClass) {
}

@Override
public ICache<QueryPlanCacheKey, ICompiledSql> getQueryPlanCache() {
public ICache<QueryPlanCacheKey, IOrmCachedQueryPlan> getQueryPlanCache() {
return queryPlanCache;
}

public void setQueryPlanCache(ICache<QueryPlanCacheKey, ICompiledSql> queryPlanCache) {
public void setQueryPlanCache(ICache<QueryPlanCacheKey, IOrmCachedQueryPlan> queryPlanCache) {
this.queryPlanCache = queryPlanCache;
}

Expand Down Expand Up @@ -408,14 +409,26 @@ public ICompiledSql compileSql(String name, String sqlText, boolean disableLogic

if (useCache) {
QueryPlanCacheKey key = new QueryPlanCacheKey(name, sqlText, disableLogicalDelete, allowUnderscoreName);
ICompiledSql result = getQueryPlanCache().get(key);
if (result == null) {
IOrmCachedQueryPlan result = getQueryPlanCache().get(key);
if (result == null || result.getCompiledSql() == null) {
ISqlCompileContext ctx = new EqlCompileContext(this, disableLogicalDelete,
astTransformer, allowUnderscoreName, enableFilter);
result = new EqlCompiler().compile(name, sqlText, ctx);
ICompiledSql compiledSql = new EqlCompiler().compile(name, sqlText, ctx);
if (compiledSql.isUseTenantModel()) {
TenantCachedQueryPlan tenantPlan;
if (result instanceof TenantCachedQueryPlan) {
tenantPlan = (TenantCachedQueryPlan) result;
} else {
tenantPlan = new TenantCachedQueryPlan();
result = tenantPlan;
}
tenantPlan.addCompiledSql(compiledSql);
} else {
result = new SimpleCachedQueryPlan(compiledSql);
}
getQueryPlanCache().put(key, result);
}
return result;
return result.getCompiledSql();
} else {
ISqlCompileContext ctx = new EqlCompileContext(this, disableLogicalDelete,
astTransformer, allowUnderscoreName, enableFilter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,14 @@ private String getCacheKey(IOrmEntity entity) {
int tenantPropId = entity.orm_entityModel().getTenantPropId();
if (tenantPropId > 0) {
// 存在一种可能,非租户表引用租户表的集合
tenantId = entity.orm_propValue(tenantPropId);
// 第一次按照主键进行load的时候没有设置tenantId。如果直接读取则导致proxy加载
if (!entity.orm_propInited(tenantPropId)) {
tenantId = ContextProvider.currentTenantId();
} else {
tenantId = entity.orm_propValue(tenantPropId);
if (tenantId == null)
tenantId = ContextProvider.currentTenantId();
}
}

if (tenantId == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -551,9 +551,17 @@ public void onAfterCommit(ITransaction txn) {
private String getCacheKey(IOrmEntity entity) {
if (!useTenantCache)
return entity.orm_idString();
Object tenantId = entity.orm_propValue(entityModel.getTenantPropId());
if (tenantId == null)
int tenantPropId = entityModel.getTenantPropId();

Object tenantId;
// 第一次按照主键进行load的时候没有设置tenantId。如果直接读取则导致proxy加载
if (!entity.orm_propInited(tenantPropId)) {
tenantId = ContextProvider.currentTenantId();
} else {
tenantId = entity.orm_propValue(entityModel.getTenantPropId());
if (tenantId == null)
tenantId = ContextProvider.currentTenantId();
}
return tenantId + ":" + entity.orm_id();
}

Expand Down

0 comments on commit a9950c7

Please sign in to comment.