【问题标题】:JDBC- Implementation of interfacesJDBC-接口的实现
【发布时间】:2012-04-26 17:08:08
【问题描述】:

在JDBC中,我们主要使用Connection、Statement和ResultSet这三个接口来连接和执行DB中的语句。但是它们对应的对象稍后用于运行 createStatement()、executeQuery()、next() 等方法。哪个类实现了这些方法? 为什么它被称为连接对象而不是实现的类对象?

【问题讨论】:

    标签: java jdbc


    【解决方案1】:

    在 JDBC 中,您首先通过调用注册驱动程序

    Class.forName('classname')
    

    加载数据库类并将该类注册到DriverManager

    当你说DriverManager.getConnection() - 它返回你java.sql.Connection(根据规范的合同)

    哪个类实现了这些方法?

    实际的实现由数据库供应商提供,例如甲骨文、MySQL。

    为什么它被称为连接对象而不是实现类 对象?

    因为你code to Interface and not implementation(良好的编码习惯)。

    如果你愿意,你可以在供应商的 jar 中查找,然后找到哪个类实现了 Connection 而不是

    Connection connection = DriverManager.getConnection()
    

    你可以写

    VendorConnectionImpl vendorConnection = (VendorConnectionImpl)DriverManager.getConnection()
    

    上面的方法会起作用,但它会将您与特定的实现绑定在一起。

    如果你想从 vendor1 移动到 vendor2 你不能这样做,首先你必须根据 vendor2 API 更改上面的代码,但是如果你使用第一种方法,你可以从 Vendor 移动到 Vendor 而无需更改你的代码。

    【讨论】:

    • 我只是想理解这个概念。是不是我们在 Class.forName() 中加载的类实现了这些方法?
    • 说MySQL实现java.sql.Connection接口的类是com.mysql.Connnection,Driver、PreparedStatement等类似
    • k.如果有A类和B类实现接口C。如果我说Cobject.methodinC(),编译器如何知道必须考虑哪个实现?
    • 要调用 Cobject.methodinC(),你可以做类似 C Cobject = new CImpl();运行时会用到CImpl,下次请新题
    • 从 JDBC 4 (Java 6) 开始,不再需要使用Class.forName“加载”驱动程序(如果您使用的是符合 JDBC 4 的驱动程序)
    【解决方案2】:

    你实际上并没有这样做

    Connection conn = new Connection();
    

    你做了类似的事情

    Connection conn = DriverManager.getConnection(
         DB_PATH + "?user=" + USER_NAME + "&password=" + USER_PASS); 
    Statement statement = conn.createStatement();
    ResultSet resultSet = statement.executeQuery(query);
    

    但要直接回答您的问题,不,您不能实例化 Interface,您必须使用 implements Interface 的类或使用代理。

    【讨论】:

    • k.但是我的问题是哪个类实现了接口的createStatement(),executQuery()方法?
    • 每个实现Statement 接口的类都必须重写executeQuery() 方法(以及该接口的任何其他方法)。您使用哪一个取决于conn.createStatement() 的工作方式以及它实际返回的内容。
    • k.我知道。我们曾经创建一个实现接口的类的对象并调用该接口的相应方法..但这里是直接用接口对象调用方法。没有类的方法是如何被覆盖的?
    • 如果您想要打印出conn.getClass() 的实际类名,它会告诉您名称,但您真的不应该使用JDBC 旨在通过其接口工作的具体类.
    • 我不想在我的课堂上实现这个接口。我只想知道使用接口对象和访问该接口的方法的概念,例如 Statement.executeQuery(query)。
    【解决方案3】:

    您不能实例化接口类。您要么自己实现该接口,要么使用Proxy 创建所述接口的实例,将所有调用委托给提供的InvocationHandler

    【讨论】:

      【解决方案4】:

      这些人正在回答你的问题,但我认为你不是从 cmets 那里得到的。

      您需要通过创建自己的类来实际实现接口。因此,创建一个实现接口的类,包含正确的抽象方法,然后将您想要的任何内容添加到新类中的功能中。然后您将实例化该类以使用这些函数。

      接口就像一个编程“合同”,它的存在是为了确保使用的任何扩展接口的类都满足某些功能,但是,您不能实例化接口本身以使用其方法,您可以继承/覆盖它们他们在你的新班级。覆盖新类中的抽象方法后,您可以编写任何您希望特定接口扩展类执行的操作。

      http://www.javabeginner.com/learn-java/java-abstract-class-and-interfacehttp://www.javaworld.com/javaworld/javaqa/2001-04/03-qa-0420-abstract.html 将让您阅读这些主题。

      【讨论】:

      • 否决链接此人似乎不理解的基本概念? OP 显然在继承和接口方面苦苦挣扎,之前的答案并没有指向背景材料。
      【解决方案5】:

      希望下面的解释会有所帮助。

      问:驱动连接实现从何而来?以及Statement和ResultSet的实现?

      Class.forName("com.mysql.jdbc.Driver").newInstance();
      // String url="jdbc:mysql://localhost:3306/mydb?user=root&password=root";
      Connection con = DriverManager.getConnection(url);
      

      小提示:一旦 DriverManager 类被加载(初始化),驱动程序实现就会被加载。

      以mysql-connector-java:5.1.36的源码为例

      ● 类 com.mysql.jdbc.Driver 扩展类 NonRegisteringDriver,其中有一个名为 connect() 的方法,它返回一个连接实例。
      注意 NonRegisteringDriver 的 registeredDrivers 字段

      public class Driver extends NonRegisteringDriver implements java.sql.Driver {
      ...
      public java.sql.Connection connect(String url, Properties info) throws SQLException {
      

      ● mysql驱动注册,驱动添加到registeredDrivers

      Class.forName("com.mysql.jdbc.Driver");
      ...
      java.sql.DriverManager.registerDriver(new Driver()); // from com.mysql.jdbc.Driver
      ...
      registeredDrivers.addIfAbsent(new DriverInfo(driver, da));  // mysql driver instance is added to registeredDrivers
      

      从现在开始JDBC知道有一种JDBC实现,即mysql。
      ● 然后创建连接:

      Connection con = DriverManager.getConnection(url);
      

      ● 关注DriverManager.getConnection的源码
      注意注册司机
      这里的connection implementation是由aDriver.driver.connect

      创建的
      for(DriverInfo aDriver : registeredDrivers) {
      ...
           Connection con = aDriver.driver.connect(url, info);
      ...
      }
      

      ● 既然已经找到了mysql的连接实现,那么StatementResultSet的实现也可以通过挖掘mysql-connector-java的源码找到: 5.1.36

      Statement stmt = con.createStatement();
      // String sql = "select * from user";
      ResultSet rs=stmt.executeQuery(sql);
      

      对于JDBC 4,DriverManager类加载时会自动从classpath中检测驱动实现:
      DriverManager.java#l101

      static {
          loadInitialDrivers();
          println("JDBC DriverManager initialized");
      }
      
      ...
      
      private static void loadInitialDrivers() {
      ...
          ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
      ...
      }
      

      文件 mysql-connector-java-5.1.36.jar!/META-INF/services/java.sql.Driver的内容:

      com.mysql.jdbc.Driver
      com.mysql.fabric.jdbc.FabricMySQLDriver
      

      【讨论】:

        猜你喜欢
        • 2020-05-27
        • 1970-01-01
        • 2012-08-26
        • 2015-01-31
        • 2013-08-03
        • 2016-06-20
        • 1970-01-01
        • 2019-07-26
        相关资源
        最近更新 更多