首页 > 数据库 >Mybatis数据库驱动

Mybatis数据库驱动

时间:2023-03-15 11:56:29浏览次数:35  
标签:DriverManager Driver 数据库 driver ibatis apache org Mybatis 驱动

Mybatis数据库驱动

最近在学习mybatis的源码,有一个databaseIdProvider根据不同数据库执行不同sql的功能,我正好有一个mysql还有一个瀚高数据库,就去试了一下,使用如下

pom文件导入两个数据库的驱动

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.13</version>
</dependency>

<dependency>
    <groupId>com.highgo</groupId>
    <artifactId>HgdbJdbc</artifactId>
    <version>6.2.2</version>
</dependency>

主启动类.java

public class MybatisHelloWorld {
    public static void main(String[] args) throws Exception {
        String resource = "org/mybatis/config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> users = mapper.getUsers(1);
        session.close();
    }
}

User.java


public class User {
    private Integer id;
    private String name;
    private Integer age;
    //....getter setter 构造..
}

UserMapper.java

public interface UserMapper {
    List<User> getUsers(int age);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.mapper.UserMapper" >

    <select id="getUsers" resultType="org.mybatis.pojo.User" databaseId="mysql">
        select * from user where age = #{age}
    </select>

    <select id="getUsers" resultType="org.mybatis.pojo.User" databaseId="postgresql">
        select * from mybatis.user where age = #{age}
    </select>

</mapper>

Mybatis配置文件

<configuration>
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>

        <environment id="highgo">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:highgo://localhost:5866/highgo?currentSchema=mybatis"/>
                <property name="username" value="highgo"/>
                <property name="password" value="Hello@123"/>
            </dataSource>
        </environment>
    </environments>


    <databaseIdProvider type="DB_VENDOR">
        <property name="MySQL" value="mysql"/>
        <property name="PostgreSQL" value="postgresql"/>
    </databaseIdProvider>


    <mappers>
        <package name="org.mybatis.mapper"/>
    </mappers>

</configuration>

当我把mybatis配置文件中的环境设置为<environments default="mysql">,代码执行结果如下

然后我修改环境设置为<environments default="highgo">后,代码执行结果如下

不知道您有没有看出问题所在,在上面的mybatis配置文件中highgo环境的驱动是com.mysql.cj.jdbc.Driver 但是能连接上瀚高的数据库并且能正常执行sql

当时我也发现这个问题了,于是想研究下原因

首先要找到是哪一段代码进行的操作,那么这里肯定是创建连接的时候,因为驱动不对的话是连接不上的,于是跟着这个思路就去寻找

最后找到方法栈如下

  • doGetConnection:200, UnpooledDataSource (org.apache.ibatis.datasource.unpooled)
  • doGetConnection:196, UnpooledDataSource (org.apache.ibatis.datasource.unpooled)
  • getConnection:93, UnpooledDataSource (org.apache.ibatis.datasource.unpooled)
  • popConnection:407, PooledDataSource (org.apache.ibatis.datasource.pooled)
  • getConnection:89, PooledDataSource (org.apache.ibatis.datasource.pooled)
  • getDatabaseProductName:82, VendorDatabaseIdProvider (org.apache.ibatis.mapping)
  • getDatabaseName:66, VendorDatabaseIdProvider (org.apache.ibatis.mapping)
  • getDatabaseId:53, VendorDatabaseIdProvider (org.apache.ibatis.mapping)
  • databaseIdProviderElement:305, XMLConfigBuilder (org.apache.ibatis.builder.xml)
  • parseConfiguration:123, XMLConfigBuilder (org.apache.ibatis.builder.xml)
  • parse:97, XMLConfigBuilder (org.apache.ibatis.builder.xml)
  • build:82, SqlSessionFactoryBuilder (org.apache.ibatis.session)
  • build:67, SqlSessionFactoryBuilder (org.apache.ibatis.session)
  • main:32, MybatisHelloWorld (org.mybatis)

UnpooledDataSource.java

private Connection doGetConnection(Properties properties) throws SQLException {
    initializeDriver();
    Connection connection = DriverManager.getConnection(url, properties);
    configureConnection(connection);
    return connection;
}
private synchronized void initializeDriver() throws SQLException {
    //判断这个驱动是否注册过
    if (!registeredDrivers.containsKey(driver)) {
        Class<?> driverType;
        try {
            if (driverClassLoader != null) {
                driverType = Class.forName(driver, true, driverClassLoader);
            } else {
                driverType = Resources.classForName(driver);
            }
            Driver driverInstance = (Driver)driverType.newInstance();
            DriverManager.registerDriver(new DriverProxy(driverInstance));
            registeredDrivers.put(driver, driverInstance);
        } catch (Exception e) {
            throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);
        }
    }
}

先判断需要加载的驱动是否已经注册了

那这里面的两个驱动是从哪里来的呢?

就在这个UnpooledDataSource类中的静态块里面

static {
    Enumeration<Driver> drivers = DriverManager.getDrivers();
    while (drivers.hasMoreElements()) {
        Driver driver = drivers.nextElement();
        registeredDrivers.put(driver.getClass().getName(), driver);
    }
}

而DriverManager中有一个集合用来存储所有已经注册的数据库连接驱动

public class DriverManager {

    // List of registered JDBC drivers
    private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
	//....
    public static java.util.Enumeration<Driver> getDrivers() {
        java.util.Vector<Driver> result = new java.util.Vector<>();

        Class<?> callerClass = Reflection.getCallerClass();

        // Walk through the loaded registeredDrivers.
        for(DriverInfo aDriver : registeredDrivers) {
            // If the caller does not have permission to load the driver then
            // skip it.
            if(isDriverAllowed(aDriver.driver, callerClass)) {
                result.addElement(aDriver.driver);
            } else {
                println("    skipping: " + aDriver.getClass().getName());
            }
        }
        return (result.elements());
    }
    //......
}

那么问题又来了,DriverManager里面的瀚高数据库驱动啥时候放进去的呢

在学java基础的jdbc时,肯定都写过类似这样的代码

public static void main(String[] args) throws Exception {
    Class.forName("com.mysql.cj.jdbc.Driver");
    Connection con= DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx","root","XXXXXX");
    Statement stat=con.createStatement();
	//......
}

当时这段Class.forName("com.mysql.cj.jdbc.Driver");就告诉你是加载驱动,有的博客写了这段代码,有的没写,具体操作一直都不清楚

首先JDK5版本以后可以不用显式调用这段话,DriverManager会自己去合适的驱动,前提是这个驱动存在于CLASSPATH下

其次,它是怎么加载的呢?为啥Class.forName就能加载呢?

当一个类被加载到JVM时会执行静态代码块,我们以mysql的驱动举例子

package com.mysql.cj.jdbc;

import java.sql.DriverManager;
import java.sql.SQLException;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }

    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}

所以最终调用的还是DriverManager.registerDriver(new Driver());注册一个驱动,底层就是放入到registeredDrivers这个集合中

以瀚高的数据库驱动来看,当调用DriverManager.getDrivers

最终还是使用DriverManager.registerDriver注册了瀚高的数库驱动

那么回到UnpooledDataSource类中

public class UnpooledDataSource implements DataSource {
    private static Map<String, Driver> registeredDrivers = new ConcurrentHashMap<String, Driver>();
    //.....
    static {
        //这里就会获取到mysql和瀚高的驱动
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            registeredDrivers.put(driver.getClass().getName(), driver);
        }
    }
    //.....
	
    private Connection doGetConnection(Properties properties) throws SQLException {
        initializeDriver();
        Connection connection = DriverManager.getConnection(url, properties);
        configureConnection(connection);
        return connection;
    }
}

initializeDriver()加载一些其他的驱动,例如我们自定义一个类,实现Driver接口,然后在<property name="driver" value="com.drive.MyDrive"/>使用

那么Connection connection = DriverManager.getConnection(url, properties);不就是基础的JDBC连接数据库的操作吗

也解答了我自己以前的疑惑或者错误的理解

  1. 一直不清楚Class.forName("")的作用
  2. 以为mybatis配置文件中的<property name="driver" value="com.mysql.cj.jdbc.Driver"/> 写给那个环境,那个环境就使用这个驱动

现在是明白了

标签:DriverManager,Driver,数据库,driver,ibatis,apache,org,Mybatis,驱动
From: https://www.cnblogs.com/sunankang/p/17217982.html

相关文章

  • LMG3522R030RQSR 650V 30mΩ GaN FET、TPS92667QPHPRQ1 LED矩阵驱动器、UCC21755QDWRQ
    1、LMG3522R030RQSR650V30mΩGaNFET具有集成式驱动器和保护功能,适用于开关模式电源转换器。LMG3522R030集成了一个硅驱动器,可实现高达150V/ns的开关速度。与分立式硅栅......
  • Mac 开发 | IDEA 设置 Mybatis 的XML SQL 语句提示
    1、IDEA链接数据库2、IDEA设置数据库方言为链接的数据库方言3、IDEASQL解析范围设置4、可以在mapperxml中写select测试了。......
  • JavaWeb-QQZone项目的业务需求、数据库设计等内容
    资料来源于:B站尚硅谷JavaWeb教程(全新技术栈,全程实战),本人才疏学浅,记录笔记以供日后回顾由于是多个视频内容混合在一起,因此只放了第一个链接本文参考价值不高,自我记录......
  • 触摸驱动实验
    学习地址触摸校准实验......
  • Java Mybatis 笔记
    MyBatis1、简介1.1什么是MybatisMyBatis是一款优秀的持久层框架;它支持自定义SQL、存储过程以及高级映射。MyBatis免除了几乎所有的JDBC代码以及设置参数和获......
  • 创建数据库表
          数据表的类型       ......
  • MybatisX无法自动生成entity实体类
    在做项目的时候,安装MybatisX插件可以让我们不用写实体类,加快我们的开发速度,让我们更专注于业务逻辑的开发,可是最近在做项目的时候,发现MybatisX插件的MybatisX-Generator无......
  • Mysql数据库未添加索引引发的生产事故
    最近开发的新功能主要是首页的红点提示功能,某个用户登录系统app,然后进入某一个功能模块,在该功能下面有很多地方可以操作,新功能就是根据用户信息查询当月是否存在新的......
  • 12、MySQL数据库配置
    MySQL系统数据库MySQL系统数据库主要包括以下几个:mysql数据库:用于存储MySQL的权限信息和系统变量等,包括user表、db表、host表等,这些表是管理MySQL权限的重要基础......
  • 如何将自定义的日志直接写入到 mysql 数据库中?
    要将自定义的日志直接写入MySQL数据库中,您可以使用以下步骤:安装MySQL数据库,并创建一个新的数据库和表来存储日志数据。在您的代码中,使用MySQL连接器来连接到MySQL数据库。创......