站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2EE 专题【经典】请问一个关于j2ee数据库操作的问题【经典】

【经典】请问一个关于j2ee数据库操作的问题【经典】

摘要: 【经典】请问一个关于j2ee数据库操作的问题【经典】


之所以【经典】是因为这确实是一个新手常见的错误,所以请各位高手门支招!
各位大大,你们好,我是一新手,我有个数据库操作的类DBOperation,有两种写法,我不知道那种好,请各位指教!

注:Pool类的静态方法getConnection()封装了如何在Tomcat连接池中取连接的过程.

方法一:
import java.sql.*;
import cndb.Pool;

class DBOperation{
Connection conn;
Statement stat;
ResultSet rs;

public DBOperation(){
conn = Pool.getConnection();
}

public void executeUpdate(String sql){
try{
stat = conn.createStatement();
rs = stat.executeUpdate(sql);
}catch(SQLException e){}
finally{
if(rs!=null)
try{ rs.close }catch(SQLException e){}
if(stat!=null)
try{ stat.close }catch(SQLException e){}
if(conn!=null)
try{ conn.close }catch(SQLException e){}
}
}
}
-----------------------------------------------------------------

方法二:
import java.sql.*;
import cndb.Pool;

class DBOperation{
public DBOperation(){
conn = Pool.getConnection();
}

public void executeUpdate(String sql){
Connection conn = Pool.getConnection();
try{
Statement stat = conn.createStatement();
ResultSet rs = stat.executeUpdate(sql);
}catch(SQLException e){}
finally{
close();
}
}

public void close(){
if(rs!=null)
try{ rs.close }catch(SQLException e){}
if(stat!=null)
try{ stat.close }catch(SQLException e){}
if(conn!=null)
try{ conn.close }catch(SQLException e){}
}
}

上面两个方法效率高啊?哪个更加安全呢? 安全是指数据库能够保证关闭.不会出现内存益出!
我现在很苦恼,刚刚学习JSP,帮学校做了个网站,经常出现404错误,就是数据库出问题那个NullPointerException异常,只能重启Tomcat才能解决,但是过了几天有出问题了,又要重启.用了连接池子还是一样,我想,肯定是我程序写法有问题,所以请高手们不啬赐教,我定当虚心学习!谢谢了!!


你的代码一看确实是个新手写的,漏洞很多。
我有点纳闷,你这两个类能用?执行一些个增加和修改方法应该不会有很大问题,但是你的方法要执行个查询的话,executeUpdate方法都没有返回值,记录集刚获得值就被关掉了,有什么意义?,再说第二个类你应该丢掉了一个定义conn、stat、rs,你的构造函数里的conn是哪来的,?没见到你定义,要是定义,应该和第一个类里一样定义在类的作用域,但是你在executeUpdate方法里又重新定义了一个作用域在executeUpdate方法内部的conn,很显然两个conn是拿了两个连接,而你最后释放的时候肯定只是释放的是类作用域的conon,所以你在方法executeUpdate里定义的conn,stat,rs都没有释放掉。

说实话让我从你这两个类里挑一个说哪个好,我还真挑不出来。相对来说第一个比第二个漏洞错误少一些。


/**
* 本类是数据库连接的管理类,因此在整个系统中没有必要出现多个,一个就够用了
* 因此,决定在此类上使用单态设计模式,只提供本类的一个实例出去。
* 在此我是用单态的饿汉模式进行使用
*/
public class DBConnectionManager {
private static Logger logger=Logger.getLogger(DBConnectionManager.class.getName());
/**
* 本静态变量用来存放本系统启动时由Struts生成的连接池的数据源
*/
private static DataSource datasource;
/**
* 由于本类使用单态设计模式,因此不允许在使用中通过New进行实例化,那么本类就要提供一个
* 此类的实例供外界使用,这就是供外界使用的实例
*/
private static DBConnectionManager dbConManager=new DBConnectionManager();
private DBConnectionManager(){}
/**
* 此静态方法用来向类的静态变量赋值,用来在系统中使用
* @param mydatasource 传入的struts生成的数据源
*/
public static void setDatasource(DataSource mydatasource) {
logger.info("设置数据源");
if(datasource==null){
datasource = mydatasource;
}
}
/**
* 由于本类使用单态模式,不允许其他的类使用New进行创建实例
* 因此在这里提供一个共有的静态方法来向外界提供自己的一个实例。
* @return 返回本类的唯一实例
*/
public static DBConnectionManager getInstance() {
logger.info("获得数据库连接管理类的实例");
return dbConManager;
}
/**
* 此方法提供一个可用的数据库连接,从连接池中取得可用连接
* @return 可用的数据库连接
*/
public Connection getConnection() {
Connection conn = null;
try {
logger.info("从连接池中获得空闲的数据库连接");
conn = datasource.getConnection();
return conn;
}
catch (SQLException ex) {
ex.printStackTrace();
return null;
}
}
/**
* 这是一个用来关闭所有的数据库连接相关的打开对象的方法,这样作的好处是不用在每一次调用了sql之后
* 要写一大串的关闭操作。
* @param conn 将要关闭的数据库连接
* @param st 将要关闭的数据库操作对象
* @param pst 将要关闭的预处理数据库操作对象
* @param cst 将要关闭的数据库存储过程调用对象
* @param rst 将要关闭的数据库记录集对象
* @throws java.lang.Exception 有可能要抛出的异常
*/
public void closeAll(Connection conn,Statement st,PreparedStatement pst,CallableStatement cst,ResultSet rst)
throws Exception{
if(conn!=null){
conn.close();
}
if(st!=null){
st.close();
}
if(pst!=null){
pst.close();
}
if(cst!=null){
cst.close();
}
if(rst!=null){
rst.close();
}
}
}


我写的一个数据库连接管理类,用单态写的,看看吧。。。嘿嘿
LZ还需努力学习


好的,谢谢,正在研究您的例子中....


深蓝忧郁: 怎么想到用单态了?强悍!!!

欢迎大家加入:JAVA开发工程师QQ群 14672911 :在这里都用JAVA开发工程师白领族...

上班的时候讨论技术问题,下班的时候可以谈事业,心思等等(闲人或者是打广告的人免进)



lip009(深蓝忧郁)
你的也不咋样 不需要这么说别人。
没有必要以为自己很厉害。
无聊否,你的例子里面错误好象也不少。



lip009(深蓝忧郁) : 是单子模式吧。。。
说的那么怪异。。
哎。。怎么说你。。J2EE开发中是强烈不建议使用单子模式的。
你考虑过线程并发这些问题么?

PS:设计模式有很多,单子模式是最简单的一种。。


多线程并发。。

最好的处理方式就是用单例,不过一定要是无状态的。


不知道是我无聊,还是6楼、7楼的两位仁兄无聊!呵呵。。。至于我的代码里的错误,还希望6楼的兄弟指出!
而对于线程并发,我想我的类是没有问题的!希望7类的兄弟再仔细研究研究再做讨论!


lip009(深蓝忧郁) ,确实感觉你的代码不怎么好,如果你是随便敲的还可以说的过去,如果这就是你平时使用过很久的东西....

我感觉getConnection()方法在得不到数据库连接时应抛出异常


to vvpang(NullPointerException)
老兄写EJB的吧,怎么连无状态都用上了。。呵呵,不会指的是无状态Session Bean吧 呵呵



to lip009(深蓝忧郁)
呵呵 不好意思,I'M WORKING TIME NOW~不过我觉得实在不必为了写了个一个连接池而沾沾自喜。


写一个单态的来处理获取连接的和关闭资源的类。

建议用DbUtils这个工具类。
要不就自己封装DAO的操作类。


to chnic(挠痒痒)
楼上的,我还没有实力写个连接池!我写的只是个简单的连接管理类!我更搞不懂我什么地方让你看出来我很沾沾自喜!我就很纳闷!


帮人回答个问题怎么就有这么多无聊的人!我就很不爽,没见一个给解决问题的!就知道在这说三道四!


天下居然就有免费的午餐
-------梦网科技暑期系列优惠促销活动通知
梦网科技公司是一家面向政府,企事业和行业专业提供移动信息化和移动商务产品和服务的高科技企业,成立至今,秉持“以人为本,品质成就未来,以客为尊,服务创造价值”的理念,已提出了一系列移动商务的行业解决方案,并在全国设立了80多个营销服务机构,为更好的回馈用户,经公司认真研究,特面向新老客户推出一系列暑期优惠促销活动,并期待您的参与。活动时间为2006年7月1到8月31日。
优惠一:梦网双向客服短信平台免费接入活动
梦网科技是一家拥有信息产业部颁发的全网电信运营资质的企业,拥有覆盖全国四网合一的双向客服短信平台,能同时支持中国移动,中国联通,中国电信,中国网通的移动电话和小灵通用户。能提供发送信息同步实时的状态报告。能为企业提供全国唯一专用的双向企业短信服务号码。企业只需一个电话,一天之内就能构建属于自己的双向客服短信网关。
优惠二:免费提供全网唯一企业专用短信服务号,首号充值2000元免费获取,次号开始充值短信1500元即可免费获取。多买多送,不限数量。凡单个企业拥有5个以上企业短信服务号码的,我公司免费提供管理软件和管理帐号,企业可自行对下属短信号码进行充值管理。
优惠三:凡一次性充值在1万元以上的企业用户,除享受上两项优惠外,我公司还免费赠送无线短信收发设备一套,全网的网关对本地卡和小灵通的上行有些地区会有一些限制,而企业也有些信息是希望能私密的传送。我们提供的无线设备可以短信收发变得更加通畅和安全。
优惠四:对一次性充值在5000元以上的企业用户,我公司可免费提供自定义OEM企业双向短信客户端,企业可自行修改添加自己的企业名称和标记。
优惠五:短信充值大优惠:凡一次性充值短信在2000元以上的,除以上优惠外,短信也有赠送哦!充2000元送2%的短信,充5000元送5%,充10000元及以上更送10%,优惠多多,赶紧参与吧。
本活动解释权属梦网科技公司
详情请咨询:020—87601860 13711762400 MSN:dj_1413@hotmail.com
联系人:窦建 QQ;114126326



public void closeAll(Connection conn,Statement st,PreparedStatement pst,CallableStatement cst,ResultSet rst)



这里面的关闭顺序应该是先 ResultSet ,然后是Statement ,最后才是Connection 吧?


对,关闭顺序就有误.

这样的操作还要写个方法,传几个参数进来吗?能说说你的用意吗?

为什么不写在finally里头呢?


我顶


现在大家用stuts和hoibrenate多吗


嗯,应该是我一时疏忽,顺序是有问题!直接从以前做的拷过来的!不过当时竟然没出问题!纳闷中。。。

to Aqiu_Schema(路独行) :

你还是没看明白,我这只是个管理类!它自己是不使用连接的,当然也就不能自己关闭了!使用连接的是数据层的数据操作类!这些关闭是由他们来调用的!而在数据操作类里肯定是写在finally{}里边的。


这个单态模式写得也不怎么样,误人子弟


to: lip009(深蓝忧郁)
今天看了你的程序,原以为是连接池,原来不是,首先想告诉你,你引以为傲的的单子模式用的真的不怎么样。告诉你别人一般做开发是怎么写的吧。
public class Temp {
private static Temp t = null;
private Temp(){}
public static Temp getInstance(){
if(t==null)
t = new Temp();
return t;

}
}
有空多去看点设计模式吧,再去了解下需求看看到底有多少人在J2EE开发中用单子模式。

其次想告诉你 你要是真的是搞J2EE开发的 我想你不会不知道 究竟有多少公司的架构用的是Struts里的数据源?谁会吧DAO层的用的数据源放到表现层里?简直胡扯!除非你是两三个人的那种皮包公司 JSP里写脚本的那种,那我没话说。

再次想告诉你,你的程序除了刚刚上面兄弟指除的错误,我想问你几个问题,1.假如你的连接池里没有连接了,你是选择抛出一个自定义Exception还是一个NULL??荒唐。。
2.假如我拿了一个连接一直在用 比如上传东西 用了2个钟头,一直没还。你上面的NB程序怎么处理的?你考虑过内存溢出的情况么?

最后想问你什么是说三道四的人?嘴张到我们身上还不准我们用是不?多去看看书看看设计模式吧,代理、动态代理、抽象工厂、工厂方法、命令模式,观察者模式、装饰者模式就这些你能写出来几个??




to chnic(挠痒痒)
贴子讨论到这里已经很经典了,我在来个锦上添花。希望大家多指点。
单态,就是保证你的类在内存里只有一个,但你的类在内存里只有一个。你们上面写的基本实现了。但你还得保证你的类里的方法在同一时间只有一个客户端用,所以你要
public class Temp {
private static Temp t = null;
private Temp(){}
public “synchronized” static Temp getInstance(){

}
}
看到synchronized 关键字了吗?这个是保证同步用的。

希望我的发言 ,大家不要反感。
如果有疑问请大家跟贴。



to chnic(挠痒痒) ( ) :
首先告诉你,我从来没有以此为豪过,这只是做一个程序员最基本该会的东西。

还想告诉你的是
public class Temp {
private static Temp t = null;
private Temp(){}
public static Temp getInstance(){
if(t==null)
t = new Temp();
return t;

}
}
你这段代码也是单态模式,只不过是单态的一种懒汉模式,这种比我那种更有一点好处是再使用连接的时候才去创建这个类唯一的实例!只不过两种实现方法的使用要看用在什么样的场合。而对我的项目我觉得更适合用饿汉模式!

再想告诉你,我把我的类贴出来只不过想让楼住多学点东西。当然我的不是权威,有错误很正常,谁也不敢保证自己写的程序是最完美的!至少我还没有这资格!所以谁都可以取其精华,弃其糟粕!至少我觉得楼主可以从中学到东西!

还有至于我懂不懂23种经典设计模式,我想我没有必要在这里跟你叫板!没有那个必要!因为在这里其他的设计模式根本用不上,至少我这么认为!我来这里只不过为了提高自己的同时帮助别人!所以我倒是瞒感谢这么多人找出我代码中的不足之处!让我也有所提高!


to j2ee_wangdawei():

这位仁兄说的很正确!


楼主好象已经销声匿迹了,而我则成了众矢之的!^_^


to: j2ee_wangdawei()
老兄所言即是。受教了。呵呵。


继续继续。。。同志们继续关注。。。HOHOHO


两人行必有我师~~
什么高手不高手的
一起学习进步么~~
CODING没有年限的区分
要看自己的思维模式和创新意识



9494
革命尚未成功,同志们继续努力!


单态与多态的使用应区分不同的运行环境吧
一个简单的连接
初始化
建立连接
使用
关闭
无非这几步,至于细节上的控制要看你系统对每个环节的处理模式~~
在性能的优化上到可以多借鉴一下上面的高手的形式


mark


UP



to lip009(深蓝忧郁)
to chnic(挠痒痒)
有好的想法一起分享,这是原则。
单态也就这点东西了
。咱们在讨论个门户模式,听说最近比较火 的jsf就用的这个模式。
兄弟们有自己的思想精华,不妨也让我学学。


↑返回目录
前一篇: jsp页面出错,Cannot find bean ComList in any scope
后一篇: 有关websphere+myeclipse+eclipse环境下ejb开发的问题