mybatis获取当前数据库的连接类型

Java代码中检测并兼容MySQL和Oracle数据库连接类型的实现
本文介绍了如何在Java代码和mapper.xml中检测当前数据库类型,以适应MySQL和Oracle的SQL语法差异,通过MyDatabaseIdProvider类提供数据库连接类型的判断和管理,确保SQL查询的正确执行。

一、任务需求

        在java代码内和mapper.xml内获取当前数据库的连接类型,使得代码和sql语句可以同时兼容mysql和oracle数据库

二、实施

@Configuration
public class MyDatabaseIdProvider implements DatabaseIdProvider{
     /**
     * 参考mp的官方设置,sql的xml内使用_databaseId==oracle 来判断当前连接是什么类型的数据库
     * @param p
     */
    @Override
    public void setProperties(Properties p) {
        p.setProperty("Oracle", "oracle");
        p.setProperty("MySQL", "mysql");
    }

    /**
     * 根据mybatis最原始的配置方式,使用xml的那种,会有一个配置数据库圆的过程
     * 而所有的数据都在dataSource内,所以通过Connection获取getMetaData元数据库
     * 再获取name,也可以参照DatabaseIdProvider接口的默认实现方式
     * @param dataSource
     * @return
     * @throws SQLException
     */
    @Override
    public String getDatabaseId(DataSource dataSource) throws SQLException {
         Connection conn = null;
        String dbName = null;
        String dbAlias = "";
        try {
            conn = dataSource.getConnection();
            dbName = conn.getMetaData().getDatabaseProductName();
            switch (dbName) {
                case "MySQL":
                    dbAlias = "mysql";
                    break;
                case "Oracle":
                    dbAlias = "oracle";
                    break;
                default:
                    break;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
// 2024/5/17修改,线上发现占用数据库连接问题,
//导致其他sql在使用时造成数据库连接超时,这里需要释放Connection 连接
            if (conn != null) {
                conn.close();
            }
        }
        return dbAlias;
    }
     public String getDataBaseName(){
        DataSource dataSource = SpringUtil.getBean(DataSource.class);
        try {
            return this.getDatabaseId(dataSource);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return "";
    }
}

三、使用

  • 第一个重写的方法是用来判断当前数据库的类型,以便于在写SQL时,对于不同的数据库使用不同的语法。例如:
<select id="containsChild" resultType="com.xxx.entiry.user">
        <if test="_databaseId == 'oracle'">
            select *
            from A
            WHERE PERM_ID in
            (SELECT perm_id FROM A START
            WITH perm_id = #{permId}
            CONNECT BY perm_parent = PRIOR perm_id)
        </if>
        <if test="_databaseId == 'mysql'">
            WITH RECURSIVE Aa (
            SELECT * FROM
            A
            WHERE
            perm_id = #{permId}

            UNION ALL

            SELECT p.*
            FROM
            A p
            INNER JOIN
            Aa ON p.perm_parent = cte.perm_id
            )
            SELECT *
            FROM A;
        </if>

    </select>
  • 第二个方法是在代码层面判断当前连接的是什么数据库例如:
      
        String name =  myDatabaseIdProvider.getDataBaseName()
        System.out.println(name); //mysql或者oracle

### MyBatis 数据库连接失败的解决方案 当遇到 `Error querying database` 错误并提示 `No operations allowed after connection closed.` 时,这通常表明数据库连接已经关闭或者未能成功建立。以下是可能的原因及其对应的解决方案: #### 1. **检查数据库服务状态** 如果数据库服务器未启动或不可访问,则可能导致连接失败。确认目标数据库的服务正在运行,并且可以通过网络正常访问[^2]。 #### 2. **验证数据库驱动版本** 确保使用的 MySQL 驱动程序与当前安装的 MySQL 版本兼容。不匹配的驱动可能会引发各种异常行为。可以尝试更新到最新版的 MySQL 连接器/驱动程序[^3]。 ```xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> ``` #### 3. **调整连接池配置** 某些情况下,长时间闲置的连接会被数据库自动断开。这种现象常见于生产环境下的高负载应用中。为了防止这种情况发生,可以在数据源配置文件里启用测试查询功能(test-on-borrow),定期检测连接有效性。 ```properties spring.datasource.testOnBorrow=true spring.datasource.validationQuery=SELECT 1 ``` #### 4. **审查 mybatis-config.xml 文件** 仔细核对 `<environment>` 节点下定义的数据源属性是否正确无误,特别是 URL、用户名和密码部分。任何拼写错误都可能导致认证失败从而拒绝访问[^1]。 ```xml <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> ``` #### 5. **捕获超时设置不足的情况** 对于远程主机上的大型事务处理请求来说,默认的时间限制或许不足以完成整个流程。适当增加 socketTimeout 参数值有助于缓解此类问题。 ```java Properties props = new Properties(); props.setProperty("socketTimeout", "30000"); // 设置为30秒 DataSource dataSource = DataSourceFactory.getDataSource(props); ``` 以上方法能够有效应对大部分因连接丢失所引起的异常状况。然而,在实际开发过程中还需要结合具体场景深入分析根本原因所在。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘个Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值