本博客要记录的是如何去使用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的驱动注册项。