jfinal中如何判断数据连接是否已经存在?

我们这有个多租户系统,每个租户的数据库连接信息存放在数据库中。

当某租户首次登录系统时,会将租户的数据连接启动起来,使用租户唯一编号作为连接的configName。

后续访问就先检查数据连接是否存在,存在就不重复启动数据连接。

但现在问题是:检查连接是否存在时,DbKit.getConfig(dbid)返回的是空,导致重复去启动数据连接从而导致报错说连接已经存在。

所以jfinal中要如何判断数据连接是否已经存在?


    public static RetKit getDblink(String dbid) {
        if (StrKit.notNull(DbKit.getConfig(dbid))) { 
            return RetKit.ok("已成功连接数据库。");
        }
        return RetKit.fail("无数据库连接存在。");
    }


补充数据连接代码:

    /**
     * 获取数据库连接
     *
     * @param Kv
     * @return Ret msg
     */
    public static RetKit getDblink(Record rec) {
        if (!StrKit.notNull(rec)) {
            return RetKit.fail("数据库连接参数空。");
        }

        String dbid = rec.getStr(DBID); // 数据库连接ID
        // 判断数据库连接是否已经存在连接
        RetKit hasDblink = getDblink(dbid);
        if (hasDblink.isOk()) {
            return hasDblink;
        }

        String dbtype = rec.getStr(DBTYPE); // 数据库类型
        String dbhost = rec.getStr(DBHOST); // 数据库主机ip地址
        String dbport = rec.getStr(DBPORT); // 数据库端口
        String dbname = rec.getStr(DBNAME); // 数据库名称
        String dbdriver = rec.getStr(DBDRIVER); // 数据库驱动器
        String dburl = rec.getStr(DBURL);       // 数据库连接地址
        String dbusername = rec.getStr(DBUSERNAME); // 数据库用户名
        String dbpassword = rec.getStr(DBPASSWORD); // 数据库密码

        int dbmaxactive = StrKit.isBlank(rec.getStr(DBMAXACTIVE)) ? 100 : rec.getInt(DBMAXACTIVE); // 数据库最大活跃连接数
        int iscase = StrKit.isBlank(rec.getStr(ISCASE)) ? -1 : rec.getInt(ISCASE); //字段大小写,0 是大写, 1是小写, -1不写是区分大小写

        try {
            // 配置DruidPlugin数据库连接池
            DruidPlugin dp = new DruidPlugin(dburl, dbusername, dbpassword, dbdriver);
            dp.set(1, 5, dbmaxactive); // 设置初始连接池大小、最小空闲连接数、最大活跃连接数

            // 配置ActiveRecord数据库连接池插件
            ActiveRecordPlugin arp = new ActiveRecordPlugin(dbid, dp);

            // 设置数据库方言等信息
            switch (dbtype) {
                case "mysql":
                    arp.setDialect(new MysqlDialect()); // 设置数据库方言

                    WallFilter wallFilter = new WallFilter(); // 加强数据库安全
                    wallFilter.setDbType("mysql");
                    dp.addFilter(wallFilter);
                    break;
                case "sqlserver":
                    arp.setDialect(new SqlServerDialect()); // 设置数据库方言
                    break;
                case "oracle":
                    arp.setDialect(new OracleDialect()); // 设置数据库方言
                    iscase = 1; //oracle 配置属性名(字段名)大小写不敏感容器工厂。都转成小写
                    dp.setMaxPoolPreparedStatementPerConnectionSize(100); //在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
                    break;
            }

            if (dp.start() && arp.start()) {
                return RetKit.ok("连接数据库成功。");
            } else {
                throw new SQLException("数据库连接池或管理器启动失败。"); // 抛出异常,不影响程序往下执
            }

        } catch (Exception e) {
            e.printStackTrace();
            return RetKit.fail("连接数据库异常。");
        }

    }



评论区

JFinal

2024-04-25 13:21

你上面的代码应该已经对了,可以考虑在一个全局拦截器中判断,没启动时在拦截器中启动它

杜福忠

2024-04-26 09:44

启动数据库链接的整体代码 需要加锁,如果租户少,可以给启动代码整体 套个 synchronized(configName.intern()){ 就可以了,注意需要在锁外检查一下,和锁内再检查一次是否启动了数据库链接,再去启动数据库链接

liugz

2024-04-27 09:47

@杜福忠 感想杜兄的解答,我没太能理解你的意思。 上面我补充了下启动数据连接的公共方法,麻烦帮忙看下,是不是启动数据连接的姿势不对?

杜福忠

2024-04-27 10:33

@liugz
String dbtype = rec.getStr(DBTYPE); // 数据库类型
这行之前加 代码:
//锁
synchronized(dbid.intern()){
// 再次判断数据库连接是否已经存在连接
RetKit hasDblink = getDblink(dbid);
if (hasDblink.isOk()) {
return hasDblink;
}
后续代码...
}

热门反馈

扫码入社