本博客要记录的是如何去使用JDBC去操作数据库的一般过程。

JDBC操作步骤如下:

    1.注册驱动

    2.建立连接

    3.创建语句对象

    4.执行语句

    5.处理结果集

    6.关闭资源


看如下代码:

    

package Base;

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

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;

public class BaseDriver {

	public static void Test() throws SQLException{
		//注册驱动
		DriverManager.registerDriver(new com.mysql.jdbc.Driver());
		
		//建立连接
		Connection conn = (Connection) DriverManager.getConnection("", "root","password01!");
		
		//创建语句
		Statement stm = (Statement) conn.createStatement();
		
		//执行语句,获取结果
		ResultSet resultSet = stm.executeQuery("select * from t_user");
		
		//遍历结果集
		while(resultSet.next()){
			System.out.println(resultSet.getObject(0)+"\t"+resultSet.getObject(1)+"\t"+resultSet.getObject(2)+"\t"+resultSet.getObject(3));
		}
		
		//释放资源
		resultSet.close();
		stm.close();
		conn.close();
		
	}
}

    1.注册驱动

        注册驱动的方式有两种:

        a.DriverManager进行注册

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

        b.使用Class进行注册

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

    

        注册驱动过程到底做了什么事情呢?听我慢慢道来:

            a方式注册驱动主要做了如下工作:

        首先我们先来看一下DriverManager的源代码:

public class DriverManager {


    // List of registered JDBC drivers
    private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();
    private static volatile int loginTimeout = 0;
    private static volatile java.io.PrintWriter logWriter = null;
    private static volatile java.io.PrintStream logStream = null;
    // Used in println() to synchronize logWriter
    private final static  Object logSync = new Object();
   
}

    上面是通过反编译出来的DriverManager类的部分代码

private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();把驱动注册在一个列表里面。有了数据库的驱动包后,在调用getConnection后,就会在这个驱动注册列表里面去一个一个的找,看是否能够建立连接,如果最后没有找到,那么就会抛出异常。


        b.方式注册驱动做了哪些工作:

    同样我们也来看一下源代码:

 /**
     * Returns the {@code Class} object associated with the class or
     * interface with the given string name.  Invoking this method is
     * equivalent to:
     *
     * <blockquote>
     *  {@code Class.forName(className, true, currentLoader)}
     * </blockquote>
     *
     * where {@code currentLoader} denotes the defining class loader of
     * the current class.
     *
     * <p> For example, the following code fragment returns the
     * runtime {@code Class} descriptor for the class named
     * {@code java.lang.Thread}:
     *
     * <blockquote>
     *   {@code Class t = Class.forName("java.lang.Thread")}
     * </blockquote>
     * <p>
     * A call to {@code forName("X")} causes the class named
     * {@code X} to be initialized.
     *
     * @param      className   the fully qualified name of the desired class.
     * @return     the {@code Class} object for the class with the
     *             specified name.
     * @exception LinkageError if the linkage fails
     * @exception ExceptionInInitializerError if the initialization provoked
     *            by this method fails
     * @exception ClassNotFoundException if the class cannot be located
     */
    @CallerSensitive
    public static Class<?> forName(String className)
                throws ClassNotFoundException {
        return forName0(className, true,
                        ClassLoader.getClassLoader(Reflection.getCallerClass()));
    }

根据上面的反编译出来的Class源代码重的ForName的源代码,也是加载在一个驱动列表中,通过遍历驱动列表进行检测是否有符合目标的驱动注册,如果没有则抛出异常。


    区别:

        DriverManager.registerDriver(new com.mysql.jdbc.Driver());会在JVM装载类时调用静态代码初始化块,new com.mysql.jdbc.Driver()同时会实例化一个驱动实例,所以这种方式会在驱动注册列表中出现两个相同的MySql的驱动注册项。

        Class.forName("com.mysql.jdbc.Driver");因为forName的参数是字符串类型,在加载类时只会调用静态代码块创建一个实例,驱动注册表中只有一个MySql的驱动注册项。