当前使用版本(必填,否则不予处理)

3.1.2

现象及背景

  1. 我想要一个method, 这个method告诉我数据库中是否存在这条记录, 即返回true/false, 而不是去count(*);
  2. 自定义一个增强型Sql方法 ExistOneMethod 后, 发现这个自定义注入无法使用多租户插件;

该问题是如何引起的?(确定最新版也有问题再提!!!)

抱歉, 目前业务非常繁忙; 我先提出, 后续如有时间我再验证最新版本是否也有问题;

重现步骤(如果有就写完整)

  1. 开启租户插件 TenantHandler
  2. 增加自定义Sql方法 ExistOneMethod, 代码如下
public class ExistOneMethod extends AbstractMethod {

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        /* ALERT here:
              语法解析器 net.sf.jsqlparser.parser, 仍不支持 SELECT {关键字} 语法;
         */
        String existSql = String.format(
                "<script>\nSELECT CASE WHEN EXISTS(SELECT 1 FROM %s %s %s) THEN 1 ELSE 0 END\n</script>",
                tableInfo.getTableName(), sqlWhereEntityWrapper(true, tableInfo),
                sqlComment());
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, existSql, modelClass);
        return this.addSelectMappedStatementForOther(mapperClass, "exist", sqlSource, boolean.class);
    }
}

报错信息

无报错, 但租户插件失效; 自排查后, 与 net.sf.jsqlparser.parser 语法解析实现有关. 它解析到 SELECT EXIST(子查询) 语法后, 把它解析成了 PlainSelect, 导致fromItem=null, 而formItem=null, 则导致了TenantHandler失效问题; 但实际上子查询中是有表的.

Comment From: lite-up

补充: SELECT EXIST( ... )语法直接过不了parser那关; 所以改成了 SELECT CASE WHEN EXIST( ... )

Comment From: miemieYaho

你写个default方法里面 count > 0 不好吗?

Comment From: lite-up

你写个default方法里面 count > 0 不好吗?

可以是可以, 但MySQL的count会全量计数, 而exists则是遇到一个则马上停止, 所以实际上也是个性能问题吧.