java.sql.Connection的close方法究竟干了啥(以MySQL为例)(一)

2015-01-21 11:16:02 · 作者: · 浏览: 30

谨将此文送给和我一样具有考据癖的程序员,希望能帮到大家…………

闲言少叙,上代码。

?

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		Class.forName("com.mysql.jdbc.Driver");
		Connection conn = DriverManager.getConnection(
				"jdbc:mysql://localhost:3306/financial_db", "root", "admin");
		conn.close();
		System.out.println(conn.isClosed()); // true after conn.close() if no exception
		System.out.println(conn == null); // not null after conn.close()

		Connection emptyConn = null;
		emptyConn.isClosed(); // NullPointerException
	}

解释:

?

1. java.sql.Connection.close()方法做的是立刻释放connection对象占用的数据库联接资源,而不是等到JVM的垃圾回收机制将其回收。并不是像我原以为的那样,close方法会简单地将conn对象设置为null。事实上,在调用close()之后,conn仍然不为null。

2. 对一个为null的connection,调用close()方法会报空指针异常。

当然,如果你只是想知道为什么关闭一个Connection要用close方法而不是直接置为null,或者等待其被垃圾回收,那么看到这里你就可以关闭窗口了。如果你和我一样,对这个close方法究竟干了啥感兴趣,那么请不厌其烦接着往下看。

这个close方法究竟干了啥,好,读了MySQL Connector/J 的代码,接着写:

java.sql.Connection自身是一个接口,具体怎么实现是由JDBC自己实现的。MySQL中的实现是

1. 先用com.mysql.jdbc.Connection接口来继承java.sql.Connection接口:

public interface Connection extends java.sql.Connection, ConnectionProperties

2. 再用com.mysql.jdbc.MySQLConnection继承com.mysql.jdbc.Connection接口:

?

public interface MySQLConnection extends Connection, ConnectionProperties

?

3.最后使用com.mysql.jdbc.ConnectionImpl来实现com.mysql.jdbc.MySQLConnection接口:

?

public class ConnectionImpl extends ConnectionPropertiesImpl implements MySQLConnection

此处猜想,如果使用MySQL Connector/J来联接MySQL数据库,通过java.sql.DriverManager.getConnection(...)方法获得的Connection对象其类型应该是com.mysql.jdbc.ConnectionImpl(准确地说应该是其本身或其子类). 代码证明:

?

?

	public static void main(String[] args) throws Exception {
		Class.forName("com.mysql.jdbc.Driver");
		Connection conn = DriverManager.getConnection(
				"jdbc:mysql://localhost:3306/financial_db", "root", "admin");
		
		System.out.println(conn instanceof com.mysql.jdbc.ConnectionImpl); // true
	}
结果为true,假设成立。

?

找到com.mysql.jdbc.ConnectionImpl的close方法,我们编程中使用的java.sql.Connection.close()方法其在MySQL Connector/J的实现就是该方法,如下:

?

    /**
     * In some cases, it is desirable to immediately release a Connection's
     * database and JDBC resources instead of waiting for them to be
     * automatically released (cant think why off the top of my head) Note:
     * A Connection is automatically closed when it is garbage collected.
     * Certain fatal errors also result in a closed connection.
     * 
     * @exception SQLException
     *                if a database access error occurs
     */
    public void close() throws SQLException {
        synchronized (getConnectionMutex()) {
            if (this.connectionLifecycleInterceptors != null) {
                new IterateBlock(this.connectionLifecycleInterceptors.iterator()) {
                    @Override
                    void forEach(Extension each) throws SQLException {
                        ((ConnectionLifecycleInterceptor) each).close();
                    }
                }.doForAll();
            }

            realClose(true, true, false, null);
        }
    }

官方的注释说,这个方法用在那些需要立即释放连接资源的情况下。一个连接在被垃圾回收的时候是自动关闭的,并且一些致命错误(fatal errors)也会导致这个连接关闭。

?

通过代码可以发现,close这个方法里面,真正释放连接资源的是最下面这个realClose方法(上面的ConnectionLifecycleInterceptor在jdbc的代码里只找到一个接口,貌似具体的实现和MySQL的附件有关),原文这么说:Implementors of this interface can be installed via the "connectionLifecycleInterceptors" configuration property and receive events and alter beha