zoukankan      html  css  js  c++  java
  • 注册mySQL到JDBC驱动程序方法浅谈

    一、注册方法(4种)

    1)服务提供者框架:

    符合JDBC 4.0规范的驱动程序包含了一个文件META-INF/services/java.sql.Driver,在这个文件中提供了JDBC驱动实现的类名。

    例如:mysql-connector-java-5.1.40-bin.jar文件中就可以找到java.sql.Driver文件,用文本编辑器打开文件就可以看到:com.mysql.jdbc.Driver类。

    JVM的服务提供者框架在启动应用时就会注册服务,例如:mySQL的JDBC驱动就会被注册,而原代码中的Class.forName("com.mysql.jdbc.Driver")仍然可以存在,但是不会起作用。

     

    2)Class.forName("com.mysql.jdbc.Driver");

    通过对类com.mysql.jdbc.Driver初始化,执行静态初始化代码,调用DriverManager注册JDBC驱动。

    注:通过setProperty的测试,确认类com.mysql.jdbc.Driver也没有加载,那么静态初始化代码肯定被执行了,但是如果服务提供者框架已经注册的服务,这里注册会失败,编程的预期是这样的,可是理论上DriverManager.registerDriver可以重复注册的,为什么这里不能重复注册呢?

    3)System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver";);

    设置JVM的系统属性,当JVM第一次加载DriverManager类时,会执行类的静态初始化代码,代码中调用loadInitialDrivers()方法,就会加载设置的属性对应的类,执行类的静态初始化代码完成注册。

    注:因为注册的机制无法深入理解,只知道没有加载过的类可以注册成功,加载过的就不能重复注册了。

    注:setProperty必须在DriverManager第一次运行前才有效,说明”服务提供者”框架注册服务时并没有加载类,因为一旦加载类就会执行类的静态初始化代码,那么注册JDBC驱动就一定会调用DriverManager类的静态初始化代码,那么setProperty就会失效,所以说明注册服务是不加载类的。

    4)DriverManager.registerDriver(new com.mysql.jdbc.Driver());

    其实前面的2)和3)最终都是通过这个方法注册的,但是这个方法就可以重复注册。

    注:对于重复注册后,建立链接时使用哪个驱动我就不明白了,可以取消注册,取消的关键字是基于创建的对象的,所以就算重名也不会出错。

    注:这种注册方式没有前面几种好,因为这种注册方式会在代码中与需要注册的驱动程序的类绑定,前面都可以通过配置参数实现注册。

    二、各自特点:

    1)全自动。只要提供符合规范的JAR文件就可以了。

    2)利用反射机制,将驱动类注入到代码中,不需要与代码绑定。

    3)基于系统的属性设置方法,将驱动类注入到代码中,但是好像只能绑定一个JDBC驱动。

    4)最终的注册机制。会出现重复注册,但是好像对程序没影响,还需要与代码绑定,驱动变了,必须修改代码,维护成本过高,当然也是灵活性最好,管理最方便的。

    以下是测试代码:

    import java.sql.Connection;
    import java.sql.Driver;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.Enumeration;
    
    /**
     * @author 朱远翔.Tom 测试JDBC驱动注册
     */
    public class JDBCDriverTest {
    
        public static void main(String[] args) {
            Driver aDriver;
            Connection connection;
            Enumeration em;
            // “org.gjt.mm.mysql.Driver”是“com.mysql.jdbc.Driver”的子类,其构造函数就是调用父类的构造函数。
            String driverString = "com.mysql.jdbc.Driver";
            // String driverString = "org.gjt.mm.mysql.Driver";
            String url = "jdbc:mysql://localhost/ElectricalStore?useSSL=false";
            String username = "admin";
            String password = "123456";
    
            try {
               // 将DriverManager的日志流输出到Console窗口中,方便监控
               // DriverManager.setLogStream(System.out);
               // DriverManager.println("------DriverManager logs start!------");
    
               // 只是设置了一个JVM的系统属性,并不建立JDBC驱动程序。
                // 建立JDBC驱动是依赖系统第一次调用DriverManager类时,执行了这个类的静态初始化代码中的loadInitialDrivers(),
                // 加载驱动的方法会把设置的jdbc.drivers属性对应的驱动类通过DriverManager.registerDriver注册到JDBC中。
                // 因此,必须放在DriverManager被第一次调用之间,也就是需要将前面那两行代码注释掉
                System.out.println("1.1> Tried to use setProperty.");
                System.setProperty("jdbc.drivers", driverString);
                System.out.println("---List of all jdbc drivers---");
                em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
                if (!em.hasMoreElements()) {
                    System.out.println("There is no JDBC drivers");
                } else {
                    while (em.hasMoreElements()) {
                        aDriver = (Driver) em.nextElement();
                        System.out.println(aDriver);
                    }
                }
    
                System.out.println("1.2> we tried to use Class.forName");
                // Class.forName(driverString)在JavaSE 6.0后符合JDBC 4.0规范的驱动可以不用
                // 基于服务提供机制( Service Provider mechanism),
                // 系统会自动搜索mysql-connector-java-???-bin.jar中的META-INF/services/java.sql.Driver
                // 这个文件会包含mysql jdbc驱动程序的入口:com.mysql.jdbc.Driver
                // 应用程序调用Class.forName()也不会出错,只是什么都不会执行。
                // 因为Class.forName()就是执行静态初始化代码,已经初始化过的类就无法激活这段代码了
                // System.setProperty("jdbc.drivers",driverString);与Class.forName()一样。
                try {
                    Class.forName("com.mysql.fabric.jdbc.FabricMySQLDriver");
                } catch (ClassNotFoundException e) {
                    System.out.println("Driver not found");
                }
    
                System.out.println("---List of all jdbc drivers---");
                em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
                if (!em.hasMoreElements()) {
                    System.out.println("There is no JDBC drivers");
                } else {
                    while (em.hasMoreElements()) {
                        aDriver = (Driver) em.nextElement();
                        System.out.println(aDriver);
                    }
                }
    
                System.out.println("1.3> we tried to use DriverManager.registerDriver");
                // 手工注册mySQL的JDBC驱动程序,也就出现了与mySQL绑定过紧的问题,如果以后需要更换驱动,就需要修改代码。
                // 系统容许出现重复注册同样的jdbc驱动类
                DriverManager.registerDriver(new com.mysql.jdbc.Driver());
                DriverManager.registerDriver(new com.mysql.fabric.jdbc.FabricMySQLDriver());
                DriverManager.registerDriver(new com.mysql.jdbc.Driver());
    
                System.out.println("---List of all jdbc drivers---");
                em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
                while (em.hasMoreElements()) {
                    aDriver = (Driver) em.nextElement();
                    System.out.println(aDriver);
                }
    
                System.out.println("<1.5> Deregister all JDBC drivers");
                em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
                while (em.hasMoreElements()) {
                    aDriver = (Driver) em.nextElement();
                    DriverManager.deregisterDriver(aDriver); // 将已经注册的驱动程序取消注册
                }
    
                em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
                if (!em.hasMoreElements()) {
                    System.out.println("2.1> Now, there is no JDBC driver");
                }
    
                System.out.println("2.2> we tried to use Class.forName again");
                try {
                    Class.forName(driverString);
                } catch (ClassNotFoundException e) {
                    System.out.println("Driver not found");
                }
                try {
                    Class.forName("com.mysql.fabric.jdbc.FabricMySQLDriver");
                } catch (ClassNotFoundException e) {
                    System.out.println("Driver not found");
                }
                try {
                    Class.forName(driverString);
                } catch (ClassNotFoundException e) {
                    System.out.println("Driver not found");
                }
    
                em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
                if (!em.hasMoreElements()) {
                    System.out.println("There is no JDBC drivers");
                } else {
                    System.out.println("---List of all jdbc drivers---");
                    while (em.hasMoreElements()) {
                        aDriver = (Driver) em.nextElement();
                        System.out.println(aDriver);
                    }
                }
    
                System.out.println("2.3> we tried to use setProperty again");
                System.setProperty("jdbc.drivers", "com.mysql.fabric.jdbc.FabricMySQLDriver");
    
                em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
                if (!em.hasMoreElements()) {
                    System.out.println("There is no JDBC drivers");
                } else {
                    System.out.println("---List of all jdbc drivers---");
                    while (em.hasMoreElements()) {
                        aDriver = (Driver) em.nextElement();
                        System.out.println(aDriver);
                    }
                }
    
                System.out.println("2.3> Tried to use DriverManager.registerDriver again");
    
                DriverManager.registerDriver(new com.mysql.jdbc.Driver());
                DriverManager.registerDriver(new com.mysql.fabric.jdbc.FabricMySQLDriver());
                DriverManager.registerDriver(new com.mysql.jdbc.Driver());
    
                System.out.println("---List of all jdbc drivers---");
                em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
                if (!em.hasMoreElements()) {
                    System.out.println("There is no JDBC drivers");
                } else {
                    while (em.hasMoreElements()) {
                        aDriver = (Driver) em.nextElement();
                        System.out.println(aDriver);
                    }
                }
    
                System.out.print("3.1> Tried to establish a connection: ");
                connection = DriverManager.getConnection(url, username, password);
                System.out.println(connection);
            } catch (SQLException e) {
                System.out.println("Cannot registered the mysql jdbc driver");
            }
    
            System.out
                    .println("jdbc.drivers property: " + System.getProperty("jdbc.drivers", "nothing"));
    
        }
    
    }

  • 相关阅读:
    Pytorch:常用工具模块
    Pytorch: torch.nn
    流行框架阶段·概览
    jquery/js实现一个网页同时调用多个倒计时(最新的)
    用js判断页面刷新或关闭的方法
    js中substr,substring,indexOf,lastIndexOf,split 的用法
    jsonp案例
    CSS布局奇技淫巧:各种居中
    IntelliJ Idea 常用快捷键列表
    jquery中attr和prop的区别
  • 原文地址:https://www.cnblogs.com/zhuyx/p/10401906.html
Copyright © 2011-2022 走看看