`
悲剧了
  • 浏览: 144329 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

一个常见的JDBC封装导致的问题

阅读更多
大家看一个数据库封装类
操作一次没问题,操作两次就报错
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.


Debug调试,发现connection不能真正关掉,使用connection完后,调用close()方法,下次getConnection()时候
instance不为null



public class ConnectionUtil {
	private final static String  url="jdbc:mysql://localhost:3306/qq?useUnicode=true&characterEncoding=UTF-8";
	private final static String  username="root";
	private final static String  password="root";
	private  static Connection   instance=null;
	
	private ConnectionUtil(){
		if(instance==null){
			try {
				Class.forName("org.gjt.mm.mysql.Driver");
				instance=DriverManager.getConnection(url, username, password);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
		}
	}
	
	public static Connection getConnection(){
		if(instance==null){
			new ConnectionUtil();
		}
		return instance;
		
	}
	
	
	public static void close(Connection con,PreparedStatement ps,ResultSet rs){
		if(con!=null){
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				con=null;
			}
		}
		if(ps!=null){
			try {
				ps.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				ps=null;
			}
		}
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				rs=null;
			}
		}
		
	}
	
	public static void close(Connection con,PreparedStatement ps){
		if(con!=null){
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				con=null;
			}
		}
		if(ps!=null){
			try {
				ps.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				ps=null;
			}
		}
		
		
	}
	
	public static void close(Connection con){
		if(con!=null){
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				con=null;
			}
		}
	}

}



结贴了。。。。有其他结贴方式吗?
分享到:
评论
19 楼 mercyblitz 2011-05-16  
悲剧了 写道
mercyblitz 写道
悲剧了 写道
jinyao 写道
你是把connection关闭了  而不是置空



finally{ 
                con=null; 
            } 


最后有句这个代码



这代码写的,,哎,不要修改参数,这是一个不好的习惯,再说,参数只是一个形式参数,不会对实际参数产生变化。这个不是C指针!



这样写是为了保证con没有被关闭,最终强制把他赋值为null


看来楼主不太明白,编译器工作原理呀~

你自己想象,一个Connection够吗?建议看一下Connection Pool的原理,Apache DBCP就是简单的实现。
18 楼 悲剧了 2011-05-16  
gaosheng08 写道
悲剧了 写道
jinyao 写道
你这是单例,下次调用connection的时候当然不为空



是单例,但是调用关闭方法,把instance关闭了的,就是单例里面instance为null了,那么它会再次new一次


关闭方法中只是把数据库rs、ps、conn关闭了,但instance并不为null,要显示将instance置为null




那个close(0方法中的conn就是getConnection()得到的intance,里面已经con=null显示关闭了


17 楼 kakaluyi 2011-05-16  
悲剧了 写道
gaosheng08 写道
close()中还要加一句instance = null;


调用的时候传进来的就是instance ,这个connection是通过这个类的getConnection()得到的

lz你难道不知道java通过close方法传递进去的instance只是个引用吗,真正的instance是不会置为null的??
16 楼 gaosheng08 2011-05-16  
悲剧了 写道
jinyao 写道
你这是单例,下次调用connection的时候当然不为空



是单例,但是调用关闭方法,把instance关闭了的,就是单例里面instance为null了,那么它会再次new一次


关闭方法中只是把数据库rs、ps、conn关闭了,但instance并不为null,要显示将instance置为null
15 楼 悲剧了 2011-05-16  
gaosheng08 写道
close()中还要加一句instance = null;


调用的时候传进来的就是instance ,这个connection是通过这个类的getConnection()得到的
14 楼 悲剧了 2011-05-16  
mercyblitz 写道
悲剧了 写道
jinyao 写道
你是把connection关闭了  而不是置空



finally{ 
                con=null; 
            } 


最后有句这个代码



这代码写的,,哎,不要修改参数,这是一个不好的习惯,再说,参数只是一个形式参数,不会对实际参数产生变化。这个不是C指针!



这样写是为了保证con没有被关闭,最终强制把他赋值为null
13 楼 gaosheng08 2011-05-16  
close()中还要加一句instance = null;
12 楼 悲剧了 2011-05-16  
sswh 写道

代码真够混乱的。

本来不想回了,算了,还是说一下吧。

悲剧了 写道
public class ConnectionUtil {
	private  static Connection   instance=null;
}


这儿:instance是ConnectionUtil 类的静态变量。

悲剧了 写道
	public static void close(Connection con){
		if(con!=null){
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				con=null;
			}
		}
	}
}


这儿:close()方法中,置空的con=null,是方法参数。ConnectionUtil.instance 并没有受到影响。




调用的时候close(instance )
11 楼 kakaluyi 2011-05-16  
sswh 写道

代码真够混乱的。

本来不想回了,算了,还是说一下吧。

悲剧了 写道
public class ConnectionUtil {
	private  static Connection   instance=null;
}


这儿:instance是ConnectionUtil 类的静态变量。

悲剧了 写道
	public static void close(Connection con){
		if(con!=null){
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				con=null;
			}
		}
	}
}


这儿:close()方法中,置空的con=null,是方法参数。ConnectionUtil.instance 并没有受到影响。

这位朋友正解,你应该这样用finally{  
              ConnectionUtil.instance =null;
} ,但是如此非常怀疑你用单例模式的必要性
10 楼 mercyblitz 2011-05-16  
悲剧了 写道
jinyao 写道
你是把connection关闭了  而不是置空



finally{ 
                con=null; 
            } 


最后有句这个代码



这代码写的,,哎,不要修改参数,这是一个不好的习惯,再说,参数只是一个形式参数,不会对实际参数产生变化。这个不是C指针!
9 楼 sswh 2011-05-16  

再说点其他的:

悲剧了 写道
	public static Connection getConnection(){
		if(instance==null){
			new ConnectionUtil();
		}
		return instance;
	}


按上下文的意思,应该是:
	public static Connection getConnection(){
		if(instance==null){
			instance = DriverManager.getConnection(url, username, password);
		}
		return instance;
	}


8 楼 skzr.org 2011-05-16  
<p>兄弟直接用spring jdbctemplate吧<br><br>如果非要自己弄也试用datasource吧<br><br>如果非要connection,这样写ConnectionUtil吧:</p>
<p> </p>
<p>
</p>
<pre name="code" class="java">public class ConnectionUtil {
private final static String  url="jdbc:mysql://localhost:3306/qq?useUnicode=true&amp;characterEncoding=UTF-8";
private final static String  username="root";
private final static String  password="root";

public static Connection getConnection(){
try {
Class.forName("org.gjt.mm.mysql.Driver");
return DriverManager.getConnection(url, username, password);
} catch (Exception e) {
throw new IllegalStatusException(e);
}

}

public static void close(Connection con,PreparedStatement ps,ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
close(con);
}

public static void close(Connection con,PreparedStatement ps){
close(con, ps, null);
}

public static void close(Connection con){
if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
con=null;
}
}
}
}
</pre>
 
7 楼 sswh 2011-05-16  

代码真够混乱的。

本来不想回了,算了,还是说一下吧。

悲剧了 写道
public class ConnectionUtil {
	private  static Connection   instance=null;
}


这儿:instance是ConnectionUtil 类的静态变量。

悲剧了 写道
	public static void close(Connection con){
		if(con!=null){
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally{
				con=null;
			}
		}
	}
}


这儿:close()方法中,置空的con=null,是方法参数。ConnectionUtil.instance 并没有受到影响。
6 楼 悲剧了 2011-05-16  
jinyao 写道
你是把connection关闭了  而不是置空



finally{ 
                con=null; 
            } 


最后有句这个代码
5 楼 jinyao 2011-05-16  
你是把connection关闭了  而不是置空
4 楼 悲剧了 2011-05-16  
jinyao 写道
你这是单例,下次调用connection的时候当然不为空



是单例,但是调用关闭方法,把instance关闭了的,就是单例里面instance为null了,那么它会再次new一次
3 楼 jinyao 2011-05-16  
你这是单例,下次调用connection的时候当然不为空
2 楼 悲剧了 2011-05-16  
Reset 写道
关闭对象的次序貌似有问题。。。



次序换了,但问题依旧
1 楼 Reset 2011-05-16  
关闭对象的次序貌似有问题。。。

相关推荐

    原创的JDBC封装可支持各种数据库

    通过以上步骤,我们可以创建一个高度可配置、易于使用的JDBC封装库,支持多种数据库。在实际项目中,只需在配置文件中更改数据库相关参数,就能轻松切换到不同的数据库系统,极大地提高了代码的可维护性和可扩展性。...

    游戏服务器 数据库连接池 jdbc 简单封装

    在`nebula-jdbc-master`这个项目中,我们可以看到一个名为Nebula JDBC的实现,它可能就是对JDBC和数据库连接池的一个自定义封装。通过分析该项目的源码,我们可以学习如何自定义数据库连接池组件,如何优化JDBC的...

    jdbc-utils.rar_Utils_jdbc_jdbc封装

    这个文件很可能是封装好的一个基类,为具体的DAO(Data Access Object)提供通用的方法。可能包含以下功能: - 连接管理:自动获取和释放连接,通常会利用`PoolManager`来获取连接池中的连接。 - SQL执行:提供...

    jdbc封装的代码

    这个例子展示了如何使用封装后的JDBC工具类来执行一个查询操作,无需关心连接的创建与关闭,SQL参数的设置以及结果集的处理,大大提高了代码的可读性和易用性。这就是JDBC封装的主要目的和实现方式。

    自己写一个DAO 实现对jdbc dbcp封装 开源小组件

    本组件"自己写的一个DAO 实现对jdbc dbcp封装 开源小组件"是作者学习研究的成果,适用于小型项目,同时也是初学者了解和实践DAO设计模式、JDBC以及Apache DBCP连接池的好材料。 1. JDBC(Java Database ...

    有关于jdbc的基本封装

    JDBC是Java平台上的一个API,允许Java开发者与各种类型的数据库进行交互。它提供了一组接口和类,使得程序员可以编写数据库独立的代码,从而不必关心底层数据库的具体实现。 2. 基本CRUD操作: - 创建(Create)...

    JDBC 工具类JdbcUtils封装与测试应用(针对mysql)

    因此,JdbcUtils还可以进一步封装这些操作,例如添加一个执行SQL查询的方法: ```java // 执行SQL查询,返回结果集 public static ResultSet executeQuery(String sql) { Connection conn = getConnection(); ...

    SQL封装

    在IT行业中,SQL封装是Java开发中常见的一个实践,它能帮助我们更高效、更安全地操作数据库。本文将深入探讨“SQL封装”这一主题,尤其是对于初学者来说,掌握好这一技能对于提升JDBC(Java Database Connectivity)...

    Oracle jdbc 单例 工具类

    本示例中的"Oracle jdbc 单例 工具类"着重讨论了单例模式的应用,单例模式是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点。在数据库连接管理中,使用单例模式可以避免频繁创建和关闭连接,提高...

    sharding-jdbc按月分表样例

    【标题】"sharding-jdbc按月分表样例"是一个关于使用Sharding-JDBC进行数据库分片的示例项目,旨在展示如何根据月份动态地将数据分散到不同的表中,以实现数据的水平扩展和负载均衡。Sharding-JDBC是阿里巴巴开源的...

    spring+jdbc整合

    "spring+jdbc整合"是一个常见的话题,尤其对于初学者而言,理解这两者的结合是提升开发效率的关键。下面我们将详细探讨Spring如何与JDBC进行整合,以及这种整合在实际项目中的应用。 首先,Spring框架通过其JDBC...

    JDBC知识点总结

    所有对数据库的操作都需要在一个有效的连接上进行。 3. **Statement**:用于执行 SQL 语句,并获取执行结果。 4. **ResultSet**:存储 SQL 查询结果的集合,通常被视为一张虚拟表。 #### 三、JDBC 的准备工作 1. *...

    SpringJDBC注解事务.zip

    Spring JDBC提供了一个JdbcTemplate类,它封装了常见的JDBC操作,如执行SQL查询、更新、调用存储过程等,减少了代码量和出错的可能性。此外,它还处理了诸如打开和关闭连接、结果集遍历等繁琐任务。 2. **注解驱动...

    JDBC数据库访问工具类 强大 精巧 高效

    总结来说,一个强大的JDBC数据库访问工具类是Java项目中必不可少的一部分,它通过封装和优化JDBC操作,降低了开发难度,提高了代码的可读性和维护性,同时提升了系统的运行效率。在设计和实现这样的工具类时,我们...

    jdbc分页查询源码

    在给定的源码中,可能包含了一个封装好的分页查询工具类,这个类通常会有以下方法: - `queryByPage(Connection conn, String sql, int pageNum, int pageSize)`:接收数据库连接、基础SQL语句以及分页参数,返回...

    Spring与JDBC整合

    - 在执行SQL时,需要提供一个Map或SqlParameterSource对象来传递参数值。 3. **事务管理**: - Spring提供了PlatformTransactionManager接口,如DataSourceTransactionManager,用于管理事务。 - 可以使用@...

    JDBC学习笔记

    - 将每条记录封装为一个Map,然后存储到List中。 #### 二十五、Java反射技术入门 - **概念**:反射是在运行时分析类和对象的能力。 - **应用**:使用反射技术根据结果集元数据动态创建Java对象,实现查询结果的...

    效率很高的java jdbc类

    2. **迭代器模式**:提供一个迭代器接口,使得遍历结果集更加灵活且节省内存,避免一次性加载所有数据导致内存溢出。 3. **类型转换**:根据需要自动将数据库中的值转换为适当的Java类型,例如将字符串转换为日期、...

    JSP+JDBC_假分页

    - **传递数据到JSP**:将ResultSet封装到一个集合对象(如ArrayList),然后通过请求转发或者模型视图适配器(MVC)模式传递到JSP页面。 - **JSP页面处理**:在JSP页面上,使用JavaScript或者jQuery等前端技术,...

    JDBC代码详解.docx

    JDBC的接口由数据库提供商实现,这意味着只要有一个支持JDBC的驱动程序,就可以使用相同的Java代码来访问不同的数据库。 #### JDBC入门案例详解 ##### 1.2.1 流程分析 假设我们的需求是查询数据库中的数据并在...

Global site tag (gtag.js) - Google Analytics