JDBC: why 'Class.forName' at first
First, here is the following basic code:
1
package
com.googlesites.qslbinghamton.corejava.database;
2
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7 import java.sql.Statement;
8
9 public class MySqlConn {
10 public static Connection getConnection() throws Exception {
11 String driver = " com.mysql.jdbc.Driver " ;
12 String url = " jdbc:mysql://localhost/t2 " ;
13 String username = " root " ;
14 String password = "12345678 " ;
15
16 Class.forName(driver);
17 Connection conn = DriverManager.getConnection(url, username, password);
18 return conn;
19 }
20
21 public static void main(String[] args) {
22 Connection conn = null ;
23 Statement stmt = null ;
24 ResultSet rs = null ;
25 try {
26 conn = getConnection();
27 System.out.println( " conn= " + conn);
28 // prepare query
29 String query = " select * from Employee " ;
30 // create a statement
31 stmt = conn.createStatement();
32 // execute query and return result as a ResultSet
33 rs = stmt.executeQuery(query);
34 // extract data from the ResultSet
35 while (rs.next()) {
36 String id = rs.getString( 1 );
37 String username = rs.getString( 2 );
38
39 System.out.println( " id= " + id);
40 System.out.println( " name= " + username);
41 System.out.println( " --------------- " );
42 }
43 } catch (Exception e) {
44 e.printStackTrace();
45 System.exit( 1 );
46 } finally {
47 // release database resources
48 try {
49 rs.close();
50 stmt.close();
51 conn.close();
52 } catch (SQLException e) {
53 e.printStackTrace();
54 }
55 }
56 }
57 }
58
2
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7 import java.sql.Statement;
8
9 public class MySqlConn {
10 public static Connection getConnection() throws Exception {
11 String driver = " com.mysql.jdbc.Driver " ;
12 String url = " jdbc:mysql://localhost/t2 " ;
13 String username = " root " ;
14 String password = "12345678 " ;
15
16 Class.forName(driver);
17 Connection conn = DriverManager.getConnection(url, username, password);
18 return conn;
19 }
20
21 public static void main(String[] args) {
22 Connection conn = null ;
23 Statement stmt = null ;
24 ResultSet rs = null ;
25 try {
26 conn = getConnection();
27 System.out.println( " conn= " + conn);
28 // prepare query
29 String query = " select * from Employee " ;
30 // create a statement
31 stmt = conn.createStatement();
32 // execute query and return result as a ResultSet
33 rs = stmt.executeQuery(query);
34 // extract data from the ResultSet
35 while (rs.next()) {
36 String id = rs.getString( 1 );
37 String username = rs.getString( 2 );
38
39 System.out.println( " id= " + id);
40 System.out.println( " name= " + username);
41 System.out.println( " --------------- " );
42 }
43 } catch (Exception e) {
44 e.printStackTrace();
45 System.exit( 1 );
46 } finally {
47 // release database resources
48 try {
49 rs.close();
50 stmt.close();
51 conn.close();
52 } catch (SQLException e) {
53 e.printStackTrace();
54 }
55 }
56 }
57 }
58
Here is a trivial question, why Class.forName in the first place.
Now, let's take a look at class com.mysql.jdbc.Driver source file:
1
package
com.mysql.jdbc;
2
3 import java.sql.SQLException;
4
5 /**
6 * The Java SQL framework allows for multiple database drivers. Each driver
7 * should supply a class that implements the Driver interface
8 *
9 * <p>
10 * The DriverManager will try to load as many drivers as it can find and then
11 * for any given connection request, it will ask each driver in turn to try to
12 * connect to the target URL.
13 *
14 * <p>
15 * It is strongly recommended that each Driver class should be small and
16 * standalone so that the Driver class can be loaded and queried without
17 * bringing in vast quantities of supporting code.
18 *
19 * <p>
20 * When a Driver class is loaded, it should create an instance of itself and
21 * register it with the DriverManager. This means that a user can load and
22 * register a driver by doing Class.forName("foo.bah.Driver")
23 *
24 * @see org.gjt.mm.mysql.Connection
25 * @see java.sql.Driver
26 * @author Mark Matthews
27 * @version $Id$
28 */
29 public class Driver extends NonRegisteringDriver implements java.sql.Driver {
30 // ~ Static fields/initializers
31 // ---------------------------------------------
32
33 //
34 // Register ourselves with the DriverManager
35 //
36 static {
37 try {
38 java.sql.DriverManager.registerDriver( new Driver());
39 } catch (SQLException E) {
40 throw new RuntimeException( " Can't register driver! " );
41 }
42 }
43
44 // ~ Constructors
45 // -----------------------------------------------------------
46
47 /**
48 * Construct a new driver and register it with DriverManager
49 *
50 * @throws SQLException
51 * if a database error occurs.
52 */
53 public Driver() throws SQLException {
54 // Required for Class.forName().newInstance()
55 }
56 }
57
2
3 import java.sql.SQLException;
4
5 /**
6 * The Java SQL framework allows for multiple database drivers. Each driver
7 * should supply a class that implements the Driver interface
8 *
9 * <p>
10 * The DriverManager will try to load as many drivers as it can find and then
11 * for any given connection request, it will ask each driver in turn to try to
12 * connect to the target URL.
13 *
14 * <p>
15 * It is strongly recommended that each Driver class should be small and
16 * standalone so that the Driver class can be loaded and queried without
17 * bringing in vast quantities of supporting code.
18 *
19 * <p>
20 * When a Driver class is loaded, it should create an instance of itself and
21 * register it with the DriverManager. This means that a user can load and
22 * register a driver by doing Class.forName("foo.bah.Driver")
23 *
24 * @see org.gjt.mm.mysql.Connection
25 * @see java.sql.Driver
26 * @author Mark Matthews
27 * @version $Id$
28 */
29 public class Driver extends NonRegisteringDriver implements java.sql.Driver {
30 // ~ Static fields/initializers
31 // ---------------------------------------------
32
33 //
34 // Register ourselves with the DriverManager
35 //
36 static {
37 try {
38 java.sql.DriverManager.registerDriver( new Driver());
39 } catch (SQLException E) {
40 throw new RuntimeException( " Can't register driver! " );
41 }
42 }
43
44 // ~ Constructors
45 // -----------------------------------------------------------
46
47 /**
48 * Construct a new driver and register it with DriverManager
49 *
50 * @throws SQLException
51 * if a database error occurs.
52 */
53 public Driver() throws SQLException {
54 // Required for Class.forName().newInstance()
55 }
56 }
57
Take a close look in class Driver's static block:
java.sql.DriverManager.registerDriver(
new
Driver());
It ensures the new created Driver object is registered every time after Driver class is created or Driver instance is created.
Class.forName(driver); make sure the code in static block run at first which means a new Driver class object is created during the compile time.
For better understanding, here is a sample program which have a static block in the class
class
A {
static {
System.out.println( " Class A loaded " );
}
public A() {
System.out.println( " create a instance of A " );
}
}
public class Main {
public static void main(String[] args) throws Exception {
Class.forName( " com.javaye.A " );
}
}
static {
System.out.println( " Class A loaded " );
}
public A() {
System.out.println( " create a instance of A " );
}
}
public class Main {
public static void main(String[] args) throws Exception {
Class.forName( " com.javaye.A " );
}
}
The output from class Main is
Class A loaded
Now, change the above code a little bit in public static void main function: only initiate class A a=null.
1
class
A {
2 static {
3 System.out.println( " Class A loaded " );
4 }
5
6 public A() {
7 System.out.println( " create a instance of A " );
8 }
9 }
10
11 public class Main {
12
13 public static void main(String[] args) throws Exception {
14 A a = null ;
15
16 }
17 }
2 static {
3 System.out.println( " Class A loaded " );
4 }
5
6 public A() {
7 System.out.println( " create a instance of A " );
8 }
9 }
10
11 public class Main {
12
13 public static void main(String[] args) throws Exception {
14 A a = null ;
15
16 }
17 }
There is no output at this time. This is because only with a variable name 'a' doesn't change the fact that no new object from class 'A' is created and the static block doesn't
run neither.
Change the code again:
1
class
A {
2 static {
3 System.out.println( " Class A loaded " );
4 }
5
6 public A() {
7 System.out.println( " create a instance of A " );
8 }
9 }
10
11 public class Main {
12
13 public static void main(String[] args) throws Exception {
14 A a = new A();
15 A a2 = new A();
16 }
17 }
2 static {
3 System.out.println( " Class A loaded " );
4 }
5
6 public A() {
7 System.out.println( " create a instance of A " );
8 }
9 }
10
11 public class Main {
12
13 public static void main(String[] args) throws Exception {
14 A a = new A();
15 A a2 = new A();
16 }
17 }
The outputs are:
Class A loaded
create a instance of A
create a instance of A
Clearly, with new A(), static block only runs once(The basic concept of static) and constructor of A runs twice as 2 objects are creates.