如何正确使用Sqlsql connectionn

5854人阅读
本文将详细介绍如何使用Connection对象连接数据库。
对于不同的.NET数据提供者,ADO.NET采用不同的Connection对象连接数据库。这些Connection对象为我们屏蔽了具体的实现细节,并提供了一种统一的实现方法。  Connection类有四种:SqlConnection,OleDbConnection,OdbcConnection和OracleConnection。  SqlConnection类的对象连接SQL Server数据库;OracleConnection 类的对象连接Oracle数据库;  OleDbConnection类的对象连接支持OLE DB的数据库,如Access;而OdbcConnection类的对象连接任何支持ODBC的数据库。与数据库的所有通讯最终都是通过Connection对象来完成的。   SqlConnection类  Connection 用于与数据库&对话&,并由特定提供程序的类(如 SqlConnection)表示。尽管SqlConnection类是针对Sql Server的,但是这个类的许多属性、方法与事件和OleDbConnection及OdbcConnection等类相似。本章将重点讲解SqlConnection特定的属性与方法,其他的Connection类你可以参考相应的帮助文档。  注意:使用不同的Connection对象需要导入不同的命名空间。OleDbConnection的命名空间为System.Data.OleDb。SqlConnection的命名空间为System.Data.SqlClient。OdbcConnection的命名空间为System.Data.Odbc。OracleConnection的命名空间为System.Data.OracleClinet。  SqlConnection属性:
ConnectionString
其返回类型为string,获取或设置用于打开 SQL Server 数据库的字符串。
ConnectionTimeOut
其返回类型为int,获取在尝试建立连接时终止尝试并生成错误之前所等待的时间。
其返回类型为string,获取当前数据库或连接打开后要使用的数据库的名称。
DataSource
其返回类型为string,获取要连接的 SQL Server 实例的名称。
其返回类型为ConnectionState,取得当前的连接状态:Broken、Closed、Connecting、Fetching或Open。
ServerVersion
其返回类型为string,获取包含客户端连接的 SQL Server 实例的版本的字符串。
PacketSize
获取用来与 SQL Server 的实例通信的网络数据包的大小(以字节为单位)。这个属性只适用于SqlConnection类型
  SqlConnection方法:
其返回类型为void,关闭与数据库的连接。
CreateCommand()
其返回类型为SqlCommand,创建并返回一个与 SqlConnection 关联的 SqlCommand 对象。
其返回类型为void,用连接字符串属性指定的属性打开数据库连接
  SqlConnection事件:
StateChange
当事件状态更改时发生。 (从 DbConnection 继承。)
InfoMessage
当 SQL Server 返回一个警告或信息性消息时发生。
  提示:可以用事件让一个对象以某种方式通知另一对象产生某些事情。例如我们在Windows系统中选择&开始&菜单,一旦单击鼠标时,就发生了一个事件,通知操作系统将&开始&菜单显示出来。
  使用SqlConnection对象连接SQL Server数据库  我们可以用SqlConnection()构造函数生成一个新的SqlConnection对象。这个函数是重载的,即我们可以调用构造函数的不同版本。SqlConnection()的构造函数如下表所示:
SqlConnection ()
初始化 SqlConnection 类的新实例。
SqlConnection (String)
如果给定包含连接字符串的字符串,则初始化 SqlConnection 类的新实例。
  程序代码说明:在上述语法范例的程序代码中,我们通过使用&new&关键字生成了一个新的SqlConnection对象,并且将其命名为mySqlConnection。   现在我们就可以使用如下两种方式连接数据库,即采用集成的Windows验证和使用Sql Server身份验证进行数据库的登录。  集成的Windows身份验证语法范例
string connectionString=&server=database=Nintegrated security=SSPI&;
  程序代码说明:在上述语法范例的程序代码中,我们设置了一个针对Sql Server数据库的连接字符串。其中server表示运行Sql Server的计算机名,由于在本书中,ASP.NET程序和数据库系统是位于同一台计算机的,所以我们可以用localhost取代当前的计算机名。database表示所使用的数据库名,这里设置为Sql Server自带的一个示例数据库--Northwind。由于我们希望采用集成的Windows验证方式,所以设置 integrated security为SSPI即可。  Sql Server 2005中的Windows身份验证模式如下:
  注意:在使用集成的Windows验证方式时,并不需要我们输入用户名和口令,而是把登录Windows时输入的用户名和口令传递到Sql Server。然后Sql Server检查用户清单,检查其是否具有访问数据库的权限。而且数据库连接字符串是不区分大小写的。  采用Sql Server身份验证的语法范例
string connectionString = &server=database=Nuid=pwd=sa&;
  程序代码说明:在上述语法范例的程序代码中,采用了使用已知的用户名和密码验证进行数据库的登录。uid为指定的数据库用户名,pwd为指定的用户口令。为了安全起见,一般不要在代码中包括用户名和口令,你可以采用前面的集成的Windows验证方式或者对Web.Config文件中的连接字符串加密的方式提高程序的安全性。  Sql Server 2005中的Sql Server身份验证模式如下:
  如果你使用其他的数据提供者的话,所产生的连接字符串也具有相类似的形式。例如我们希望以OLE DB的方式连接到一个Oracle数据库,其连接字符串如下:
string connectionString = &data source=initial catalog=Suse id=password=;provider=MSDAORA&;
  程序代码说明:在上述语法范例的程序代码中,通过专门针对Oracle数据库的OLE DB提供程序,实现数据库的连接。data source 表示运行Oracle数据库的计算机名,initial catalog表示所使用的数据库名。provider表示使用的OLE DB提供程序为MSDAORA。  Access数据库的连接字符串的形式如下:
string connectionString = &provider=Microsoft.Jet.OLEDB.4.0;@&data source=c:/DataSource/Northwind.mdb&;
  程序代码说明:在上述语法范例的程序代码中,通过专门针对Access数据库的OLE DB提供程序,实现数据库的连接。这使用的的OLE DB提供程序为Microsoft.Jet.OLEDB.4.0,并且数据库存放在c:/DataSource目录下,其数据库文件为Northwind.mdb。  现在我们就可以将数据库连接字符串传人SqlConnection()构造函数,例如:
string connectionString = &server=database=Nuid=pwd=sa&;SqlConnection mySqlConnection = new SqlConnection(connectionString);
  或者写成
SqlConnection mySqlConnection =new SqlConnection(&server=database=Nuid=pwd=sa&);
  在前面的范例中,通过使用&new&关键字生成了一个新的SqlConnection对象。因此我们也可以设置该对象的ConnectionString属性,为其指定一个数据库连接字符串。这和将数据库连接字符串传人SqlConnection()构造函数的功能是一样的。
SqlConnection mySqlConnection = new SqlConnection();mySqlConnection.ConnectionString = &server=database=Nuid=pwd=sa&;
  注意:只能在关闭Connection对象时设置ConnectionString属性。
  打开和关闭数据库连接  生成Connection对象并将其设置ConnectionString属性设置为数据库连接的相应细节之后,就可以打开数据库连接。为此可以调用Connection对象的Open()方法。其方法如下:
mySqlConnection.Open();
  完成数据库的连接之后,我们可以调用Connection对象的Close()方法关闭数据库连接。例如:
mySqlConnection.Close();
  下面是一个显示如何用SqlConnection对象连接Sql Server Northwind数据库的实例程序,并且显示该SqlConnection对象的一些属性。  范例程序代码如下:
01 public partial class _Default : System.Web.UI.Page 02 {03 protected void Page_Load(object sender, EventArgs e)04 {05 //建立数据库连接字符串06 string connectionString = &server=database=N 07 integrated security=SSPI&;08 //将连接字符串传入SqlConnection对象的构造函数中09 SqlConnection mySqlConnection = new SqlConnection(connectionString);10 try11 {12 //打开连接13 mySqlConnection.Open();14 //利用label控件显示mySqlConnection对象的ConnectionString属性15 lblInfo.Text = &<b>mySqlConnection对象的ConnectionString属性为:<b>& + 16 mySqlConnection.ConnectionString + &<br>&;17 lblInfo.Text += &<b>mySqlConnection对象的ConnectionTimeout属性为<b>& + 18 mySqlConnection.ConnectionTimeout + &<br>&;19 lblInfo.Text += &<b>mySqlConnection对象的Database属性为<b>& + 20 mySqlConnection.Database + &<br>&;21 lblInfo.Text += &<b>mySqlConnection对象的DataSource属性为<b>& +22 mySqlConnection.DataSource + &<br>&;23 lblInfo.Text += &<b>mySqlConnection对象的PacketSize属性为<b>& + 24 mySqlConnection.PacketSize + &<br>&;25 lblInfo.Text += &<b>mySqlConnection对象的ServerVersion属性为<b>& + 26 mySqlConnection.ServerVersion + &<br>&;27 lblInfo.Text += &<b>mySqlConnection对象的当前状态为<b>& +28 mySqlConnection.State + &<br>&;29 }30 catch (Exception err)31 {32 lblInfo.Text = &读取数据库出错&;33 lblInfo.Text += err.M34 }35 finally 36 {37 //关闭与数据库的连接38 mySqlConnection.Close();39 lblInfo.Text += &<br><b>关闭连接后的mySqlConnection对象的状态为:</b>&;40 lblInfo.Text += mySqlConnection.State.ToString();41 }42 }43 }
  程序代码说明:在上述范例的程序代码中,我们利用try catch finally对数据库连接进行异常处理。当无法连接数据库时将抛出异常,并显示出错信息,见catch代码块所示。在此程序中,无论是否发生异常,都可以通过finally区块关闭数据库的连接,从而节省计算机资源,提高了程序的效率和可扩展性。  执行结果:
  当然,我们还可以采用一种更加简便的方法来实现上述程序的功能。这就是将SqlConnection对象包含到using区块中,这样程序会自动调用Dispose()方法释放SqlConnection对象所占用的系统资源,无需再使用SqlConnection对象的Close()方法。  范例程序代码如下:
01 public partial class _Default : System.Web.UI.Page 02 {03 protected void Page_Load(object sender, EventArgs e)04 {05 string connectionString = &server=database=N06 integrated security=SSPI&;07 SqlConnection mySqlConnection = new SqlConnection(connectionString);08 using (mySqlConnection) 09 {10 mySqlConnection.Open();11 lblInfo.Text = &<b>mySqlConnection对象的ConnectionString属性为:<b>& +12 mySqlConnection.ConnectionString + &<br>&;13 lblInfo.Text += &<b>mySqlConnection对象的ConnectionTimeout属性为<b>& +14 mySqlConnection.ConnectionTimeout + &<br>&;15 lblInfo.Text += &<b>mySqlConnection对象的Database属性为<b>& +16 mySqlConnection.Database + &<br>&;17 lblInfo.Text += &<b>mySqlConnection对象的DataSource属性为<b>& + 18 mySqlConnection.DataSource + &<br>&;19 lblInfo.Text += &<b>mySqlConnection对象的PacketSize属性为<b>& + 20 mySqlConnection.PacketSize + &<br>&;21 lblInfo.Text += &<b>mySqlConnection对象的ServerVersion属性为<b>& + 22 mySqlConnection.ServerVersion + &<br>&;23 lblInfo.Text += &<b>mySqlConnection对象的当前状态为<b>&+24 mySqlConnection.State + &<br>&;25 }26 lblInfo.Text += &<br><b>关闭连接后的mySqlConnection对象的状态为:</b>&;27 lblInfo.Text += mySqlConnection.State.ToString();28 }29 }
  程序代码说明:在上述范例的程序代码中,采用using(mySqlConnection)的形式使得代码更加简洁,并且其最大的优点就是无需编写finally区块代码,可以自动关闭与数据库的连接。
  连接池  打开与关闭数据库都是比较耗时的。为此,ADO.NET自动将数据库连接存放在连接池中。连接池可以大幅度提高程序的性能和效率,因为我们不必等待建立全新的数据库连接过程,而是直接利用现成的数据库连接。注意,利用Close()方法关闭连接时,并不是实际关闭连接,而是将连接标为未用,放在连接池中,准备下一次复用。  如果在连接字符串中提供相同的细节,即相同的数据库,用户名,密码等等,则可以直接取得并返回池中的连接。然后可以用这个连接访问数据库。  使用SqlConnection对象时,可以在连接字符串中指定max pool size,表示连接池允许的最大连接数(默认为100),也可以指定min pool size表示连接池允许的最小连接数(默认为0)。下面的代码指定了SqlConnection对象的max pool size为10,min pool size为5。
SqlConnection mySqlConnection = new SqlConnection(&server=database=Nintegrated security=SSPI;&+&max pool size=10;min pool size=5&);
  程序代码说明:在上述范例的程序代码中,程序最初在池中生成5个SqlConnection对象。池中可以存储最多10个SqlConnection对象。如果要打开新的SqlConnection对象时,池中的对象全部都在使用中,则请求要等待一个SqlConnection对象关闭,然后才可以使用新的SqlConnection对象。如果请求等待时间超过ConnectionTimeout属性指定的秒数,则会抛出异常。  下面通过一个程序来显示连接池的性能优势。在应用此程序过程我们要先引用System.Data.SqlClinet和System.Text命名空间。  范例程序代码如下:
01 public partial class _Default : System.Web.UI.Page 02 {03 protected void Page_Load(object sender, EventArgs e)04 {05 //设置连接池的最大连接数为5,最小为106 SqlConnection mySqlConnection =new SqlConnection(07 &server=database=Nintegrated security=SSPI;&+08 &max pool size=5;min pool size=1&);09 //新建一个StringBuilder对象 10 StringBuilder htmStr = new StringBuilder(&&);11 for (int count = 1; count <= 5; count++)12 {13 //使用Append()方法追加字符串到StringBuilder对象的结尾处14 htmStr.Append(&连接对象 &+count);15 htmStr.Append(&<br>&);16 //设置一个连接的开始时间17 DateTime start = DateTime.N18 mySqlConnection.Open();19 //连接所用的时间20 TimeSpan timeTaken = DateTime.Now -21 htmStr.Append(&连接时间为 &+timeTaken.Milliseconds+&毫秒&);22 htmStr.Append(&<br>&);23 htmStr.Append(&mySqlConnection对象的状态为& + mySqlConnection.State);24 htmStr.Append(&<br>&);25 mySqlConnection.Close();26 }27 //将StringBuilder对象的包含的字符串在label控件中显示出来28 lblInfo.Text = htmStr.ToString();29 }30 }
  程序代码说明:在上述范例的程序代码中,我们将在连接池中重复5次打开一个SqlConnection对象,DateTime.Now表示当前的时间。timeTaken表示从连接开始到打开连接所用的时间间隔。可以看出,打开第一个连接的时间比打开后续连接的时间要长,因为第一个连接要实际连接数据库。被关闭之后,这个连接存放在连接池中。再次打开连接时,只要从池中直接读取即可,速度非常快。  提示:String 对象是不可改变的。每次使用 System.String 类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新的 String 对象相关的系统开销可能会非常昂贵。如果要修改字符串而不创建新的对象,则可以使用 System.Text.StringBuilder 类。例如,当在一个循环中将许多字符串连接在一起时,使用 StringBuilder 类可以提升性能。Append 方法可用来将文本或对象的字符串表示形式添加到由当前 StringBuilder 对象表示的字符串的结尾处。  执行结果:
  ASP.NET 2.0中连接字符串的设置  在ASP.NET 2.0中,使用了一种在运行时解析为连接字符串值的新的声明性表达式语法,按名称引用数据库连接字符串。连接字符串本身存储在 Web.config 文件中的 <connectionStrings> 配置节下面,以便易于在单个位置为应用程序中的所有页进行维护。  范例程序代码如下:
<?xml version=&1.0&?><configuration><connectionStrings><add name=&Pubs& connectionString=&Server=Integrated Security=TDatabase=Persist Security Info=True&providerName=&System.Data.SqlClient& /><add name=&Northwind& connectionString=&Server=Integrated Security=TDatabase=NPersist Security Info=True&providerName=&System.Data.SqlClient& /></connectionStrings><system.web><pages styleSheetTheme=&Default&/></system.web></configuration>
  程序代码说明:在上述范例的程序代码中,我们在Web.Config文件中的<connectionStrings> 配置节点下面设置了两个数据库连接字符串,分别指向pubs和Northwind两个示例数据库。注意,在2.0中引进了数据源控件,例如SqlDataSource 控件,我们可以将SqlDataSource 控件的 ConnectionString 属性被设置为表达式 <%$ ConnectionStrings:Pubs %>,该表达式在运行时由 ASP.NET 分析器解析为连接字符串。还可以为SqlDataSource 的 ProviderName 属性指定一个表达式,例如 <%$ ConnectionStrings:Pubs.ProviderName %>。其具体的用法和新特征将在以后的章节进行详细的介绍。现在有个基础的了解即可。  当然,我们也可以用下面的方式从配置文件直接读取数据库连接字符串。首先我们需要引用using System.Web.Configuration命名空间,该命名空间包含用于设置 ASP.NET 配置的类。
string connectionString =ConfigurationManager.ConnectionStrings[&Northwind&].ConnectionS
  程序代码说明:在上述范例的程序代码中,我们可以利用ConnectionStrings[&Northwind&]读取相应的Northwind字符串。同理以可以利用ConnectionStrings[&Pubs&]读取相应的Pubs字符串。&&&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:295193次
积分:4120
积分:4120
排名:第5001名
原创:94篇
转载:136篇
评论:81条
(1)(1)(2)(4)(6)(7)(1)(1)(2)(1)(1)(1)(1)(2)(3)(1)(10)(6)(53)(51)(28)(6)(16)(4)(1)(19)(1)java.sql.Connection的close方法究竟干了啥(以MySQL为例)
谨将此文送给和我一样具有考据癖的程序员,希望能帮到大家&&&&
闲言少叙,上代码。
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 =
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) &B&Note:&/B&
* 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&Extension&(this.connectionLifecycleInterceptors.iterator()) {
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 behavior of &lifecycle& methods on our connection implementation. (这个接口的实现可以通过connectionLifecycleInterceptors configuration property来安装,接收时间并且改变我们connection实现当中的lifecycle方法的行为)。这不是重点,重点是下面这个realClose。代码太长,我贴在最后。
通过阅读realClose的代码,可以发现这个方法有四个参数,前三个都是boolean类型,第四个是Throwable类型。calledExplicitly为这个方法是否是从close()方法调用的,issueRollback表示在释放资源的时候是否需要回滚操作rollback()。后两个参数没有给出注释,只好顾名思义,skipLocalTeardown表示是否跳过local teardown(在google上没有搜到什么有价值的结果&&),reason最终在代码中被赋值给ConnectionImpl的forceClosedReason(Why was this connection implicitly closed, if known? (for diagnostics) 为什么这个连接是隐式关闭的,如果原因可知(诊断用))。这两个参数和我们研究的问题关系不大。realClose核心代码在此:
if (!skipLocalTeardown) { // part 1 starts
&strong&closeAllOpenStatements();&/strong&
} catch (SQLException ex) {
} // part 1 ends
if (this.io != null) { // part 2 starts
&strong&this.io.quit();&/strong&
} catch (Exception e) {
&strong&this.io.forceClose();&/strong&
} // part 2 ends
if (this.statementInterceptors != null) { // part 3 starts
for (int i = 0; i & this.statementInterceptors.size(); i++) {
this.statementInterceptors.get(i).destroy();
if (this.exceptionInterceptor != null) {
this.exceptionInterceptor.destroy();
} // part 3 ends
} finally {
// part 4 starts
this.openStatements =
if (this.io != null) {
&strong&this.io.releaseResources();&/strong&
this.statementInterceptors =
this.exceptionInterceptor =
&strong&ProfilerEventHandlerFactory.removeInstance(this);&/strong&
synchronized (getConnectionMutex()) {
if (this.cancelTimer != null) {
&strong&this.cancelTimer.cancel();&/strong&
&strong&this.isClosed =&/strong&
// part 4 ends
在代码中做了注释,
part 1 通过closeAllIOpenStatements方法关闭了该连接中所有处于打开状态的声明statement,
part 2 用来关闭连接的IO(通过quit或forceClose方法),
part 3 用来销毁(destroy)连接的声明拦截器(statement interceptor)和异常拦截器(exception interceptor),
part 4 将上述已经关闭的openStatements, IO (如果IO不为null,则通过releaseResources方法释放资源), statementInterceptors和exceptionInterceptor置为null,并删除掉这个连接对应的的ProfilerEventHandler(这个类在jdbc的里就是孤零零一个接口,没有对应注释),将连接的cancelTimer计时器取消掉,再将连接的isClosed属性设置为true(代码中看到的isClosed方法就是返回这个属性的值)。
所以,通过这些代码,我们大概可以看出MySQL JDBC在建立一个连接的时候需要申请使用什么样的资源,至于这些资源有什么用,我再研究研究,后面的文章里再接着跟大家唠。^_^
写到这里才发现自己蠢哭了T_T,如果close方法只是将Connection置为null,那么怎么调用isClosed方法呢?唉,too young too naive,写了这么半天才转过弯来。 T_T
不过通过代码,发现realclose方法将释放后的资源对象的引用都置为了null,这是一个启发,以后在对connection调用完close方法之后,再将其设置为null,免得写着写着就忘了这连接已经被关闭不能使用了(因为会直接NullPointerException),也算是减少潜在的bug风险。总之,读一趟代码下来,收获还是挺大的。听周围很多外国同行说,我们国内的程序员不愿意和大家分享自己的收获和所得,听着惭愧啊。好,这边一点了都,写到这里,感谢一下中间给我递雪糕的室友,我们下篇文章再见。Cya.
附com.jdbc..ConnectionImpl.realClose方法完整源码,感兴趣大家可以一起研究,哈哈:
* Closes connection and frees resources.
* @param calledExplicitly
is this being called from close()
* @param issueRollback
should a rollback() be issued?
* @throws SQLException
if an error occurs
public void realClose(boolean calledExplicitly, boolean issueRollback, boolean skipLocalTeardown, Throwable reason) throws SQLException {
SQLException sqlEx =
if (this.isClosed()) {
this.forceClosedReason =
if (!skipLocalTeardown) {
if (!getAutoCommit() && issueRollback) {
rollback();
} catch (SQLException ex) {
reportMetrics();
if (getUseUsageAdvisor()) {
if (!calledExplicitly) {
String message = &Connection implicitly closed by Driver. You should call Connection.close() from your code to free resources more efficiently and avoid resource leaks.&;
this.eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_WARN, &&, this.getCatalog(), this.getId(), -1, -1, System
.currentTimeMillis(), 0, Constants.MILLIS_I18N, null, this.pointOfOrigin, message));
long connectionLifeTime = System.currentTimeMillis() - this.connectionCreationTimeM
if (connectionLifeTime & 500) {
String message = &Connection lifetime of & .5 seconds. You might be un-necessarily creating short-lived connections and should investigate connection pooling to be more efficient.&;
this.eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_WARN, &&, this.getCatalog(), this.getId(), -1, -1, System
.currentTimeMillis(), 0, Constants.MILLIS_I18N, null, this.pointOfOrigin, message));
closeAllOpenStatements();
} catch (SQLException ex) {
if (this.io != null) {
this.io.quit();
} catch (Exception e) {
this.io.forceClose();
if (this.statementInterceptors != null) {
for (int i = 0; i & this.statementInterceptors.size(); i++) {
this.statementInterceptors.get(i).destroy();
if (this.exceptionInterceptor != null) {
this.exceptionInterceptor.destroy();
} finally {
this.openStatements =
if (this.io != null) {
this.io.releaseResources();
this.statementInterceptors =
this.exceptionInterceptor =
ProfilerEventHandlerFactory.removeInstance(this);
synchronized (getConnectionMutex()) {
if (this.cancelTimer != null) {
this.cancelTimer.cancel();
this.isClosed =
if (sqlEx != null) {
throw sqlEx;
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'}

我要回帖

更多关于 sqlconnection 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信